github.com/koko1123/flow-go-1@v0.29.6/engine/execution/state/bootstrap/bootstrap.go (about) 1 package bootstrap 2 3 import ( 4 "errors" 5 "fmt" 6 7 "github.com/dgraph-io/badger/v3" 8 "github.com/rs/zerolog" 9 10 "github.com/koko1123/flow-go-1/engine/execution/state" 11 "github.com/koko1123/flow-go-1/engine/execution/state/delta" 12 "github.com/koko1123/flow-go-1/fvm" 13 "github.com/koko1123/flow-go-1/ledger" 14 "github.com/koko1123/flow-go-1/model/flow" 15 "github.com/koko1123/flow-go-1/storage" 16 "github.com/koko1123/flow-go-1/storage/badger/operation" 17 ) 18 19 // an increased limit for bootstrapping 20 const ledgerIntractionLimitNeededForBootstrapping = 1_000_000_000 21 22 type Bootstrapper struct { 23 logger zerolog.Logger 24 } 25 26 func NewBootstrapper(logger zerolog.Logger) *Bootstrapper { 27 return &Bootstrapper{ 28 logger: logger, 29 } 30 } 31 32 // BootstrapLedger adds the above root account to the ledger and initializes execution node-only data 33 func (b *Bootstrapper) BootstrapLedger( 34 ledger ledger.Ledger, 35 servicePublicKey flow.AccountPublicKey, 36 chain flow.Chain, 37 opts ...fvm.BootstrapProcedureOption, 38 ) (flow.StateCommitment, error) { 39 view := delta.NewView(state.LedgerGetRegister(ledger, flow.StateCommitment(ledger.InitialState()))) 40 41 vm := fvm.NewVirtualMachine() 42 43 ctx := fvm.NewContext( 44 fvm.WithLogger(b.logger), 45 fvm.WithMaxStateInteractionSize(ledgerIntractionLimitNeededForBootstrapping), 46 fvm.WithChain(chain), 47 ) 48 49 bootstrap := fvm.Bootstrap( 50 servicePublicKey, 51 opts..., 52 ) 53 54 err := vm.Run(ctx, bootstrap, view) 55 if err != nil { 56 return flow.DummyStateCommitment, err 57 } 58 59 newStateCommitment, _, err := state.CommitDelta(ledger, view.Delta(), flow.StateCommitment(ledger.InitialState())) 60 if err != nil { 61 return flow.DummyStateCommitment, err 62 } 63 64 return newStateCommitment, nil 65 } 66 67 // IsBootstrapped returns whether the execution database has been bootstrapped, if yes, returns the 68 // root statecommitment 69 func (b *Bootstrapper) IsBootstrapped(db *badger.DB) (flow.StateCommitment, bool, error) { 70 var commit flow.StateCommitment 71 72 err := db.View(func(txn *badger.Txn) error { 73 err := operation.LookupStateCommitment(flow.ZeroID, &commit)(txn) 74 if err != nil { 75 return fmt.Errorf("could not lookup state commitment: %w", err) 76 } 77 78 return nil 79 }) 80 81 if errors.Is(err, storage.ErrNotFound) { 82 return flow.DummyStateCommitment, false, nil 83 } 84 85 if err != nil { 86 return flow.DummyStateCommitment, false, err 87 } 88 89 return commit, true, nil 90 } 91 92 func (b *Bootstrapper) BootstrapExecutionDatabase(db *badger.DB, commit flow.StateCommitment, genesis *flow.Header) error { 93 94 err := operation.RetryOnConflict(db.Update, func(txn *badger.Txn) error { 95 96 err := operation.InsertExecutedBlock(genesis.ID())(txn) 97 if err != nil { 98 return fmt.Errorf("could not index initial genesis execution block: %w", err) 99 } 100 101 err = operation.IndexStateCommitment(flow.ZeroID, commit)(txn) 102 if err != nil { 103 return fmt.Errorf("could not index void state commitment: %w", err) 104 } 105 106 err = operation.IndexStateCommitment(genesis.ID(), commit)(txn) 107 if err != nil { 108 return fmt.Errorf("could not index genesis state commitment: %w", err) 109 } 110 111 views := make([]*delta.Snapshot, 0) 112 err = operation.InsertExecutionStateInteractions(genesis.ID(), views)(txn) 113 if err != nil { 114 return fmt.Errorf("could not bootstrap execution state interactions: %w", err) 115 } 116 117 return nil 118 }) 119 120 if err != nil { 121 return err 122 } 123 124 return nil 125 }