@@ -21,6 +21,7 @@ import (
21
21
"fmt"
22
22
"io"
23
23
"os"
24
+ "reflect"
24
25
"runtime"
25
26
"strconv"
26
27
"sync/atomic"
@@ -56,6 +57,20 @@ The init command initializes a new genesis block and definition for the network.
56
57
This is a destructive action and changes the network in which you will be
57
58
participating.
58
59
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
+
59
74
It expects the genesis file as argument.` ,
60
75
}
61
76
dumpGenesisCommand = cli.Command {
@@ -206,6 +221,64 @@ func getIsQuorum(file io.Reader) bool {
206
221
return altGenesis .Config .IsQuorum == nil || * altGenesis .Config .IsQuorum
207
222
}
208
223
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
+ rawdb .WriteChainConfig (chaindb , stored , storedcfg )
275
+ } else {
276
+ log .Info ("No change in transitions, no update required to chain config" )
277
+ }
278
+ }
279
+ return nil
280
+ }
281
+
209
282
// initGenesis will initialise the given JSON format genesis file and writes it as
210
283
// the zero'd block (i.e. genesis) or will fail hard if it can't succeed.
211
284
func initGenesis (ctx * cli.Context ) error {
0 commit comments