@@ -21,6 +21,7 @@ import (
2121	"fmt" 
2222	"io" 
2323	"os" 
24+ 	"reflect" 
2425	"runtime" 
2526	"strconv" 
2627	"sync/atomic" 
@@ -56,6 +57,20 @@ The init command initializes a new genesis block and definition for the network.
5657This is a destructive action and changes the network in which you will be 
5758participating. 
5859
60+ It expects the genesis file as argument.` ,
61+ 	}
62+ 	updateCommand  =  cli.Command {
63+ 		Action :    utils .MigrateFlags (updateTransitions ),
64+ 		Name :      "update" ,
65+ 		Usage :     "Update genesis block with new transitions" ,
66+ 		ArgsUsage : "<genesisPath>" ,
67+ 		Flags : []cli.Flag {
68+ 			utils .DataDirFlag ,
69+ 		},
70+ 		Category : "BLOCKCHAIN COMMANDS" ,
71+ 		Description : ` 
72+ The update commands updates the chain data configuration in genesis block for new transition changes. 
73+ 
5974It expects the genesis file as argument.` ,
6075	}
6176	dumpGenesisCommand  =  cli.Command {
@@ -206,6 +221,64 @@ func getIsQuorum(file io.Reader) bool {
206221	return  altGenesis .Config .IsQuorum  ==  nil  ||  * altGenesis .Config .IsQuorum 
207222}
208223
224+ // updateTransitions will update genesis block with the new transitions data 
225+ func  updateTransitions (ctx  * cli.Context ) error  {
226+ 	// Open and initialise both full and light databases 
227+ 	stack , _  :=  makeConfigNode (ctx )
228+ 	defer  stack .Close ()
229+ 
230+ 	// Make sure we have a valid genesis JSON 
231+ 	genesisPath  :=  ctx .Args ().First ()
232+ 	if  len (genesisPath ) ==  0  {
233+ 		utils .Fatalf ("Must supply path to genesis JSON file" )
234+ 	}
235+ 	file , err  :=  os .Open (genesisPath )
236+ 	if  err  !=  nil  {
237+ 		utils .Fatalf ("Failed to read genesis file: %v" , err )
238+ 	}
239+ 	defer  file .Close ()
240+ 
241+ 	genesis  :=  new (core.Genesis )
242+ 	if  err  :=  json .NewDecoder (file ).Decode (genesis ); err  !=  nil  {
243+ 		utils .Fatalf ("invalid genesis file: %v" , err )
244+ 	}
245+ 
246+ 	// Quorum 
247+ 	file .Seek (0 , 0 )
248+ 	genesis .Config .IsQuorum  =  getIsQuorum (file )
249+ 
250+ 	if  genesis .Config .IsQuorum  {
251+ 		err  =  genesis .Config .CheckTransitionsData ()
252+ 		if  err  !=  nil  {
253+ 			utils .Fatalf ("transitions data invalid: %v" , err )
254+ 		}
255+ 	} else  {
256+ 		return  fmt .Errorf ("update transitions only apply to quorum configuration" )
257+ 	}
258+ 
259+ 	// Update transitions and recommit to db 
260+ 	for  _ , name  :=  range  []string {"chaindata" , "lightchaindata" } {
261+ 		chaindb , err  :=  stack .OpenDatabase (name , 0 , 0 , "" , false )
262+ 		if  err  !=  nil  {
263+ 			utils .Fatalf ("Failed to open database: %v" , err )
264+ 		}
265+ 		stored  :=  rawdb .ReadCanonicalHash (chaindb , 0 )
266+ 		storedcfg  :=  rawdb .ReadChainConfig (chaindb , stored )
267+ 		if  storedcfg  ==  nil  {
268+ 			return  fmt .Errorf ("found genesis block without chain config" )
269+ 		}
270+ 		// Check that new transitions have changed before updating them 
271+ 		if  ! reflect .DeepEqual (storedcfg .Transitions , genesis .Config .Transitions ) {
272+ 			log .Info ("Change found in transitions, proceeding to update chain config" )
273+ 			storedcfg .Transitions  =  genesis .Config .Transitions 
274+ 		} else  {
275+ 			log .Info ("No change in transitions, no update required to chain config" )
276+ 		}
277+ 		rawdb .WriteChainConfig (chaindb , stored , storedcfg )
278+ 	}
279+ 	return  nil 
280+ }
281+ 
209282// initGenesis will initialise the given JSON format genesis file and writes it as 
210283// the zero'd block (i.e. genesis) or will fail hard if it can't succeed. 
211284func  initGenesis (ctx  * cli.Context ) error  {
0 commit comments