github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/integration/makegenesis/genesis.go (about)

     1  package makegenesis
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"io"
     7  	"math/big"
     8  
     9  	"github.com/unicornultrafoundation/go-u2u/common"
    10  	"github.com/unicornultrafoundation/go-u2u/core/state"
    11  	"github.com/unicornultrafoundation/go-u2u/core/types"
    12  	"github.com/unicornultrafoundation/go-u2u/rlp"
    13  
    14  	"github.com/unicornultrafoundation/go-helios/hash"
    15  	"github.com/unicornultrafoundation/go-helios/u2udb"
    16  	"github.com/unicornultrafoundation/go-u2u/evmcore"
    17  	"github.com/unicornultrafoundation/go-u2u/gossip/blockproc"
    18  	"github.com/unicornultrafoundation/go-u2u/gossip/blockproc/drivermodule"
    19  	"github.com/unicornultrafoundation/go-u2u/gossip/blockproc/eventmodule"
    20  	"github.com/unicornultrafoundation/go-u2u/gossip/blockproc/evmmodule"
    21  	"github.com/unicornultrafoundation/go-u2u/gossip/blockproc/sealmodule"
    22  	"github.com/unicornultrafoundation/go-u2u/gossip/evmstore"
    23  	"github.com/unicornultrafoundation/go-u2u/native"
    24  	"github.com/unicornultrafoundation/go-u2u/native/iblockproc"
    25  	"github.com/unicornultrafoundation/go-u2u/native/ibr"
    26  	"github.com/unicornultrafoundation/go-u2u/native/ier"
    27  	"github.com/unicornultrafoundation/go-u2u/u2u"
    28  	"github.com/unicornultrafoundation/go-u2u/u2u/genesis"
    29  	"github.com/unicornultrafoundation/go-u2u/u2u/genesisstore"
    30  	"github.com/unicornultrafoundation/go-u2u/utils/iodb"
    31  )
    32  
    33  type GenesisBuilder struct {
    34  	dbs u2udb.DBProducer
    35  
    36  	tmpEvmStore *evmstore.Store
    37  	tmpStateDB  *state.StateDB
    38  
    39  	totalSupply *big.Int
    40  
    41  	blocks       []ibr.LlrIdxFullBlockRecord
    42  	epochs       []ier.LlrIdxFullEpochRecord
    43  	currentEpoch ier.LlrIdxFullEpochRecord
    44  }
    45  
    46  type BlockProc struct {
    47  	SealerModule     blockproc.SealerModule
    48  	TxListenerModule blockproc.TxListenerModule
    49  	PreTxTransactor  blockproc.TxTransactor
    50  	PostTxTransactor blockproc.TxTransactor
    51  	EventsModule     blockproc.ConfirmedEventsModule
    52  	EVMModule        blockproc.EVM
    53  }
    54  
    55  func DefaultBlockProc() BlockProc {
    56  	return BlockProc{
    57  		SealerModule:     sealmodule.New(),
    58  		TxListenerModule: drivermodule.NewDriverTxListenerModule(),
    59  		PreTxTransactor:  drivermodule.NewDriverTxPreTransactor(),
    60  		PostTxTransactor: drivermodule.NewDriverTxTransactor(),
    61  		EventsModule:     eventmodule.New(),
    62  		EVMModule:        evmmodule.New(),
    63  	}
    64  }
    65  
    66  func (b *GenesisBuilder) GetStateDB() *state.StateDB {
    67  	if b.tmpStateDB == nil {
    68  		tmpEvmStore := evmstore.NewStore(b.dbs, evmstore.LiteStoreConfig())
    69  		b.tmpStateDB, _ = tmpEvmStore.StateDB(hash.Zero)
    70  	}
    71  	return b.tmpStateDB
    72  }
    73  
    74  func (b *GenesisBuilder) AddBalance(acc common.Address, balance *big.Int) {
    75  	b.tmpStateDB.AddBalance(acc, balance)
    76  	b.totalSupply.Add(b.totalSupply, balance)
    77  }
    78  
    79  func (b *GenesisBuilder) SetCode(acc common.Address, code []byte) {
    80  	b.tmpStateDB.SetCode(acc, code)
    81  }
    82  
    83  func (b *GenesisBuilder) SetNonce(acc common.Address, nonce uint64) {
    84  	b.tmpStateDB.SetNonce(acc, nonce)
    85  }
    86  
    87  func (b *GenesisBuilder) SetStorage(acc common.Address, key, val common.Hash) {
    88  	b.tmpStateDB.SetState(acc, key, val)
    89  }
    90  
    91  func (b *GenesisBuilder) AddBlock(br ibr.LlrIdxFullBlockRecord) {
    92  	b.blocks = append(b.blocks, br)
    93  }
    94  
    95  func (b *GenesisBuilder) AddEpoch(er ier.LlrIdxFullEpochRecord) {
    96  	b.epochs = append(b.epochs, er)
    97  }
    98  
    99  func (b *GenesisBuilder) SetCurrentEpoch(er ier.LlrIdxFullEpochRecord) {
   100  	b.currentEpoch = er
   101  }
   102  
   103  func (b *GenesisBuilder) TotalSupply() *big.Int {
   104  	return b.totalSupply
   105  }
   106  
   107  func (b *GenesisBuilder) CurrentHash() hash.Hash {
   108  	er := b.epochs[len(b.epochs)-1]
   109  	return er.Hash()
   110  }
   111  
   112  func NewGenesisBuilder(dbs u2udb.DBProducer) *GenesisBuilder {
   113  	tmpEvmStore := evmstore.NewStore(dbs, evmstore.LiteStoreConfig())
   114  	statedb, _ := tmpEvmStore.StateDB(hash.Zero)
   115  	return &GenesisBuilder{
   116  		dbs:         dbs,
   117  		tmpEvmStore: tmpEvmStore,
   118  		tmpStateDB:  statedb,
   119  		totalSupply: new(big.Int),
   120  	}
   121  }
   122  
   123  type dummyHeaderReturner struct {
   124  }
   125  
   126  func (d dummyHeaderReturner) GetHeader(common.Hash, uint64) *evmcore.EvmHeader {
   127  	return &evmcore.EvmHeader{}
   128  }
   129  
   130  func (b *GenesisBuilder) ExecuteGenesisTxs(blockProc BlockProc, genesisTxs types.Transactions) error {
   131  	bs, es := b.currentEpoch.BlockState.Copy(), b.currentEpoch.EpochState.Copy()
   132  
   133  	blockCtx := iblockproc.BlockCtx{
   134  		Idx:     bs.LastBlock.Idx + 1,
   135  		Time:    bs.LastBlock.Time + 1,
   136  		Atropos: hash.Event{},
   137  	}
   138  
   139  	sealer := blockProc.SealerModule.Start(blockCtx, bs, es)
   140  	sealing := true
   141  	txListener := blockProc.TxListenerModule.Start(blockCtx, bs, es, b.tmpStateDB)
   142  	evmProcessor := blockProc.EVMModule.Start(blockCtx, b.tmpStateDB, dummyHeaderReturner{}, func(l *types.Log) {
   143  		txListener.OnNewLog(l)
   144  	}, es.Rules, es.Rules.EvmChainConfig([]u2u.UpgradeHeight{
   145  		{
   146  			Upgrades: es.Rules.Upgrades,
   147  			Height:   0,
   148  		},
   149  	}))
   150  
   151  	// Execute genesis transactions
   152  	evmProcessor.Execute(genesisTxs)
   153  	bs = txListener.Finalize()
   154  
   155  	// Execute pre-internal transactions
   156  	preInternalTxs := blockProc.PreTxTransactor.PopInternalTxs(blockCtx, bs, es, sealing, b.tmpStateDB)
   157  	evmProcessor.Execute(preInternalTxs)
   158  	bs = txListener.Finalize()
   159  
   160  	// Seal epoch if requested
   161  	if sealing {
   162  		sealer.Update(bs, es)
   163  		bs, es = sealer.SealEpoch()
   164  		txListener.Update(bs, es)
   165  	}
   166  
   167  	// Execute post-internal transactions
   168  	internalTxs := blockProc.PostTxTransactor.PopInternalTxs(blockCtx, bs, es, sealing, b.tmpStateDB)
   169  	evmProcessor.Execute(internalTxs)
   170  
   171  	evmBlock, skippedTxs, receipts := evmProcessor.Finalize()
   172  	for _, r := range receipts {
   173  		if r.Status == 0 {
   174  			return errors.New("genesis transaction reverted")
   175  		}
   176  	}
   177  	if len(skippedTxs) != 0 {
   178  		return errors.New("genesis transaction is skipped")
   179  	}
   180  	bs = txListener.Finalize()
   181  	bs.FinalizedStateRoot = hash.Hash(evmBlock.Root)
   182  
   183  	bs.LastBlock = blockCtx
   184  
   185  	prettyHash := func(root hash.Hash) hash.Event {
   186  		e := native.MutableEventPayload{}
   187  		// for nice-looking ID
   188  		e.SetEpoch(es.Epoch)
   189  		e.SetLamport(1)
   190  		// actual data hashed
   191  		e.SetExtra(root[:])
   192  
   193  		return e.Build().ID()
   194  	}
   195  	receiptsStorage := make([]*types.ReceiptForStorage, len(receipts))
   196  	for i, r := range receipts {
   197  		receiptsStorage[i] = (*types.ReceiptForStorage)(r)
   198  	}
   199  	// add block
   200  	b.blocks = append(b.blocks, ibr.LlrIdxFullBlockRecord{
   201  		LlrFullBlockRecord: ibr.LlrFullBlockRecord{
   202  			Atropos:  prettyHash(bs.FinalizedStateRoot),
   203  			Root:     bs.FinalizedStateRoot,
   204  			Txs:      evmBlock.Transactions,
   205  			Receipts: receiptsStorage,
   206  			Time:     blockCtx.Time,
   207  			GasUsed:  evmBlock.GasUsed,
   208  		},
   209  		Idx: blockCtx.Idx,
   210  	})
   211  	// add epoch
   212  	b.currentEpoch = ier.LlrIdxFullEpochRecord{
   213  		LlrFullEpochRecord: ier.LlrFullEpochRecord{
   214  			BlockState: bs,
   215  			EpochState: es,
   216  		},
   217  		Idx: es.Epoch,
   218  	}
   219  	b.epochs = append(b.epochs, b.currentEpoch)
   220  
   221  	return b.tmpEvmStore.Commit(bs.LastBlock.Idx, bs.FinalizedStateRoot, true)
   222  }
   223  
   224  type memFile struct {
   225  	*bytes.Buffer
   226  }
   227  
   228  func (f *memFile) Close() error {
   229  	*f = memFile{}
   230  	return nil
   231  }
   232  
   233  func (b *GenesisBuilder) Build(head genesis.Header) *genesisstore.Store {
   234  	return genesisstore.NewStore(func(name string) (io.Reader, error) {
   235  		buf := &memFile{bytes.NewBuffer(nil)}
   236  		if name == genesisstore.BlocksSection(0) {
   237  			for i := len(b.blocks) - 1; i >= 0; i-- {
   238  				_ = rlp.Encode(buf, b.blocks[i])
   239  			}
   240  			return buf, nil
   241  		}
   242  		if name == genesisstore.EpochsSection(0) {
   243  			for i := len(b.epochs) - 1; i >= 0; i-- {
   244  				_ = rlp.Encode(buf, b.epochs[i])
   245  			}
   246  			return buf, nil
   247  		}
   248  		if name == genesisstore.EvmSection(0) {
   249  			it := b.tmpEvmStore.EvmDb.NewIterator(nil, nil)
   250  			defer it.Release()
   251  			_ = iodb.Write(buf, it)
   252  		}
   253  		if buf.Len() == 0 {
   254  			return nil, errors.New("not found")
   255  		}
   256  		return buf, nil
   257  	}, head, func() error {
   258  		*b = GenesisBuilder{}
   259  		return nil
   260  	})
   261  }