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  }