From 0122722c441928d27ab2469b6e9d01d6ad8e7e51 Mon Sep 17 00:00:00 2001 From: Jan Kalina Date: Wed, 3 May 2023 08:26:06 +0200 Subject: [PATCH 01/10] Replace StateDB struct with interface and wrapper --- accounts/abi/bind/backends/simulated.go | 6 +- core/state/adapter.go | 138 +++++++++++++++++++ core/state/dump.go | 10 +- core/state/iterator.go | 4 +- core/state/journal.go | 30 ++-- core/state/state_object.go | 6 +- core/state/statedb.go | 175 ++++++++++++++---------- core/vm/instructions.go | 7 +- 8 files changed, 271 insertions(+), 105 deletions(-) create mode 100644 core/state/adapter.go diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index e410522ac..bb9909e2f 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -455,8 +455,7 @@ func (b *SimulatedBackend) PendingCallContract(ctx context.Context, call ethereu func (b *SimulatedBackend) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { b.mu.Lock() defer b.mu.Unlock() - - return b.pendingState.GetOrNewStateObject(account).Nonce(), nil + return b.pendingState.GetNonce(account), nil } // SuggestGasPrice implements ContractTransactor.SuggestGasPrice. Since the simulated @@ -617,8 +616,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM call.Value = new(big.Int) } // Set infinite balance to the fake caller account. - from := stateDB.GetOrNewStateObject(call.From) - from.SetBalance(math.MaxBig256) + stateDB.SetBalance(call.From, math.MaxBig256) // Execute the call. msg := callMsg{call} diff --git a/core/state/adapter.go b/core/state/adapter.go new file mode 100644 index 000000000..2b24ba16c --- /dev/null +++ b/core/state/adapter.go @@ -0,0 +1,138 @@ +package state + +import ( + "encoding/json" + substate "github.com/Fantom-foundation/Substate" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/state/snapshot" + "github.com/ethereum/go-ethereum/core/types" + "math/big" + "time" +) + +type StateDbInterface interface { + StartPrefetcher(namespace string) + StopPrefetcher() + Error() error + AddLog(log *types.Log) + GetLogs(hash common.Hash, blockHash common.Hash) []*types.Log + Logs() []*types.Log + AddPreimage(hash common.Hash, preimage []byte) + Preimages() map[common.Hash][]byte + AddRefund(gas uint64) + SubRefund(gas uint64) + Exist(addr common.Address) bool + Empty(addr common.Address) bool + GetBalance(addr common.Address) *big.Int + GetNonce(addr common.Address) uint64 + TxIndex() int + GetCode(addr common.Address) []byte + GetCodeSize(addr common.Address) int + GetCodeHash(addr common.Address) common.Hash + GetState(addr common.Address, hash common.Hash) common.Hash + GetProof(addr common.Address) ([][]byte, error) + GetProofByHash(addrHash common.Hash) ([][]byte, error) + GetStorageProof(a common.Address, key common.Hash) ([][]byte, error) + GetCommittedState(addr common.Address, hash common.Hash) common.Hash + Database() Database + StorageTrie(addr common.Address) Trie + HasSuicided(addr common.Address) bool + AddBalance(addr common.Address, amount *big.Int) + SubBalance(addr common.Address, amount *big.Int) + SetBalance(addr common.Address, amount *big.Int) + SetNonce(addr common.Address, nonce uint64) + SetCode(addr common.Address, code []byte) + SetState(addr common.Address, key, value common.Hash) + SetStorage(addr common.Address, storage map[common.Hash]common.Hash) + Suicide(addr common.Address) bool + CreateAccount(addr common.Address) + ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) error + Copy() StateDbInterface + Snapshot() int + RevertToSnapshot(revid int) + GetRefund() uint64 + Finalise(deleteEmptyObjects bool) + IntermediateRoot(deleteEmptyObjects bool) common.Hash + Prepare(thash common.Hash, ti int) + Commit(deleteEmptyObjects bool) (common.Hash, error) + PrepareAccessList(sender common.Address, dst *common.Address, precompiles []common.Address, list types.AccessList) + AddAddressToAccessList(addr common.Address) + AddSlotToAccessList(addr common.Address, slot common.Hash) + AddressInAccessList(addr common.Address) bool + SlotInAccessList(addr common.Address, slot common.Hash) (addressPresent bool, slotPresent bool) + + RawDump(opts *DumpConfig) Dump + IteratorDump(opts *DumpConfig) IteratorDump + IterativeDump(opts *DumpConfig, output *json.Encoder) + Dump(opts *DumpConfig) []byte + DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []byte) + + GetAccountReads() time.Duration + GetAccountHashes() time.Duration + GetAccountUpdates() time.Duration + GetAccountCommits() time.Duration + GetStorageReads() time.Duration + GetStorageHashes() time.Duration + GetStorageUpdates() time.Duration + GetStorageCommits() time.Duration + GetSnapshotAccountReads() time.Duration + GetSnapshotStorageReads() time.Duration + GetSnapshotCommits() time.Duration + + SetPrehashedCode(addr common.Address, hash common.Hash, code []byte) + GetSubstatePostAlloc() substate.SubstateAlloc +} + +type StateDB struct { + StateDbInterface + + // Measurements gathered during execution for debugging purposes + AccountReads time.Duration + AccountHashes time.Duration + AccountUpdates time.Duration + AccountCommits time.Duration + StorageReads time.Duration + StorageHashes time.Duration + StorageUpdates time.Duration + StorageCommits time.Duration + SnapshotAccountReads time.Duration + SnapshotStorageReads time.Duration + SnapshotCommits time.Duration +} + +func (s *StateDB) Copy() *StateDB { + return &StateDB{ s.StateDbInterface.Copy(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +} + +func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) { + hash, err := s.StateDbInterface.Commit(deleteEmptyObjects) + s.AccountReads = s.GetAccountReads() + s.AccountHashes = s.GetAccountHashes() + s.AccountUpdates = s.GetAccountUpdates() + s.AccountCommits = s.GetAccountCommits() + s.StorageReads = s.GetStorageReads() + s.StorageHashes = s.GetStorageHashes() + s.StorageUpdates = s.GetStorageUpdates() + s.StorageCommits = s.GetStorageCommits() + s.SnapshotAccountReads = s.GetSnapshotAccountReads() + s.SnapshotStorageReads = s.GetSnapshotStorageReads() + s.SnapshotCommits = s.GetSnapshotCommits() + return hash, err +} + +// New creates a new state from a given trie. +func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) { + return NewWithSnapLayers(root, db, snaps, 128) +} + +func NewWithSnapLayers(root common.Hash, db Database, snaps *snapshot.Tree, layers int) (*StateDB, error) { + sdb, err := NewLegacyWithSnapLayers(root, db, snaps, layers) + if err != nil { + return nil, err + } + return NewWrapper(sdb), nil +} + +func NewWrapper(inner StateDbInterface) *StateDB { + return &StateDB{ inner, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +} diff --git a/core/state/dump.go b/core/state/dump.go index 00faa4ed6..6b48f5b64 100644 --- a/core/state/dump.go +++ b/core/state/dump.go @@ -124,7 +124,7 @@ func (d iterativeDump) OnRoot(root common.Hash) { // DumpToCollector iterates the state according to the given options and inserts // the items into a collector for aggregation or serialization. -func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []byte) { +func (s *LegacyStateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []byte) { // Sanitize the input to allow nil configs if conf == nil { conf = new(DumpConfig) @@ -201,7 +201,7 @@ func (s *StateDB) DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey [] } // RawDump returns the entire state an a single large object -func (s *StateDB) RawDump(opts *DumpConfig) Dump { +func (s *LegacyStateDB) RawDump(opts *DumpConfig) Dump { dump := &Dump{ Accounts: make(map[common.Address]DumpAccount), } @@ -210,7 +210,7 @@ func (s *StateDB) RawDump(opts *DumpConfig) Dump { } // Dump returns a JSON string representing the entire state as a single json-object -func (s *StateDB) Dump(opts *DumpConfig) []byte { +func (s *LegacyStateDB) Dump(opts *DumpConfig) []byte { dump := s.RawDump(opts) json, err := json.MarshalIndent(dump, "", " ") if err != nil { @@ -220,12 +220,12 @@ func (s *StateDB) Dump(opts *DumpConfig) []byte { } // IterativeDump dumps out accounts as json-objects, delimited by linebreaks on stdout -func (s *StateDB) IterativeDump(opts *DumpConfig, output *json.Encoder) { +func (s *LegacyStateDB) IterativeDump(opts *DumpConfig, output *json.Encoder) { s.DumpToCollector(iterativeDump{output}, opts) } // IteratorDump dumps out a batch of accounts starts with the given start key -func (s *StateDB) IteratorDump(opts *DumpConfig) IteratorDump { +func (s *LegacyStateDB) IteratorDump(opts *DumpConfig) IteratorDump { iterator := &IteratorDump{ Accounts: make(map[common.Address]DumpAccount), } diff --git a/core/state/iterator.go b/core/state/iterator.go index 6a5c73d3d..1e9f501bc 100644 --- a/core/state/iterator.go +++ b/core/state/iterator.go @@ -28,7 +28,7 @@ import ( // NodeIterator is an iterator to traverse the entire state trie post-order, // including all of the contract code and contract state tries. type NodeIterator struct { - state *StateDB // State being iterated + state *LegacyStateDB // State being iterated stateIt trie.NodeIterator // Primary iterator for the global state trie dataIt trie.NodeIterator // Secondary iterator for the data trie of a contract @@ -44,7 +44,7 @@ type NodeIterator struct { } // NewNodeIterator creates an post-order state node iterator. -func NewNodeIterator(state *StateDB) *NodeIterator { +func NewNodeIterator(state *LegacyStateDB) *NodeIterator { return &NodeIterator{ state: state, } diff --git a/core/state/journal.go b/core/state/journal.go index c902f787e..b90ea4396 100644 --- a/core/state/journal.go +++ b/core/state/journal.go @@ -26,7 +26,7 @@ import ( // reverted on demand. type journalEntry interface { // revert undoes the changes introduced by this journal entry. - revert(*StateDB) + revert(*LegacyStateDB) // dirtied returns the Ethereum address modified by this journal entry. dirtied() *common.Address @@ -57,7 +57,7 @@ func (j *journal) append(entry journalEntry) { // revert undoes a batch of journalled modifications along with any reverted // dirty handling too. -func (j *journal) revert(statedb *StateDB, snapshot int) { +func (j *journal) revert(statedb *LegacyStateDB, snapshot int) { for i := len(j.entries) - 1; i >= snapshot; i-- { // Undo the changes made by the operation j.entries[i].revert(statedb) @@ -140,7 +140,7 @@ type ( } ) -func (ch createObjectChange) revert(s *StateDB) { +func (ch createObjectChange) revert(s *LegacyStateDB) { delete(s.stateObjects, *ch.account) delete(s.stateObjectsDirty, *ch.account) } @@ -149,7 +149,7 @@ func (ch createObjectChange) dirtied() *common.Address { return ch.account } -func (ch resetObjectChange) revert(s *StateDB) { +func (ch resetObjectChange) revert(s *LegacyStateDB) { s.setStateObject(ch.prev) if !ch.prevdestruct && s.snap != nil { delete(s.snapDestructs, ch.prev.addrHash) @@ -162,7 +162,7 @@ func (ch resetObjectChange) dirtied() *common.Address { return &ch.prev.address } -func (ch suicideChange) revert(s *StateDB) { +func (ch suicideChange) revert(s *LegacyStateDB) { obj := s.getStateObject(*ch.account) if obj != nil { obj.suicided = ch.prev @@ -176,14 +176,14 @@ func (ch suicideChange) dirtied() *common.Address { var ripemd = common.HexToAddress("0000000000000000000000000000000000000003") -func (ch touchChange) revert(s *StateDB) { +func (ch touchChange) revert(s *LegacyStateDB) { } func (ch touchChange) dirtied() *common.Address { return ch.account } -func (ch balanceChange) revert(s *StateDB) { +func (ch balanceChange) revert(s *LegacyStateDB) { s.getStateObject(*ch.account).setBalance(ch.prev) } @@ -191,7 +191,7 @@ func (ch balanceChange) dirtied() *common.Address { return ch.account } -func (ch nonceChange) revert(s *StateDB) { +func (ch nonceChange) revert(s *LegacyStateDB) { s.getStateObject(*ch.account).setNonce(ch.prev) } @@ -199,7 +199,7 @@ func (ch nonceChange) dirtied() *common.Address { return ch.account } -func (ch codeChange) revert(s *StateDB) { +func (ch codeChange) revert(s *LegacyStateDB) { s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode) } @@ -207,7 +207,7 @@ func (ch codeChange) dirtied() *common.Address { return ch.account } -func (ch storageChange) revert(s *StateDB) { +func (ch storageChange) revert(s *LegacyStateDB) { s.getStateObject(*ch.account).setState(ch.key, ch.prevalue) } @@ -215,7 +215,7 @@ func (ch storageChange) dirtied() *common.Address { return ch.account } -func (ch refundChange) revert(s *StateDB) { +func (ch refundChange) revert(s *LegacyStateDB) { s.refund = ch.prev } @@ -223,7 +223,7 @@ func (ch refundChange) dirtied() *common.Address { return nil } -func (ch addLogChange) revert(s *StateDB) { +func (ch addLogChange) revert(s *LegacyStateDB) { logs := s.logs[ch.txhash] if len(logs) == 1 { delete(s.logs, ch.txhash) @@ -237,7 +237,7 @@ func (ch addLogChange) dirtied() *common.Address { return nil } -func (ch addPreimageChange) revert(s *StateDB) { +func (ch addPreimageChange) revert(s *LegacyStateDB) { delete(s.preimages, ch.hash) } @@ -245,7 +245,7 @@ func (ch addPreimageChange) dirtied() *common.Address { return nil } -func (ch accessListAddAccountChange) revert(s *StateDB) { +func (ch accessListAddAccountChange) revert(s *LegacyStateDB) { /* One important invariant here, is that whenever a (addr, slot) is added, if the addr is not already present, the add causes two journal entries: @@ -262,7 +262,7 @@ func (ch accessListAddAccountChange) dirtied() *common.Address { return nil } -func (ch accessListAddSlotChange) revert(s *StateDB) { +func (ch accessListAddSlotChange) revert(s *LegacyStateDB) { s.accessList.DeleteSlot(*ch.address, *ch.slot) } diff --git a/core/state/state_object.go b/core/state/state_object.go index 1c7bb579d..990deee76 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -67,7 +67,7 @@ type stateObject struct { address common.Address addrHash common.Hash // hash of ethereum address of the account data Account - db *StateDB + db *LegacyStateDB // DB error. // State objects are used by the consensus core and VM which are @@ -111,7 +111,7 @@ type Account struct { } // newObject creates a state object. -func newObject(db *StateDB, address common.Address, data Account) *stateObject { +func newObject(db *LegacyStateDB, address common.Address, data Account) *stateObject { if data.Balance == nil { data.Balance = new(big.Int) } @@ -466,7 +466,7 @@ func (s *stateObject) setBalance(amount *big.Int) { s.data.Balance = amount } -func (s *stateObject) deepCopy(db *StateDB) *stateObject { +func (s *stateObject) deepCopy(db *LegacyStateDB) *stateObject { stateObject := newObject(db, s.address, s.data) if s.trie != nil { stateObject.trie = db.db.CopyTrie(s.trie) diff --git a/core/state/statedb.go b/core/state/statedb.go index 5bbdc9e2f..548fcc513 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -57,12 +57,12 @@ func (n *proofList) Delete(key []byte) error { panic("not supported") } -// StateDB structs within the ethereum protocol are used to store anything -// within the merkle trie. StateDBs take care of caching and storing +// LegacyStateDB structs within the ethereum protocol are used to store anything +// within the merkle trie. LegacyStateDBs take care of caching and storing // nested states. It's the general query interface to retrieve: // * Contracts // * Accounts -type StateDB struct { +type LegacyStateDB struct { db Database prefetcher *triePrefetcher originalRoot common.Hash // The pre-state root, before any changes were made @@ -85,7 +85,7 @@ type StateDB struct { // State objects are used by the consensus core and VM which are // unable to deal with database-level errors. Any error that occurs // during a database read is memoized here and will eventually be returned - // by StateDB.Commit. + // by LegacyStateDB.Commit. dbErr error // The refund counter, also used by state transitioning. @@ -126,17 +126,12 @@ type StateDB struct { SubstateBlockHashes map[uint64]common.Hash } -// New creates a new state from a given trie. -func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) { - return NewWithSnapLayers(root, db, snaps, 128) -} - -func NewWithSnapLayers(root common.Hash, db Database, snaps *snapshot.Tree, layers int) (*StateDB, error) { +func NewLegacyWithSnapLayers(root common.Hash, db Database, snaps *snapshot.Tree, layers int) (StateDbInterface, error) { tr, err := db.OpenTrie(root) if err != nil { return nil, err } - sdb := &StateDB{ + sdb := &LegacyStateDB{ db: db, trie: tr, originalRoot: root, @@ -172,7 +167,7 @@ func NewWithSnapLayers(root common.Hash, db Database, snaps *snapshot.Tree, laye // StartPrefetcher initializes a new trie prefetcher to pull in nodes from the // state trie concurrently while the state is mutated so that when we reach the // commit phase, most of the needed data is already hot. -func (s *StateDB) StartPrefetcher(namespace string) { +func (s *LegacyStateDB) StartPrefetcher(namespace string) { if s.prefetcher != nil { s.prefetcher.close() s.prefetcher = nil @@ -184,7 +179,7 @@ func (s *StateDB) StartPrefetcher(namespace string) { // StopPrefetcher terminates a running prefetcher and reports any leftover stats // from the gathered metrics. -func (s *StateDB) StopPrefetcher() { +func (s *LegacyStateDB) StopPrefetcher() { if s.prefetcher != nil { s.prefetcher.close() s.prefetcher = nil @@ -192,17 +187,17 @@ func (s *StateDB) StopPrefetcher() { } // setError remembers the first non-nil error it is called with. -func (s *StateDB) setError(err error) { +func (s *LegacyStateDB) setError(err error) { if s.dbErr == nil { s.dbErr = err } } -func (s *StateDB) Error() error { +func (s *LegacyStateDB) Error() error { return s.dbErr } -func (s *StateDB) AddLog(log *types.Log) { +func (s *LegacyStateDB) AddLog(log *types.Log) { s.journal.append(addLogChange{txhash: s.thash}) log.TxHash = s.thash @@ -212,7 +207,7 @@ func (s *StateDB) AddLog(log *types.Log) { s.logSize++ } -func (s *StateDB) GetLogs(hash common.Hash, blockHash common.Hash) []*types.Log { +func (s *LegacyStateDB) GetLogs(hash common.Hash, blockHash common.Hash) []*types.Log { logs := s.logs[hash] for _, l := range logs { l.BlockHash = blockHash @@ -220,7 +215,7 @@ func (s *StateDB) GetLogs(hash common.Hash, blockHash common.Hash) []*types.Log return logs } -func (s *StateDB) Logs() []*types.Log { +func (s *LegacyStateDB) Logs() []*types.Log { var logs []*types.Log for _, lgs := range s.logs { logs = append(logs, lgs...) @@ -229,7 +224,7 @@ func (s *StateDB) Logs() []*types.Log { } // AddPreimage records a SHA3 preimage seen by the VM. -func (s *StateDB) AddPreimage(hash common.Hash, preimage []byte) { +func (s *LegacyStateDB) AddPreimage(hash common.Hash, preimage []byte) { if _, ok := s.preimages[hash]; !ok { s.journal.append(addPreimageChange{hash: hash}) pi := make([]byte, len(preimage)) @@ -239,19 +234,19 @@ func (s *StateDB) AddPreimage(hash common.Hash, preimage []byte) { } // Preimages returns a list of SHA3 preimages that have been submitted. -func (s *StateDB) Preimages() map[common.Hash][]byte { +func (s *LegacyStateDB) Preimages() map[common.Hash][]byte { return s.preimages } // AddRefund adds gas to the refund counter -func (s *StateDB) AddRefund(gas uint64) { +func (s *LegacyStateDB) AddRefund(gas uint64) { s.journal.append(refundChange{prev: s.refund}) s.refund += gas } // SubRefund removes gas from the refund counter. // This method will panic if the refund counter goes below zero -func (s *StateDB) SubRefund(gas uint64) { +func (s *LegacyStateDB) SubRefund(gas uint64) { s.journal.append(refundChange{prev: s.refund}) if gas > s.refund { panic(fmt.Sprintf("Refund counter below zero (gas: %d > refund: %d)", gas, s.refund)) @@ -261,19 +256,19 @@ func (s *StateDB) SubRefund(gas uint64) { // Exist reports whether the given account address exists in the state. // Notably this also returns true for suicided accounts. -func (s *StateDB) Exist(addr common.Address) bool { +func (s *LegacyStateDB) Exist(addr common.Address) bool { return s.getStateObject(addr) != nil } // Empty returns whether the state object is either non-existent // or empty according to the EIP161 specification (balance = nonce = code = 0) -func (s *StateDB) Empty(addr common.Address) bool { +func (s *LegacyStateDB) Empty(addr common.Address) bool { so := s.getStateObject(addr) return so == nil || so.empty() } // GetBalance retrieves the balance from the given address or 0 if object not found -func (s *StateDB) GetBalance(addr common.Address) *big.Int { +func (s *LegacyStateDB) GetBalance(addr common.Address) *big.Int { stateObject := s.getStateObject(addr) if stateObject != nil { return stateObject.Balance() @@ -281,7 +276,7 @@ func (s *StateDB) GetBalance(addr common.Address) *big.Int { return common.Big0 } -func (s *StateDB) GetNonce(addr common.Address) uint64 { +func (s *LegacyStateDB) GetNonce(addr common.Address) uint64 { stateObject := s.getStateObject(addr) if stateObject != nil { return stateObject.Nonce() @@ -291,11 +286,11 @@ func (s *StateDB) GetNonce(addr common.Address) uint64 { } // TxIndex returns the current transaction index set by Prepare. -func (s *StateDB) TxIndex() int { +func (s *LegacyStateDB) TxIndex() int { return s.txIndex } -func (s *StateDB) GetCode(addr common.Address) []byte { +func (s *LegacyStateDB) GetCode(addr common.Address) []byte { stateObject := s.getStateObject(addr) if stateObject != nil { return stateObject.Code(s.db) @@ -303,7 +298,7 @@ func (s *StateDB) GetCode(addr common.Address) []byte { return nil } -func (s *StateDB) GetCodeSize(addr common.Address) int { +func (s *LegacyStateDB) GetCodeSize(addr common.Address) int { stateObject := s.getStateObject(addr) if stateObject != nil { return stateObject.CodeSize(s.db) @@ -311,7 +306,7 @@ func (s *StateDB) GetCodeSize(addr common.Address) int { return 0 } -func (s *StateDB) GetCodeHash(addr common.Address) common.Hash { +func (s *LegacyStateDB) GetCodeHash(addr common.Address) common.Hash { stateObject := s.getStateObject(addr) if stateObject == nil { return common.Hash{} @@ -320,7 +315,7 @@ func (s *StateDB) GetCodeHash(addr common.Address) common.Hash { } // GetState retrieves a value from the given account's storage trie. -func (s *StateDB) GetState(addr common.Address, hash common.Hash) common.Hash { +func (s *LegacyStateDB) GetState(addr common.Address, hash common.Hash) common.Hash { stateObject := s.getStateObject(addr) if stateObject != nil { return stateObject.GetState(s.db, hash) @@ -329,19 +324,19 @@ func (s *StateDB) GetState(addr common.Address, hash common.Hash) common.Hash { } // GetProof returns the Merkle proof for a given account. -func (s *StateDB) GetProof(addr common.Address) ([][]byte, error) { +func (s *LegacyStateDB) GetProof(addr common.Address) ([][]byte, error) { return s.GetProofByHash(crypto.Keccak256Hash(addr.Bytes())) } // GetProofByHash returns the Merkle proof for a given account. -func (s *StateDB) GetProofByHash(addrHash common.Hash) ([][]byte, error) { +func (s *LegacyStateDB) GetProofByHash(addrHash common.Hash) ([][]byte, error) { var proof proofList err := s.trie.Prove(addrHash[:], 0, &proof) return proof, err } // GetStorageProof returns the Merkle proof for given storage slot. -func (s *StateDB) GetStorageProof(a common.Address, key common.Hash) ([][]byte, error) { +func (s *LegacyStateDB) GetStorageProof(a common.Address, key common.Hash) ([][]byte, error) { var proof proofList trie := s.StorageTrie(a) if trie == nil { @@ -352,7 +347,7 @@ func (s *StateDB) GetStorageProof(a common.Address, key common.Hash) ([][]byte, } // GetCommittedState retrieves a value from the given account's committed storage trie. -func (s *StateDB) GetCommittedState(addr common.Address, hash common.Hash) common.Hash { +func (s *LegacyStateDB) GetCommittedState(addr common.Address, hash common.Hash) common.Hash { stateObject := s.getStateObject(addr) if stateObject != nil { return stateObject.GetCommittedState(s.db, hash) @@ -361,13 +356,13 @@ func (s *StateDB) GetCommittedState(addr common.Address, hash common.Hash) commo } // Database retrieves the low level database supporting the lower level trie ops. -func (s *StateDB) Database() Database { +func (s *LegacyStateDB) Database() Database { return s.db } // StorageTrie returns the storage trie of an account. // The return value is a copy and is nil for non-existent accounts. -func (s *StateDB) StorageTrie(addr common.Address) Trie { +func (s *LegacyStateDB) StorageTrie(addr common.Address) Trie { stateObject := s.getStateObject(addr) if stateObject == nil { return nil @@ -377,7 +372,7 @@ func (s *StateDB) StorageTrie(addr common.Address) Trie { return cpy.getTrie(s.db) } -func (s *StateDB) HasSuicided(addr common.Address) bool { +func (s *LegacyStateDB) HasSuicided(addr common.Address) bool { stateObject := s.getStateObject(addr) if stateObject != nil { return stateObject.suicided @@ -390,7 +385,7 @@ func (s *StateDB) HasSuicided(addr common.Address) bool { */ // AddBalance adds amount to the account associated with addr. -func (s *StateDB) AddBalance(addr common.Address, amount *big.Int) { +func (s *LegacyStateDB) AddBalance(addr common.Address, amount *big.Int) { stateObject := s.GetOrNewStateObject(addr) if stateObject != nil { stateObject.AddBalance(amount) @@ -398,42 +393,42 @@ func (s *StateDB) AddBalance(addr common.Address, amount *big.Int) { } // SubBalance subtracts amount from the account associated with addr. -func (s *StateDB) SubBalance(addr common.Address, amount *big.Int) { +func (s *LegacyStateDB) SubBalance(addr common.Address, amount *big.Int) { stateObject := s.GetOrNewStateObject(addr) if stateObject != nil { stateObject.SubBalance(amount) } } -func (s *StateDB) SetBalance(addr common.Address, amount *big.Int) { +func (s *LegacyStateDB) SetBalance(addr common.Address, amount *big.Int) { stateObject := s.GetOrNewStateObject(addr) if stateObject != nil { stateObject.SetBalance(amount) } } -func (s *StateDB) SetNonce(addr common.Address, nonce uint64) { +func (s *LegacyStateDB) SetNonce(addr common.Address, nonce uint64) { stateObject := s.GetOrNewStateObject(addr) if stateObject != nil { stateObject.SetNonce(nonce) } } -func (s *StateDB) SetCode(addr common.Address, code []byte) { +func (s *LegacyStateDB) SetCode(addr common.Address, code []byte) { stateObject := s.GetOrNewStateObject(addr) if stateObject != nil { stateObject.SetCode(crypto.Keccak256Hash(code), code) } } -func (s *StateDB) SetPrehashedCode(addr common.Address, hash common.Hash, code []byte) { +func (s *LegacyStateDB) SetPrehashedCode(addr common.Address, hash common.Hash, code []byte) { stateObject := s.GetOrNewStateObject(addr) if stateObject != nil { stateObject.SetCode(hash, code) } } -func (s *StateDB) SetState(addr common.Address, key, value common.Hash) { +func (s *LegacyStateDB) SetState(addr common.Address, key, value common.Hash) { stateObject := s.GetOrNewStateObject(addr) if stateObject != nil { stateObject.SetState(s.db, key, value) @@ -442,7 +437,7 @@ func (s *StateDB) SetState(addr common.Address, key, value common.Hash) { // SetStorage replaces the entire storage for the specified account with given // storage. This function should only be used for debugging. -func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common.Hash) { +func (s *LegacyStateDB) SetStorage(addr common.Address, storage map[common.Hash]common.Hash) { stateObject := s.GetOrNewStateObject(addr) if stateObject != nil { stateObject.SetStorage(storage) @@ -454,7 +449,7 @@ func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common // // The account's state object is still available until the state is committed, // getStateObject will return a non-nil account after Suicide. -func (s *StateDB) Suicide(addr common.Address) bool { +func (s *LegacyStateDB) Suicide(addr common.Address) bool { stateObject := s.getStateObject(addr) if stateObject == nil { return false @@ -475,7 +470,7 @@ func (s *StateDB) Suicide(addr common.Address) bool { // // updateStateObject writes the given object to the trie. -func (s *StateDB) updateStateObject(obj *stateObject) { +func (s *LegacyStateDB) updateStateObject(obj *stateObject) { // Track the amount of time wasted on updating the account from the trie if metrics.EnabledExpensive { defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now()) @@ -501,7 +496,7 @@ func (s *StateDB) updateStateObject(obj *stateObject) { } // deleteStateObject removes the given object from the state trie. -func (s *StateDB) deleteStateObject(obj *stateObject) { +func (s *LegacyStateDB) deleteStateObject(obj *stateObject) { // Track the amount of time wasted on deleting the account from the trie if metrics.EnabledExpensive { defer func(start time.Time) { s.AccountUpdates += time.Since(start) }(time.Now()) @@ -516,7 +511,7 @@ func (s *StateDB) deleteStateObject(obj *stateObject) { // getStateObject retrieves a state object given by the address, returning nil if // the object is not found or was deleted in this execution context. If you need // to differentiate between non-existent/just-deleted, use getDeletedStateObject. -func (s *StateDB) getStateObject(addr common.Address) *stateObject { +func (s *LegacyStateDB) getStateObject(addr common.Address) *stateObject { if obj := s.getDeletedStateObject(addr); obj != nil && !obj.deleted { if substate.RecordReplay { @@ -544,7 +539,7 @@ func (s *StateDB) getStateObject(addr common.Address) *stateObject { // nil for a deleted state object, it returns the actual object with the deleted // flag set. This is needed by the state journal to revert to the correct s- // destructed object instead of wiping all knowledge about the state object. -func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject { +func (s *LegacyStateDB) getDeletedStateObject(addr common.Address) *stateObject { // Prefer live objects if any is available if obj := s.stateObjects[addr]; obj != nil { return obj @@ -602,12 +597,12 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject { return obj } -func (s *StateDB) setStateObject(object *stateObject) { +func (s *LegacyStateDB) setStateObject(object *stateObject) { s.stateObjects[object.Address()] = object } // GetOrNewStateObject retrieves a state object or create a new state object if nil. -func (s *StateDB) GetOrNewStateObject(addr common.Address) *stateObject { +func (s *LegacyStateDB) GetOrNewStateObject(addr common.Address) *stateObject { stateObject := s.getStateObject(addr) if stateObject == nil { stateObject, _ = s.createObject(addr) @@ -617,7 +612,7 @@ func (s *StateDB) GetOrNewStateObject(addr common.Address) *stateObject { // createObject creates a new state object. If there is an existing account with // the given address, it is overwritten and returned as the second return value. -func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) { +func (s *LegacyStateDB) createObject(addr common.Address) (newobj, prev *stateObject) { prev = s.getDeletedStateObject(addr) // Note, prev might have been deleted, we need that! var prevdestruct bool @@ -650,14 +645,14 @@ func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) // 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1) // // Carrying over the balance ensures that Ether doesn't disappear. -func (s *StateDB) CreateAccount(addr common.Address) { +func (s *LegacyStateDB) CreateAccount(addr common.Address) { newObj, prev := s.createObject(addr) if prev != nil { newObj.setBalance(prev.data.Balance) } } -func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) error { +func (db *LegacyStateDB) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) error { so := db.getStateObject(addr) if so == nil { return nil @@ -688,9 +683,9 @@ func (db *StateDB) ForEachStorage(addr common.Address, cb func(key, value common // Copy creates a deep, independent copy of the state. // Snapshots of the copied state cannot be applied to the copy. -func (s *StateDB) Copy() *StateDB { +func (s *LegacyStateDB) Copy() StateDbInterface { // Copy all the basic fields, initialize the memory ones - state := &StateDB{ + state := &LegacyStateDB{ db: s.db, trie: s.db.CopyTrie(s.trie), stateObjects: make(map[common.Address]*stateObject, len(s.journal.dirties)), @@ -804,7 +799,7 @@ func (s *StateDB) Copy() *StateDB { } // Snapshot returns an identifier for the current revision of the state. -func (s *StateDB) Snapshot() int { +func (s *LegacyStateDB) Snapshot() int { id := s.nextRevisionId s.nextRevisionId++ s.validRevisions = append(s.validRevisions, revision{id, s.journal.length()}) @@ -812,7 +807,7 @@ func (s *StateDB) Snapshot() int { } // RevertToSnapshot reverts all state changes made since the given revision. -func (s *StateDB) RevertToSnapshot(revid int) { +func (s *LegacyStateDB) RevertToSnapshot(revid int) { // Find the snapshot in the stack of valid snapshots. idx := sort.Search(len(s.validRevisions), func(i int) bool { return s.validRevisions[i].id >= revid @@ -828,14 +823,14 @@ func (s *StateDB) RevertToSnapshot(revid int) { } // GetRefund returns the current value of the refund counter. -func (s *StateDB) GetRefund() uint64 { +func (s *LegacyStateDB) GetRefund() uint64 { return s.refund } // Finalise finalises the state by removing the s destructed objects and clears // the journal as well as the refunds. Finalise, however, will not push any updates // into the tries just yet. Only IntermediateRoot or Commit will do that. -func (s *StateDB) Finalise(deleteEmptyObjects bool) { +func (s *LegacyStateDB) Finalise(deleteEmptyObjects bool) { if substate.RecordReplay { // copy original storage values to Prestate and Poststate @@ -910,12 +905,12 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) { // IntermediateRoot computes the current root hash of the state trie. // It is called in between transactions to get the root hash that // goes into transaction receipts. -func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash { +func (s *LegacyStateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash { // Finalise all the dirty storage states and write them into the tries s.Finalise(deleteEmptyObjects) // If there was a trie prefetcher operating, it gets aborted and irrevocably - // modified after we start retrieving tries. Remove it from the statedb after + // modified after we start retrieving tries. Remove it from the LegacyStateDB after // this round of use. // // This is weird pre-byzantium since the first tx runs with a prefetcher and @@ -970,7 +965,7 @@ func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash { // Prepare sets the current transaction hash and index which are // used when the EVM emits new state logs. -func (s *StateDB) Prepare(thash common.Hash, ti int) { +func (s *LegacyStateDB) Prepare(thash common.Hash, ti int) { s.thash = thash s.txIndex = ti @@ -987,7 +982,7 @@ func (s *StateDB) Prepare(thash common.Hash, ti int) { s.accessList = newAccessList() } -func (s *StateDB) clearJournalAndRefund() { +func (s *LegacyStateDB) clearJournalAndRefund() { if len(s.journal.entries) > 0 { s.journal = newJournal() s.refund = 0 @@ -996,7 +991,7 @@ func (s *StateDB) clearJournalAndRefund() { } // Commit writes the state to the underlying in-memory trie database. -func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) { +func (s *LegacyStateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) { if s.dbErr != nil { return common.Hash{}, fmt.Errorf("commit aborted due to earlier error: %v", s.dbErr) } @@ -1078,7 +1073,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) { // - Add the contents of the optional tx access list (2930) // // This method should only be called if Berlin/2929+2930 is applicable at the current number. -func (s *StateDB) PrepareAccessList(sender common.Address, dst *common.Address, precompiles []common.Address, list types.AccessList) { +func (s *LegacyStateDB) PrepareAccessList(sender common.Address, dst *common.Address, precompiles []common.Address, list types.AccessList) { s.AddAddressToAccessList(sender) if dst != nil { s.AddAddressToAccessList(*dst) @@ -1096,14 +1091,14 @@ func (s *StateDB) PrepareAccessList(sender common.Address, dst *common.Address, } // AddAddressToAccessList adds the given address to the access list -func (s *StateDB) AddAddressToAccessList(addr common.Address) { +func (s *LegacyStateDB) AddAddressToAccessList(addr common.Address) { if s.accessList.AddAddress(addr) { s.journal.append(accessListAddAccountChange{&addr}) } } // AddSlotToAccessList adds the given (address, slot)-tuple to the access list -func (s *StateDB) AddSlotToAccessList(addr common.Address, slot common.Hash) { +func (s *LegacyStateDB) AddSlotToAccessList(addr common.Address, slot common.Hash) { addrMod, slotMod := s.accessList.AddSlot(addr, slot) if addrMod { // In practice, this should not happen, since there is no way to enter the @@ -1121,15 +1116,49 @@ func (s *StateDB) AddSlotToAccessList(addr common.Address, slot common.Hash) { } // AddressInAccessList returns true if the given address is in the access list. -func (s *StateDB) AddressInAccessList(addr common.Address) bool { +func (s *LegacyStateDB) AddressInAccessList(addr common.Address) bool { return s.accessList.ContainsAddress(addr) } // SlotInAccessList returns true if the given (address, slot)-tuple is in the access list. -func (s *StateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addressPresent bool, slotPresent bool) { +func (s *LegacyStateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addressPresent bool, slotPresent bool) { return s.accessList.Contains(addr, slot) } -func (s *StateDB) GetSubstatePostAlloc() substate.SubstateAlloc { +func (s *LegacyStateDB) GetSubstatePostAlloc() substate.SubstateAlloc { return s.SubstatePostAlloc } + +func (s *LegacyStateDB) GetAccountReads() time.Duration { + return s.AccountReads +} +func (s *LegacyStateDB) GetAccountHashes() time.Duration { + return s.AccountHashes +} +func (s *LegacyStateDB) GetAccountUpdates() time.Duration { + return s.AccountUpdates +} +func (s *LegacyStateDB) GetAccountCommits() time.Duration { + return s.AccountCommits +} +func (s *LegacyStateDB) GetStorageReads() time.Duration { + return s.StorageReads +} +func (s *LegacyStateDB) GetStorageHashes() time.Duration { + return s.StorageHashes +} +func (s *LegacyStateDB) GetStorageUpdates() time.Duration { + return s.StorageUpdates +} +func (s *LegacyStateDB) GetStorageCommits() time.Duration { + return s.StorageCommits +} +func (s *LegacyStateDB) GetSnapshotAccountReads() time.Duration { + return s.SnapshotAccountReads +} +func (s *LegacyStateDB) GetSnapshotStorageReads() time.Duration { + return s.SnapshotStorageReads +} +func (s *LegacyStateDB) GetSnapshotCommits() time.Duration { + return s.SnapshotCommits +} diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 787f1a967..5e1189315 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -448,9 +448,10 @@ func opBlockhash(pc *uint64, interpreter *GethEVMInterpreter, scope *ScopeContex if substate.RecordReplay { // convert vm.StateDB to state.StateDB and save block hash defer func() { - statedb, ok := interpreter.evm.StateDB.(*state.StateDB) - if ok { - statedb.SubstateBlockHashes[num64] = common.BytesToHash(num.Bytes()) + if statedb, ok := interpreter.evm.StateDB.(*state.StateDB); ok { + if legacy, ok := statedb.StateDbInterface.(*state.LegacyStateDB); ok { + legacy.SubstateBlockHashes[num64] = common.BytesToHash(num.Bytes()) + } } }() } From 96917b7b3a4a44d4da8677ed29ec5e7d15f549dc Mon Sep 17 00:00:00 2001 From: Jan Kalina Date: Wed, 17 May 2023 21:52:00 +0200 Subject: [PATCH 02/10] Add EndBlock into StateDB interface (#33) --- core/state/adapter.go | 5 +++-- core/state/statedb.go | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/core/state/adapter.go b/core/state/adapter.go index 2b24ba16c..9b299eb6b 100644 --- a/core/state/adapter.go +++ b/core/state/adapter.go @@ -81,6 +81,7 @@ type StateDbInterface interface { SetPrehashedCode(addr common.Address, hash common.Hash, code []byte) GetSubstatePostAlloc() substate.SubstateAlloc + EndBlock(number uint64) } type StateDB struct { @@ -101,7 +102,7 @@ type StateDB struct { } func (s *StateDB) Copy() *StateDB { - return &StateDB{ s.StateDbInterface.Copy(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + return &StateDB{s.StateDbInterface.Copy(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} } func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) { @@ -134,5 +135,5 @@ func NewWithSnapLayers(root common.Hash, db Database, snaps *snapshot.Tree, laye } func NewWrapper(inner StateDbInterface) *StateDB { - return &StateDB{ inner, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } + return &StateDB{inner, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} } diff --git a/core/state/statedb.go b/core/state/statedb.go index 548fcc513..61b651275 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -1129,6 +1129,10 @@ func (s *LegacyStateDB) GetSubstatePostAlloc() substate.SubstateAlloc { return s.SubstatePostAlloc } +func (s *LegacyStateDB) EndBlock(number uint64) { + // not used by LegacyStateDB +} + func (s *LegacyStateDB) GetAccountReads() time.Duration { return s.AccountReads } From 2c34addfd51518755ecf43790c073188792ad883 Mon Sep 17 00:00:00 2001 From: Jan Kalina Date: Fri, 19 May 2023 09:01:50 +0200 Subject: [PATCH 03/10] Add BeginBlock into StateDB interface (#34) --- core/state/adapter.go | 1 + core/state/statedb.go | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/core/state/adapter.go b/core/state/adapter.go index 9b299eb6b..f4f97cf66 100644 --- a/core/state/adapter.go +++ b/core/state/adapter.go @@ -81,6 +81,7 @@ type StateDbInterface interface { SetPrehashedCode(addr common.Address, hash common.Hash, code []byte) GetSubstatePostAlloc() substate.SubstateAlloc + BeginBlock(number uint64) EndBlock(number uint64) } diff --git a/core/state/statedb.go b/core/state/statedb.go index 61b651275..87b54db60 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -1129,6 +1129,10 @@ func (s *LegacyStateDB) GetSubstatePostAlloc() substate.SubstateAlloc { return s.SubstatePostAlloc } +func (s *LegacyStateDB) BeginBlock(number uint64) { + // not used by LegacyStateDB +} + func (s *LegacyStateDB) EndBlock(number uint64) { // not used by LegacyStateDB } From 1a14fdc1d4be9b8f67c0c91655a998256102604b Mon Sep 17 00:00:00 2001 From: wsodsong Date: Mon, 12 Jun 2023 09:42:19 +0000 Subject: [PATCH 04/10] Port to v1.10.8-ftm-rc11 --- core/state/adapter.go | 2 +- core/state/state_object.go | 2 +- core/state/statedb.go | 2 +- core/vm/instructions.go | 2 +- go.mod | 7 +- go.sum | 122 ++------- substate/destroyed_account_db.go | 142 ++++++++++ substate/metadata.go | 47 ++++ substate/static_substate_db.go | 107 ++++++++ substate/substate.go | 396 +++++++++++++++++++++++++++ substate/substate_db.go | 447 +++++++++++++++++++++++++++++++ substate/substate_json.go | 347 ++++++++++++++++++++++++ substate/substate_rlp.go | 409 ++++++++++++++++++++++++++++ substate/substate_task.go | 256 ++++++++++++++++++ substate/update_db.go | 313 ++++++++++++++++++++++ 15 files changed, 2487 insertions(+), 114 deletions(-) create mode 100644 substate/destroyed_account_db.go create mode 100644 substate/metadata.go create mode 100644 substate/static_substate_db.go create mode 100644 substate/substate.go create mode 100644 substate/substate_db.go create mode 100644 substate/substate_json.go create mode 100644 substate/substate_rlp.go create mode 100644 substate/substate_task.go create mode 100644 substate/update_db.go diff --git a/core/state/adapter.go b/core/state/adapter.go index f4f97cf66..4e7e0943c 100644 --- a/core/state/adapter.go +++ b/core/state/adapter.go @@ -2,10 +2,10 @@ package state import ( "encoding/json" - substate "github.com/Fantom-foundation/Substate" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state/snapshot" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/substate" "math/big" "time" ) diff --git a/core/state/state_object.go b/core/state/state_object.go index 990deee76..5ac7c97c8 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -19,7 +19,6 @@ package state import ( "bytes" "fmt" - substate "github.com/Fantom-foundation/Substate" "io" "math/big" "time" @@ -28,6 +27,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/substate" ) var emptyCodeHash = crypto.Keccak256(nil) diff --git a/core/state/statedb.go b/core/state/statedb.go index 87b54db60..46721668f 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -24,7 +24,6 @@ import ( "sort" "time" - substate "github.com/Fantom-foundation/Substate" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state/snapshot" @@ -33,6 +32,7 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/substate" "github.com/ethereum/go-ethereum/trie" ) diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 5e1189315..2b5028ab4 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -17,13 +17,13 @@ package vm import ( - substate "github.com/Fantom-foundation/Substate" "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/substate" "github.com/holiman/uint256" "golang.org/x/crypto/sha3" ) diff --git a/go.mod b/go.mod index 4b1d9bd61..86ad00d95 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,6 @@ require ( github.com/Azure/azure-pipeline-go v0.2.2 // indirect github.com/Azure/azure-storage-blob-go v0.7.0 github.com/Azure/go-autorest/autorest/adal v0.8.0 // indirect - github.com/Fantom-foundation/Substate v0.0.0-20230224090651-4c8c024214f4 github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect github.com/VictoriaMetrics/fastcache v1.6.0 github.com/aws/aws-sdk-go-v2 v1.2.0 @@ -21,13 +20,15 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set v1.8.0 github.com/deepmap/oapi-codegen v1.8.2 // indirect + github.com/dlclark/regexp2 v1.10.0 // indirect github.com/docker/docker v1.6.2 - github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf + github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498 github.com/edsrzf/mmap-go v1.0.0 github.com/fatih/color v1.7.0 github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff github.com/go-ole/go-ole v1.2.1 // indirect + github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect github.com/go-stack/stack v1.8.0 github.com/golang/mock v1.3.1 github.com/golang/protobuf v1.5.2 @@ -73,6 +74,4 @@ require ( gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 gopkg.in/urfave/cli.v1 v1.20.0 - gopkg.in/yaml.v2 v2.4.0 // indirect - gotest.tools v2.2.0+incompatible // indirect ) diff --git a/go.sum b/go.sum index 790792b6f..dc09fc9af 100644 --- a/go.sum +++ b/go.sum @@ -18,48 +18,34 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/azure-pipeline-go v0.2.1 h1:OLBdZJ3yvOn2MezlWvbrBMTEUQC72zAftRZOMdj5HYo= github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= github.com/Azure/azure-pipeline-go v0.2.2 h1:6oiIS9yaG6XCCzhgAgKFfIWyo4LLCiDhZot6ltoThhY= github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1/go.mod h1:fBF9PQNqB8scdgpZ3ufzaLntG0AG7C1WjPMsiFOmfHM= -github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3/go.mod h1:KLF4gFr6DcKFZwSuH8w8yEK6DpFl3LP5rhdvAb7Yz5I= -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0/go.mod h1:tPaiy8S5bQ+S5sOiDlINkp7+Ef339+Nz5L5XO+cnOHo= github.com/Azure/azure-storage-blob-go v0.7.0 h1:MuueVOYkufCxJw5YZzF842DY2MBsp+hLuh2apKY0mck= github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= -github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= -github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.9.0 h1:MRvx8gncNaXJqOoLmhNjUAKh33JJF8LyxPhomEtOsjs= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.0 h1:CxTzQrySOxDnKpLjFJeZAS5Qrv/qFPkgLjx5bOAi//I= github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= -github.com/Azure/go-autorest/autorest/adal v0.9.22 h1:/GblQdIudfEM3AWWZ0mrYJQSd7JS4S/Mbzh6F0ov0Xc= -github.com/Azure/go-autorest/autorest/adal v0.9.22/go.mod h1:XuAbAEUv2Tta//+voMI038TrJBqjKam0me7qR+L8Cmk= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM= github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= -github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= -github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= -github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= -github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= -github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= -github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= -github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= -github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= -github.com/Fantom-foundation/Substate v0.0.0-20230224090651-4c8c024214f4 h1:AA0BtERxmlf7jvDF4fwIB2k/Lsc7HTRE3QHTZnfcSVA= -github.com/Fantom-foundation/Substate v0.0.0-20230224090651-4c8c024214f4/go.mod h1:/yIHWCDDJcdKMJYvOLdYOnHt5eUBF9XWnrvrNE+90ik= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= -github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= @@ -94,8 +80,6 @@ github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+Wji github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= -github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= @@ -122,11 +106,9 @@ github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3h github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ= github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f h1:C43yEtQ6NIf4ftFXD/V55gnGFgPbMQobd//YlnLjUJ8= github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -135,40 +117,32 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= -github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/deepmap/oapi-codegen v1.6.0 h1:w/d1ntwh91XI0b/8ja7+u5SvA4IFfM0UNNLmiDR1gg0= github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= github.com/deepmap/oapi-codegen v1.8.2 h1:SegyeYGcdi0jLLrpbCMoJxnUUn8GBXHsvr4rbzjuhfU= github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 h1:Izz0+t1Z5nI16/II7vuEo/nHjodOg0p7+OiDpjX5t1E= -github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= -github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0= +github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/docker/docker v1.6.2 h1:HlFGsy+9/xrgMmhmN+NGhCc5SHGJ7I+kHosRR1xc/aI= github.com/docker/docker v1.6.2/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf h1:Yt+4K30SdjOkRoRRm3vYNQgR+/ZIy0RmeUDZo7Y8zeQ= -github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= -github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= +github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498 h1:Y9vTBSsV4hSwPSj4bacAU/eSnV3dAxVpepaghAdhGoQ= +github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ethereum/go-ethereum v1.10.25/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= @@ -186,8 +160,6 @@ github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80n github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= -github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= -github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= @@ -198,9 +170,6 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/golang-jwt/jwt/v4 v4.0.0 h1:RAqyYixv1p7uEnocuy8P1nru5wprCh/MH2BIlW5z5/o= -github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -210,8 +179,6 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -225,7 +192,6 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -258,7 +224,6 @@ github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0U github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= -github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= @@ -280,7 +245,6 @@ github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= github.com/influxdata/influxql v1.1.1-0.20200828144457-65d3ef77d385/go.mod h1:gHp9y86a/pxhjJ+zMjNXiQAA197Xk9wLxaz+fGG+kWk= github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE= -github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU= github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 h1:vilfsDSy7TDxedi9gyBkMvAirat/oRcL0lFdJBf6tdM= github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= @@ -317,14 +281,11 @@ github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH6 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= @@ -340,7 +301,6 @@ github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149 h1:HfxbT6/JcvIljmERptWhwa8XzP7H3T+Z2N26gTsaDaA= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d h1:oNAwILwmgWKFpuU+dXvI6dl9jG2mAWAZLX3r9s0PPiw= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= @@ -354,15 +314,10 @@ github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/Qd github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q= github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= -github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks= @@ -376,7 +331,6 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= @@ -419,7 +373,6 @@ github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRr github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -428,7 +381,6 @@ github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfP github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -449,25 +401,17 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= -github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= -github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= -github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= -github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= -github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= -github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y= github.com/urfave/cli/v2 v2.10.2/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo= @@ -479,8 +423,6 @@ github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6Ut github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -500,8 +442,6 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= -golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -512,7 +452,6 @@ golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm0 golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -531,8 +470,6 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -551,19 +488,11 @@ golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -594,7 +523,6 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -613,29 +541,19 @@ golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -666,19 +584,15 @@ golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191126055441-b0650ceb63d9/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= @@ -727,9 +641,8 @@ google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/l google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= @@ -745,14 +658,11 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/substate/destroyed_account_db.go b/substate/destroyed_account_db.go new file mode 100644 index 000000000..4caac18ca --- /dev/null +++ b/substate/destroyed_account_db.go @@ -0,0 +1,142 @@ +package substate + +import ( + "encoding/binary" + "fmt" + "log" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/rlp" +) + +type DestroyedAccountDB struct { + backend BackendDatabase +} + +func NewDestroyedAccountDB(backend BackendDatabase) *DestroyedAccountDB { + return &DestroyedAccountDB{backend: backend} +} + +func OpenDestroyedAccountDB(destroyedAccountDir string) (*DestroyedAccountDB, error) { + return openDestroyedAccountDB(destroyedAccountDir, false) +} + +func OpenDestroyedAccountDBReadOnly(destroyedAccountDir string) (*DestroyedAccountDB, error) { + return openDestroyedAccountDB(destroyedAccountDir, true) +} + +func openDestroyedAccountDB(destroyedAccountDir string, readOnly bool) (*DestroyedAccountDB, error) { + log.Println("substate: OpenDestroyedAccountDB") + backend, err := rawdb.NewLevelDBDatabase(destroyedAccountDir, 1024, 100, "destroyed_accounts", readOnly) + if err != nil { + return nil, fmt.Errorf("error opening deletion-db %s: %v", destroyedAccountDir, err) + } + return NewDestroyedAccountDB(backend), nil +} + +func (db *DestroyedAccountDB) Close() error { + return db.backend.Close() +} + +type SuicidedAccountLists struct { + DestroyedAccounts []common.Address + ResurrectedAccounts []common.Address +} + +func (db *DestroyedAccountDB) SetDestroyedAccounts(block uint64, tx int, des []common.Address, res []common.Address) error { + accountList := SuicidedAccountLists{DestroyedAccounts: des, ResurrectedAccounts: res} + value, err := rlp.EncodeToBytes(accountList) + if err != nil { + panic(err) + } + return db.backend.Put(encodeDestroyedAccountKey(block, tx), value) +} + +func (db *DestroyedAccountDB) GetDestroyedAccounts(block uint64, tx int) ([]common.Address, []common.Address, error) { + data, err := db.backend.Get(encodeDestroyedAccountKey(block, tx)) + if err != nil { + return nil, nil, err + } + list, err := decodeAddressList(data) + return list.DestroyedAccounts, list.ResurrectedAccounts, err +} + +func (db *DestroyedAccountDB) getFirstKeyInBlock(block uint64) []byte { + prefix := []byte(DestroyedAccountPrefix) + blockBytes := make([]byte, len(prefix)+8) + copy(blockBytes[0:], prefix) + binary.BigEndian.PutUint64(blockBytes[len(prefix):], block) + iter := db.backend.NewIterator(blockBytes, nil) + defer iter.Release() + if iter.Key() != nil { + return iter.Key()[len(prefix):] + } + return nil +} + +// GetAccountsDestroyedInRange get list of all accounts between block from and to (including from and to). +func (db *DestroyedAccountDB) GetAccountsDestroyedInRange(from, to uint64) ([]common.Address, error) { + firstKey := db.getFirstKeyInBlock(from) + iter := db.backend.NewIterator([]byte(DestroyedAccountPrefix), firstKey) + defer iter.Release() + isDestroyed := make(map[common.Address]bool) + for iter.Next() { + block, _, err := decodeDestroyedAccountKey(iter.Key()) + if err != nil { + return nil, err + } + if block > to { + break + } + list, err := decodeAddressList(iter.Value()) + if err != nil { + return nil, err + } + for _, addr := range list.DestroyedAccounts { + isDestroyed[addr] = true + } + for _, addr := range list.ResurrectedAccounts { + isDestroyed[addr] = false + } + } + + accountList := []common.Address{} + for addr, isDeleted := range isDestroyed { + if isDeleted { + accountList = append(accountList, addr) + } + } + return accountList, nil +} + +const ( + DestroyedAccountPrefix = "da" // DestroyedAccountPrefix + block (64-bit) -> SuicidedAccountLists +) + +func encodeDestroyedAccountKey(block uint64, tx int) []byte { + prefix := []byte(DestroyedAccountPrefix) + key := make([]byte, len(prefix)+12) + copy(key[0:], prefix) + binary.BigEndian.PutUint64(key[len(prefix):], block) + binary.BigEndian.PutUint32(key[len(prefix)+8:], uint32(tx)) + return key +} + +func decodeDestroyedAccountKey(data []byte) (uint64, int, error) { + if len(data) != len(DestroyedAccountPrefix)+12 { + return 0, 0, fmt.Errorf("invalid length of destroyed account key, expected %d, got %d", len(DestroyedAccountPrefix)+12, len(data)) + } + if string(data[0:len(DestroyedAccountPrefix)]) != DestroyedAccountPrefix { + return 0, 0, fmt.Errorf("invalid prefix of destroyed account key") + } + block := binary.BigEndian.Uint64(data[len(DestroyedAccountPrefix):]) + tx := binary.BigEndian.Uint32(data[len(DestroyedAccountPrefix)+8:]) + return block, int(tx), nil +} + +func decodeAddressList(data []byte) (SuicidedAccountLists, error) { + list := SuicidedAccountLists{} + err := rlp.DecodeBytes(data, &list) + return list, err +} diff --git a/substate/metadata.go b/substate/metadata.go new file mode 100644 index 000000000..b61350150 --- /dev/null +++ b/substate/metadata.go @@ -0,0 +1,47 @@ +package substate + +import ( + "encoding/binary" +) + +const ( + MetadataPrefix = "md" + UpdatesetPrefix = "us" + UpdatesetIntervalKey = MetadataPrefix + UpdatesetPrefix + "in" + UpdatesetSizeKey = MetadataPrefix + UpdatesetPrefix + "si" +) + +// PutMetadata into db +func (db *UpdateDB) PutMetadata(interval, size uint64) error { + + byteInterval := make([]byte, 8) + binary.BigEndian.PutUint64(byteInterval, interval) + + if err := db.backend.Put([]byte(UpdatesetIntervalKey), byteInterval); err != nil { + return err + } + + sizeInterval := make([]byte, 8) + binary.BigEndian.PutUint64(sizeInterval, size) + + if err := db.backend.Put([]byte(UpdatesetSizeKey), sizeInterval); err != nil { + return err + } + + return nil +} + +// GetMetadata from db +func (db *UpdateDB) GetMetadata() (uint64, uint64, error) { + byteInterval, err := db.backend.Get([]byte(UpdatesetIntervalKey)) + if err != nil { + return 0, 0, err + } + + byteSize, err := db.backend.Get([]byte(UpdatesetSizeKey)) + if err != nil { + return 0, 0, err + } + + return binary.BigEndian.Uint64(byteInterval), binary.BigEndian.Uint64(byteSize), nil +} diff --git a/substate/static_substate_db.go b/substate/static_substate_db.go new file mode 100644 index 000000000..1598ba59f --- /dev/null +++ b/substate/static_substate_db.go @@ -0,0 +1,107 @@ +package substate + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/urfave/cli/v2" +) + +var ( + SubstateDbFlag = cli.StringFlag{ + Name: "substate-db", + Usage: "Data directory for substate recorder/replayer", + } + substateDir = SubstateDbFlag.Value + staticSubstateDB *SubstateDB + RecordReplay bool = false +) + +func OpenSubstateDB() { + fmt.Println("record-replay: OpenSubstateDB") + backend, err := rawdb.NewLevelDBDatabase(substateDir, 1024, 100, "substatedir", false) + if err != nil { + panic(fmt.Errorf("error opening substate leveldb %s: %v", substateDir, err)) + } + fmt.Println("record-replay: opened successfully") + staticSubstateDB = NewSubstateDB(backend) +} + +func OpenSubstateDBReadOnly() { + fmt.Println("record-replay: OpenSubstateDB") + backend, err := rawdb.NewLevelDBDatabase(substateDir, 1024, 100, "substatedir", true) + if err != nil { + panic(fmt.Errorf("error opening substate leveldb %s: %v", substateDir, err)) + } + staticSubstateDB = NewSubstateDB(backend) +} + +func CloseSubstateDB() { + defer fmt.Println("record-replay: CloseSubstateDB") + + err := staticSubstateDB.Close() + if err != nil { + panic(fmt.Errorf("error closing substate leveldb %s: %v", substateDir, err)) + } +} + +func CompactSubstateDB() { + fmt.Println("record-replay: CompactSubstateDB") + + // compact entire DB + err := staticSubstateDB.Compact(nil, nil) + if err != nil { + panic(fmt.Errorf("error compacting substate leveldb %s: %v", substateDir, err)) + } +} + +func OpenFakeSubstateDB() { + backend := rawdb.NewMemoryDatabase() + staticSubstateDB = NewSubstateDB(backend) +} + +func CloseFakeSubstateDB() { + staticSubstateDB.Close() +} + +func SetSubstateDbFlags(ctx *cli.Context) { + substateDir = ctx.String(SubstateDbFlag.Name) + fmt.Printf("record-replay: --substatedir=%s\n", substateDir) +} + +func SetSubstateDb(dir string) { + substateDir = dir +} + +func HasCode(codeHash common.Hash) bool { + return staticSubstateDB.HasCode(codeHash) +} + +func GetCode(codeHash common.Hash) []byte { + return staticSubstateDB.GetCode(codeHash) +} + +func PutCode(code []byte) { + staticSubstateDB.PutCode(code) +} + +func HasSubstate(block uint64, tx int) bool { + return staticSubstateDB.HasSubstate(block, tx) +} + +func GetSubstate(block uint64, tx int) *Substate { + return staticSubstateDB.GetSubstate(block, tx) +} + +func GetBlockSubstates(block uint64) map[int]*Substate { + return staticSubstateDB.GetBlockSubstates(block) +} + +func PutSubstate(block uint64, tx int, substate *Substate) { + staticSubstateDB.PutSubstate(block, tx, substate) +} + +func DeleteSubstate(block uint64, tx int) { + staticSubstateDB.DeleteSubstate(block, tx) +} diff --git a/substate/substate.go b/substate/substate.go new file mode 100644 index 000000000..10dbbbb0b --- /dev/null +++ b/substate/substate.go @@ -0,0 +1,396 @@ +package substate + +import ( + "bytes" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" +) + +// SubstateAccount is modification of GenesisAccount in core/genesis.go +type SubstateAccount struct { + Nonce uint64 + Balance *big.Int + Storage map[common.Hash]common.Hash + Code []byte +} + +func NewSubstateAccount(nonce uint64, balance *big.Int, code []byte) *SubstateAccount { + return &SubstateAccount{ + Nonce: nonce, + Balance: new(big.Int).Set(balance), + Storage: make(map[common.Hash]common.Hash), + Code: code, + } +} + +func (x *SubstateAccount) Equal(y *SubstateAccount) bool { + if x == y { + return true + } + + if (x == nil || y == nil) && x != y { + return false + } + + equal := (x.Nonce == y.Nonce && + x.Balance.Cmp(y.Balance) == 0 && + bytes.Equal(x.Code, y.Code) && + len(x.Storage) == len(y.Storage)) + if !equal { + return false + } + + for k, xv := range x.Storage { + yv, exist := y.Storage[k] + if !(exist && xv == yv) { + return false + } + } + + return true +} + +func (sa *SubstateAccount) Copy() *SubstateAccount { + saCopy := NewSubstateAccount(sa.Nonce, sa.Balance, sa.Code) + + for key, value := range sa.Storage { + saCopy.Storage[key] = value + } + + return saCopy +} + +func (sa *SubstateAccount) CodeHash() common.Hash { + return crypto.Keccak256Hash(sa.Code) +} + +type SubstateAlloc map[common.Address]*SubstateAccount + +// EstinateIncrementalSize returns estimated substate size increase after merge +func (x SubstateAlloc) EstimateIncrementalSize (y SubstateAlloc) uint64 { + var ( + size uint64 = 0 + sizeOfAddress uint64 = 20 + sizeOfHash uint64 = 32 + sizeOfNonce uint64 = 8 + ) + for addr, account := range y { + if xaccount, found := x[addr]; found { + // skip if no diff + if xaccount.Equal(account) { + continue + } + // update storage by y + for key, _ := range account.Storage { + // only add new storage keys + if _, found := x[addr].Storage[key]; !found { + size += sizeOfHash // add sizeof(common.Hash) + } + } + } else { + // add size of new accounts + // address + nonce + balance + codehash + size += sizeOfAddress + sizeOfNonce + uint64(len(account.Balance.Bytes())) + sizeOfHash + // storage slots * sizeof(common.Hash) + size += uint64(len(account.Storage)) * sizeOfHash + } + } + return size +} + +func (x SubstateAlloc) Merge(y SubstateAlloc) { + for addr, account := range y { + if xaccount, found := x[addr]; found { + if xaccount.Equal(account) { + continue + } + // overwrite account details in x by y + x[addr].Nonce = account.Nonce + x[addr].Balance = new(big.Int).Set(account.Balance) + x[addr].Code = make([]byte, len(account.Code)) + copy(x[addr].Code, account.Code) + } else { + // create new account details in x + x[addr] = NewSubstateAccount(account.Nonce, account.Balance, account.Code) + } + // update storage by y + for key, value := range account.Storage { + x[addr].Storage[key] = value + } + } +} + +func (x SubstateAlloc) Equal(y SubstateAlloc) bool { + if len(x) != len(y) { + return false + } + + for k, xv := range x { + yv, exist := y[k] + if !(exist && xv.Equal(yv)) { + return false + } + } + + return true +} + +type SubstateEnv struct { + Coinbase common.Address + Difficulty *big.Int + GasLimit uint64 + Number uint64 + Timestamp uint64 + BlockHashes map[uint64]common.Hash + + // London hard fork, EIP-1559 + BaseFee *big.Int // nil if EIP-1559 is not activated +} + +func NewSubstateEnv(b *types.Block, blockHashes map[uint64]common.Hash) *SubstateEnv { + var env = &SubstateEnv{} + + env.Coinbase = b.Coinbase() + env.Difficulty = new(big.Int).Set(b.Difficulty()) + env.GasLimit = b.GasLimit() + env.Number = b.NumberU64() + env.Timestamp = b.Time() + env.BlockHashes = make(map[uint64]common.Hash) + for num64, bhash := range blockHashes { + env.BlockHashes[num64] = bhash + } + + env.BaseFee = b.BaseFee() + + return env +} + +func (x *SubstateEnv) Equal(y *SubstateEnv) bool { + if x == y { + return true + } + + if (x == nil || y == nil) && x != y { + return false + } + + equal := (x.Coinbase == y.Coinbase && + x.Difficulty.Cmp(y.Difficulty) == 0 && + x.GasLimit == y.GasLimit && + x.Number == y.Number && + x.Timestamp == y.Timestamp && + len(x.BlockHashes) == len(y.BlockHashes) && + x.BaseFee.Cmp(y.BaseFee) == 0) + if !equal { + return false + } + + for k, xv := range x.BlockHashes { + yv, exist := y.BlockHashes[k] + if !(exist && xv == yv) { + return false + } + } + + return true +} + +type SubstateMessage struct { + Nonce uint64 + CheckNonce bool // inversion of IsFake + GasPrice *big.Int + Gas uint64 + + From common.Address + To *common.Address // nil means contract creation + Value *big.Int + Data []byte + + // for memoization + dataHash *common.Hash + + // Berlin hard fork, EIP-2930: Optional access lists + AccessList types.AccessList // nil if EIP-2930 is not activated + + // London hard fork, EIP-1559: Fee market + GasFeeCap *big.Int // GasPrice if EIP-1559 is not activated + GasTipCap *big.Int // GasPrice if EIP-1559 is not activated +} + +func NewSubstateMessage(msg *types.Message) *SubstateMessage { + var smsg = &SubstateMessage{} + + smsg.Nonce = msg.Nonce() + smsg.CheckNonce = !msg.IsFake() + smsg.GasPrice = msg.GasPrice() + smsg.Gas = msg.Gas() + + smsg.From = msg.From() + smsg.To = msg.To() + smsg.Value = msg.Value() + smsg.Data = msg.Data() + + smsg.AccessList = msg.AccessList() + + smsg.GasFeeCap = msg.GasFeeCap() + smsg.GasTipCap = msg.GasTipCap() + + return smsg +} + +func (x *SubstateMessage) Equal(y *SubstateMessage) bool { + if x == y { + return true + } + + if (x == nil || y == nil) && x != y { + return false + } + + equal := (x.Nonce == y.Nonce && + x.CheckNonce == y.CheckNonce && + x.GasPrice.Cmp(y.GasPrice) == 0 && + x.Gas == y.Gas && + x.From == y.From && + (x.To == y.To || (x.To != nil && y.To != nil && *x.To == *y.To)) && + x.Value.Cmp(y.Value) == 0 && + bytes.Equal(x.Data, y.Data) && + len(x.AccessList) == len(y.AccessList) && + x.GasFeeCap.Cmp(y.GasFeeCap) == 0 && + x.GasTipCap.Cmp(y.GasTipCap) == 0) + if !equal { + return false + } + + for i, xa := range x.AccessList { + ya := y.AccessList[i] + equal := (xa.Address == ya.Address && + len(xa.StorageKeys) == len(ya.StorageKeys)) + if !equal { + return false + } + for j, xk := range xa.StorageKeys { + yk := ya.StorageKeys[j] + if xk != yk { + return false + } + } + } + + return true +} + +func (msg *SubstateMessage) DataHash() common.Hash { + if msg.dataHash == nil { + dataHash := crypto.Keccak256Hash(msg.Data) + msg.dataHash = &dataHash + } + return *msg.dataHash +} + +func (msg *SubstateMessage) AsMessage() types.Message { + return types.NewMessage( + msg.From, msg.To, msg.Nonce, msg.Value, + msg.Gas, msg.GasPrice, msg.GasFeeCap, msg.GasTipCap, + msg.Data, msg.AccessList, !msg.CheckNonce) +} + +// modification of types.Receipt +type SubstateResult struct { + Status uint64 + Bloom types.Bloom + Logs []*types.Log + + ContractAddress common.Address + GasUsed uint64 +} + +func NewSubstateResult(receipt *types.Receipt) *SubstateResult { + var sr = &SubstateResult{} + + sr.Status = receipt.Status + sr.Bloom = receipt.Bloom + sr.Logs = receipt.Logs + + sr.ContractAddress = receipt.ContractAddress + sr.GasUsed = receipt.GasUsed + + return sr +} + +func (x *SubstateResult) Equal(y *SubstateResult) bool { + if x == y { + return true + } + + if (x == nil || y == nil) && x != y { + return false + } + + equal := (x.Status == y.Status && + x.Bloom == y.Bloom && + len(x.Logs) == len(y.Logs) && + x.ContractAddress == y.ContractAddress && + x.GasUsed == y.GasUsed) + if !equal { + return false + } + + for i, xl := range x.Logs { + yl := y.Logs[i] + + equal := (xl.Address == yl.Address && + len(xl.Topics) == len(yl.Topics) && + bytes.Equal(xl.Data, yl.Data)) + if !equal { + return false + } + + for i, xt := range xl.Topics { + yt := yl.Topics[i] + if xt != yt { + return false + } + } + } + + return true +} + +type Substate struct { + InputAlloc SubstateAlloc + OutputAlloc SubstateAlloc + Env *SubstateEnv + Message *SubstateMessage + Result *SubstateResult +} + +func NewSubstate(inputAlloc SubstateAlloc, outputAlloc SubstateAlloc, env *SubstateEnv, message *SubstateMessage, result *SubstateResult) *Substate { + return &Substate{ + InputAlloc: inputAlloc, + OutputAlloc: outputAlloc, + Env: env, + Message: message, + Result: result, + } +} + +func (x *Substate) Equal(y *Substate) bool { + if x == y { + return true + } + + if (x == nil || y == nil) && x != y { + return false + } + + equal := (x.InputAlloc.Equal(y.InputAlloc) && + x.OutputAlloc.Equal(y.OutputAlloc) && + x.Env.Equal(y.Env) && + x.Message.Equal(y.Message) && + x.Result.Equal(y.Result)) + return equal +} diff --git a/substate/substate_db.go b/substate/substate_db.go new file mode 100644 index 000000000..9be0cf008 --- /dev/null +++ b/substate/substate_db.go @@ -0,0 +1,447 @@ +package substate + +import ( + "encoding/binary" + "fmt" + "io" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/rlp" +) + +const ( + Stage1SubstatePrefix = "1s" // Stage1SubstatePrefix + block (64-bit) + tx (64-bit) -> substateRLP + Stage1CodePrefix = "1c" // Stage1CodePrefix + codeHash (256-bit) -> code +) + +func Stage1SubstateKey(block uint64, tx int) []byte { + prefix := []byte(Stage1SubstatePrefix) + + blockTx := make([]byte, 16) + binary.BigEndian.PutUint64(blockTx[0:8], block) + binary.BigEndian.PutUint64(blockTx[8:16], uint64(tx)) + + return append(prefix, blockTx...) +} + +func DecodeStage1SubstateKey(key []byte) (block uint64, tx int, err error) { + prefix := Stage1SubstatePrefix + if len(key) != len(prefix)+8+8 { + err = fmt.Errorf("invalid length of stage1 substate key: %v", len(key)) + return + } + if p := string(key[:len(prefix)]); p != prefix { + err = fmt.Errorf("invalid prefix of stage1 substate key: %#x", p) + return + } + blockTx := key[len(prefix):] + block = binary.BigEndian.Uint64(blockTx[0:8]) + tx = int(binary.BigEndian.Uint64(blockTx[8:16])) + return +} + +func Stage1SubstateBlockPrefix(block uint64) []byte { + return append([]byte(Stage1SubstatePrefix), BlockToBytes(block)...) +} +func BlockToBytes(block uint64) []byte { + blockBytes := make([]byte, 8) + binary.BigEndian.PutUint64(blockBytes[0:8], block) + return blockBytes +} + +func Stage1CodeKey(codeHash common.Hash) []byte { + prefix := []byte(Stage1CodePrefix) + return append(prefix, codeHash.Bytes()...) +} + +func DecodeStage1CodeKey(key []byte) (codeHash common.Hash, err error) { + prefix := Stage1CodePrefix + if len(key) != len(prefix)+32 { + err = fmt.Errorf("invalid length of stage1 code key: %v", len(key)) + return + } + if p := string(key[:2]); p != prefix { + err = fmt.Errorf("invalid prefix of stage1 code key: %#x", p) + return + } + codeHash = common.BytesToHash(key[len(prefix):]) + return +} + +type BackendDatabase interface { + ethdb.KeyValueReader + ethdb.KeyValueWriter + ethdb.Batcher + ethdb.Iteratee + ethdb.Stater + ethdb.Compacter + io.Closer +} + +type SubstateDB struct { + backend BackendDatabase +} + +func NewSubstateDB(backend BackendDatabase) *SubstateDB { + return &SubstateDB{backend: backend} +} + +func (db *SubstateDB) Compact(start []byte, limit []byte) error { + return db.backend.Compact(start, limit) +} + +func (db *SubstateDB) Close() error { + return db.backend.Close() +} + +func CodeHash(code []byte) common.Hash { + return crypto.Keccak256Hash(code) +} + +var EmptyCodeHash = CodeHash(nil) + +func (db *SubstateDB) HasCode(codeHash common.Hash) bool { + if codeHash == EmptyCodeHash { + return false + } + key := Stage1CodeKey(codeHash) + has, err := db.backend.Has(key) + if err != nil { + panic(fmt.Errorf("record-replay: error checking bytecode for codeHash %s: %v", codeHash.Hex(), err)) + } + return has +} + +func (db *SubstateDB) GetCode(codeHash common.Hash) []byte { + if codeHash == EmptyCodeHash { + return nil + } + key := Stage1CodeKey(codeHash) + code, err := db.backend.Get(key) + if err != nil { + panic(fmt.Errorf("record-replay: error getting code %s: %v", codeHash.Hex(), err)) + } + return code +} + +func (db *SubstateDB) PutCode(code []byte) { + if len(code) == 0 { + return + } + codeHash := crypto.Keccak256Hash(code) + key := Stage1CodeKey(codeHash) + err := db.backend.Put(key, code) + if err != nil { + panic(fmt.Errorf("record-replay: error putting code %s: %v", codeHash.Hex(), err)) + } +} + +func (db *SubstateDB) HasSubstate(block uint64, tx int) bool { + key := Stage1SubstateKey(block, tx) + has, _ := db.backend.Has(key) + return has +} + +func (db *SubstateDB) GetSubstate(block uint64, tx int) *Substate { + var err error + + key := Stage1SubstateKey(block, tx) + value, err := db.backend.Get(key) + if err != nil { + panic(fmt.Errorf("record-replay: error getting substate %v_%v from substate DB: %v,", block, tx, err)) + } + + // try decoding as substates from latest hard forks + substateRLP := SubstateRLP{} + err = rlp.DecodeBytes(value, &substateRLP) + + if err != nil { + // try decoding as legacy substates between Berlin and London hard forks + berlinRLP := berlinSubstateRLP{} + err = rlp.DecodeBytes(value, &berlinRLP) + if err == nil { + substateRLP.setBerlinRLP(&berlinRLP) + } + } + + if err != nil { + // try decoding as legacy substates before Berlin hard fork + legacyRLP := legacySubstateRLP{} + err = rlp.DecodeBytes(value, &legacyRLP) + if err != nil { + panic(fmt.Errorf("error decoding substateRLP %v_%v: %v", block, tx, err)) + } + substateRLP.setLegacyRLP(&legacyRLP) + } + + substate := Substate{} + substate.SetRLP(&substateRLP, db) + + return &substate +} + +func (db *SubstateDB) GetBlockSubstates(block uint64) map[int]*Substate { + var err error + + txSubstate := make(map[int]*Substate) + + prefix := Stage1SubstateBlockPrefix(block) + + iter := db.backend.NewIterator(prefix, nil) + for iter.Next() { + key := iter.Key() + value := iter.Value() + + b, tx, err := DecodeStage1SubstateKey(key) + if err != nil { + panic(fmt.Errorf("record-replay: invalid substate key found for block %v: %v", block, err)) + } + + if block != b { + panic(fmt.Errorf("record-replay: GetBlockSubstates(%v) iterated substates from block %v", block, b)) + } + + // try decoding as substates from latest hard forks + substateRLP := SubstateRLP{} + err = rlp.DecodeBytes(value, &substateRLP) + + if err != nil { + // try decoding as legacy substates between Berlin and London hard forks + berlinRLP := berlinSubstateRLP{} + err = rlp.DecodeBytes(value, &berlinRLP) + if err == nil { + substateRLP.setBerlinRLP(&berlinRLP) + } + } + + if err != nil { + // try decoding as legacy substates before Berlin hard fork + legacyRLP := legacySubstateRLP{} + err = rlp.DecodeBytes(value, &legacyRLP) + if err != nil { + panic(fmt.Errorf("error decoding substateRLP %v_%v: %v", block, tx, err)) + } + substateRLP.setLegacyRLP(&legacyRLP) + } + + substate := Substate{} + substate.SetRLP(&substateRLP, db) + + txSubstate[tx] = &substate + } + iter.Release() + err = iter.Error() + if err != nil { + panic(err) + } + + return txSubstate +} + +func (db *SubstateDB) PutSubstate(block uint64, tx int, substate *Substate) { + var err error + + // put deployed/creation code + for _, account := range substate.InputAlloc { + db.PutCode(account.Code) + } + for _, account := range substate.OutputAlloc { + db.PutCode(account.Code) + } + if msg := substate.Message; msg.To == nil { + db.PutCode(msg.Data) + } + + key := Stage1SubstateKey(block, tx) + defer func() { + if err != nil { + panic(fmt.Errorf("record-replay: error putting substate %v_%v into substate DB: %v", block, tx, err)) + } + }() + + substateRLP := NewSubstateRLP(substate) + value, err := rlp.EncodeToBytes(substateRLP) + if err != nil { + panic(err) + } + + err = db.backend.Put(key, value) + if err != nil { + panic(err) + } +} + +func (db *SubstateDB) DeleteSubstate(block uint64, tx int) { + key := Stage1SubstateKey(block, tx) + err := db.backend.Delete(key) + if err != nil { + panic(err) + } +} + +type Transaction struct { + Block uint64 + Transaction int + Substate *Substate +} + +type rawEntry struct { + key []byte + value []byte +} + +func parseTransaction(db *SubstateDB, data rawEntry) *Transaction { + key := data.key + value := data.value + + block, tx, err := DecodeStage1SubstateKey(data.key) + if err != nil { + panic(fmt.Errorf("record-replay: invalid substate key found: %v - issue: %v", key, err)) + } + + // try decoding as substates from latest hard forks + substateRLP := SubstateRLP{} + err = rlp.DecodeBytes(value, &substateRLP) + + if err != nil { + // try decoding as legacy substates between Berlin and London hard forks + berlinRLP := berlinSubstateRLP{} + err = rlp.DecodeBytes(value, &berlinRLP) + if err == nil { + substateRLP.setBerlinRLP(&berlinRLP) + } + } + + if err != nil { + // try decoding as legacy substates before Berlin hard fork + legacyRLP := legacySubstateRLP{} + err = rlp.DecodeBytes(value, &legacyRLP) + if err != nil { + panic(fmt.Errorf("error decoding substateRLP %v_%v: %v", block, tx, err)) + } + substateRLP.setLegacyRLP(&legacyRLP) + } + + substate := &Substate{} + substate.SetRLP(&substateRLP, db) + + return &Transaction{ + Block: block, + Transaction: tx, + Substate: substate, + } +} + +type SubstateIterator struct { + db *SubstateDB + iter ethdb.Iterator + cur *Transaction + + // Connections to parsing pipeline + source <-chan *Transaction + done chan<- int +} + +func NewSubstateIterator(start_block uint64, num_workers int) SubstateIterator { + db := staticSubstateDB + start := BlockToBytes(start_block) + // substate prefix is already in start + iter := db.backend.NewIterator([]byte(Stage1SubstatePrefix), start) + + // Create channels + done := make(chan int) + raw_data := make([]chan rawEntry, num_workers) + results := make([]chan *Transaction, num_workers) + result := make(chan *Transaction, 10) + + for i := 0; i < num_workers; i++ { + raw_data[i] = make(chan rawEntry, 10) + results[i] = make(chan *Transaction, 10) + } + + // Start iter => raw data stage + go func() { + defer func() { + for _, c := range raw_data { + close(c) + } + }() + step := 0 + for { + if !iter.Next() { + return + } + + key := make([]byte, len(iter.Key())) + copy(key, iter.Key()) + value := make([]byte, len(iter.Value())) + copy(value, iter.Value()) + + res := rawEntry{key, value} + + select { + case <-done: + return + case raw_data[step] <- res: // fall-through + } + step = (step + 1) % num_workers + } + }() + + // Start raw data => parsed transaction stage (parallel) + for i := 0; i < num_workers; i++ { + id := i + go func() { + defer close(results[id]) + for raw := range raw_data[id] { + results[id] <- parseTransaction(db, raw) + } + }() + } + + // Start the go routine moving transactions from parsers to sink in order + go func() { + defer close(result) + step := 0 + for open_producers := num_workers; open_producers > 0; { + next := <-results[step%num_workers] + if next != nil { + result <- next + } else { + open_producers-- + } + step++ + } + }() + + return SubstateIterator{ + db: db, + iter: iter, + source: result, + done: done, + } +} + +func (i *SubstateIterator) Release() { + close(i.done) + + // drain pipeline until the result channel is closed + for open := true; open; _, open = <-i.source { + } + + i.iter.Release() +} + +func (i *SubstateIterator) Next() bool { + if i.iter == nil { + return false + } + i.cur = <-i.source + return i.cur != nil +} + +func (i *SubstateIterator) Value() *Transaction { + return i.cur +} diff --git a/substate/substate_json.go b/substate/substate_json.go new file mode 100644 index 000000000..ec414efad --- /dev/null +++ b/substate/substate_json.go @@ -0,0 +1,347 @@ +package substate + +import ( + "encoding/json" + "math/big" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/common/math" + "github.com/ethereum/go-ethereum/core/types" + + "github.com/ethereum/go-ethereum/common" +) + +// SubstateAccountJSON is modification of core.GenesisAccount +type SubstateAccountJSON struct { + Code hexutil.Bytes `json:"code,omitempty"` + Storage map[common.Hash]common.Hash `json:"storage,omitempty"` + Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"` + Nonce math.HexOrDecimal64 `json:"nonce,omitempty"` +} + +func NewSubstateAccountJSON(sa *SubstateAccount) *SubstateAccountJSON { + return &SubstateAccountJSON{ + Nonce: math.HexOrDecimal64(sa.Nonce), + Balance: (*math.HexOrDecimal256)(sa.Balance), + Storage: sa.Storage, + Code: sa.Code, + } +} + +func (sa *SubstateAccount) SetJSON(saJSON *SubstateAccountJSON) { + sa.Nonce = uint64(saJSON.Nonce) + sa.Balance = (*big.Int)(saJSON.Balance) + sa.Storage = make(map[common.Hash]common.Hash) + if saJSON.Storage != nil { + sa.Storage = saJSON.Storage + } + sa.Code = saJSON.Code +} + +func (sa SubstateAccount) MarshalJSON() ([]byte, error) { + return json.Marshal(NewSubstateAccountJSON(&sa)) +} + +func (sa *SubstateAccount) UnmarshalJSON(b []byte) error { + var err error + var saJSON SubstateAccountJSON + + err = json.Unmarshal(b, &saJSON) + if err != nil { + return err + } + + sa.SetJSON(&saJSON) + + return nil +} + +type SubstateAllocJSON map[common.Address]*SubstateAccountJSON + +func NewSubstateAllocJSON(alloc SubstateAlloc) SubstateAllocJSON { + allocJSON := make(SubstateAllocJSON) + for addr, account := range alloc { + allocJSON[addr] = NewSubstateAccountJSON(account) + } + + return allocJSON +} + +func (alloc *SubstateAlloc) SetJSON(allocJSON SubstateAllocJSON) { + *alloc = make(SubstateAlloc) + for addr, saJSON := range allocJSON { + var sa SubstateAccount + + sa.Nonce = uint64(saJSON.Nonce) + sa.Balance = (*big.Int)(saJSON.Balance) + sa.Storage = make(map[common.Hash]common.Hash) + if saJSON.Storage != nil { + sa.Storage = saJSON.Storage + } + sa.Code = saJSON.Code + + (*alloc)[addr] = &sa + } +} + +func (alloc SubstateAlloc) MarshalJSON() ([]byte, error) { + return json.Marshal(NewSubstateAllocJSON(alloc)) +} + +func (alloc *SubstateAlloc) UnmarshalJSON(b []byte) error { + var err error + var allocJSON SubstateAllocJSON + + err = json.Unmarshal(b, &allocJSON) + if err != nil { + return err + } + + alloc.SetJSON(allocJSON) + + return nil +} + +// SubstateEnvJSON is modification of t8ntool.stEnv +type SubstateEnvJSON struct { + Coinbase common.Address `json:"coinbase" gencodec:"required"` + Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"` + GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` + Number math.HexOrDecimal64 `json:"number" gencodec:"required"` + Timestamp math.HexOrDecimal64 `json:"timestamp" gencodec:"required"` + BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"` + + BaseFee *math.HexOrDecimal256 `json:"baseFee,omitempty"` +} + +func NewSubstateEnvJSON(env *SubstateEnv) *SubstateEnvJSON { + var envJSON SubstateEnvJSON + + envJSON.Coinbase = env.Coinbase + envJSON.Difficulty = (*math.HexOrDecimal256)(env.Difficulty) + envJSON.GasLimit = math.HexOrDecimal64(env.GasLimit) + envJSON.Number = math.HexOrDecimal64(env.Number) + envJSON.Timestamp = math.HexOrDecimal64(env.Timestamp) + envJSON.BlockHashes = make(map[math.HexOrDecimal64]common.Hash) + if env.BlockHashes != nil { + for num64, bhash := range env.BlockHashes { + envJSON.BlockHashes[math.HexOrDecimal64(num64)] = bhash + } + } + + envJSON.BaseFee = (*math.HexOrDecimal256)(env.BaseFee) + + return &envJSON +} + +func (env *SubstateEnv) SetJSON(envJSON *SubstateEnvJSON) { + env.Coinbase = envJSON.Coinbase + env.Difficulty = (*big.Int)(envJSON.Difficulty) + env.GasLimit = uint64(envJSON.GasLimit) + env.Number = uint64(envJSON.Number) + env.Timestamp = uint64(envJSON.Timestamp) + env.BlockHashes = make(map[uint64]common.Hash) + if envJSON.BlockHashes != nil { + for num64, bhash := range envJSON.BlockHashes { + env.BlockHashes[uint64(num64)] = bhash + } + } + + env.BaseFee = (*big.Int)(envJSON.BaseFee) + if env.BaseFee.Cmp(big.NewInt(0)) == 0 { + env.BaseFee = nil + } +} + +func (env SubstateEnv) MarshalJSON() ([]byte, error) { + return json.Marshal(NewSubstateEnvJSON(&env)) +} + +func (env *SubstateEnv) UnmarshalJSON(b []byte) error { + var err error + var envJSON SubstateEnvJSON + + err = json.Unmarshal(b, &envJSON) + if err != nil { + return err + } + + env.SetJSON(&envJSON) + + return nil +} + +// SubstateMessageJSON is modification of types.msgdata +type SubstateMessageJSON struct { + Nonce math.HexOrDecimal64 `json:"nonce" gencodec:"required"` + CheckNonce bool `json:"checkNonce" gencodec:"required"` + GasPrice *math.HexOrDecimal256 `json:"gasPrice" gencodec:"required"` + Gas math.HexOrDecimal64 `json:"gas" gencodec:"required"` + + From common.Address `json:"from"` + To *common.Address `json:"to"` // nil means contract creation + Value *math.HexOrDecimal256 `json:"value" gencodec:"required"` + Data hexutil.Bytes `json:"input" gencodec:"required"` + + AccessList types.AccessList `json:"accessList,omitempty"` + + GasFeeCap *math.HexOrDecimal256 `json:"gasFeeCap,omitempty"` + GasTipCap *math.HexOrDecimal256 `json:"gasTipCap,omitempty"` +} + +func NewSubstateMessageJSON(msg *SubstateMessage) *SubstateMessageJSON { + var msgJSON SubstateMessageJSON + + msgJSON.Nonce = math.HexOrDecimal64(msg.Nonce) + msgJSON.CheckNonce = msg.CheckNonce + msgJSON.GasPrice = (*math.HexOrDecimal256)(msg.GasPrice) + msgJSON.Gas = math.HexOrDecimal64(msg.Gas) + + msgJSON.From = msg.From + msgJSON.To = msg.To + msgJSON.Value = (*math.HexOrDecimal256)(msg.Value) + msgJSON.Data = hexutil.Bytes(msg.Data) + + msgJSON.AccessList = msg.AccessList + + msgJSON.GasFeeCap = (*math.HexOrDecimal256)(msg.GasFeeCap) + msgJSON.GasTipCap = (*math.HexOrDecimal256)(msg.GasTipCap) + + return &msgJSON +} + +func (msg *SubstateMessage) SetJSON(msgJSON *SubstateMessageJSON) { + msg.Nonce = uint64(msgJSON.Nonce) + msg.CheckNonce = msgJSON.CheckNonce + msg.GasPrice = (*big.Int)(msgJSON.GasPrice) + msg.Gas = uint64(msgJSON.Gas) + + msg.From = msgJSON.From + msg.To = msgJSON.To + msg.Value = (*big.Int)(msgJSON.Value) + msg.Data = []byte(msgJSON.Data) + + msg.AccessList = msgJSON.AccessList + + msg.GasFeeCap = (*big.Int)(msgJSON.GasFeeCap) + if msg.GasFeeCap.Cmp(big.NewInt(0)) == 0 { + msg.GasFeeCap = msg.GasPrice + } + msg.GasTipCap = (*big.Int)(msgJSON.GasTipCap) + if msg.GasTipCap.Cmp(big.NewInt(0)) == 0 { + msg.GasTipCap = msg.GasPrice + } +} + +func (msg SubstateMessage) MarshalJSON() ([]byte, error) { + return json.Marshal(NewSubstateMessageJSON(&msg)) +} + +func (msg *SubstateMessage) UnmarshalJSON(b []byte) error { + var err error + var msgJSON SubstateMessageJSON + + err = json.Unmarshal(b, &msgJSON) + if err != nil { + return err + } + + msg.SetJSON(&msgJSON) + + return nil +} + +type SubstateResultJSON struct { + Status math.HexOrDecimal64 `json:"status"` + Bloom types.Bloom `json:"logsBloom"` + Logs []*types.Log `json:"logs"` + + ContractAddress common.Address `json:"contractAddress"` + GasUsed math.HexOrDecimal64 `json:"gasUsed" gencodec:"required"` +} + +func NewSubstateResultJSON(result *SubstateResult) *SubstateResultJSON { + var resultJSON SubstateResultJSON + + resultJSON.Status = math.HexOrDecimal64(result.Status) + resultJSON.Bloom = result.Bloom + resultJSON.Logs = result.Logs + + resultJSON.ContractAddress = result.ContractAddress + resultJSON.GasUsed = math.HexOrDecimal64(result.GasUsed) + + return &resultJSON +} + +func (result *SubstateResult) SetJSON(resultJSON *SubstateResultJSON) { + result.Status = uint64(resultJSON.Status) + result.Bloom = resultJSON.Bloom + result.Logs = resultJSON.Logs + + result.ContractAddress = resultJSON.ContractAddress + result.GasUsed = uint64(resultJSON.GasUsed) +} + +func (result SubstateResult) MarshalJSON() ([]byte, error) { + return json.Marshal(NewSubstateResultJSON(&result)) +} + +func (result *SubstateResult) UnmarshalJSON(b []byte) error { + var err error + var resultJSON SubstateResultJSON + + err = json.Unmarshal(b, &resultJSON) + if err != nil { + return err + } + + result.SetJSON(&resultJSON) + + return nil +} + +type SubstateJSON struct { + InputAlloc SubstateAllocJSON `json:"inputAlloc"` + OutputAlloc SubstateAllocJSON `json:"outputAlloc"` + Env *SubstateEnvJSON `json:"env"` + Message *SubstateMessageJSON `json:"message"` + Result *SubstateResultJSON `json:"result"` +} + +func NewSubstateJSON(substate *Substate) *SubstateJSON { + var substateJSON SubstateJSON + + substateJSON.InputAlloc = NewSubstateAllocJSON(substate.InputAlloc) + substateJSON.OutputAlloc = NewSubstateAllocJSON(substate.OutputAlloc) + substateJSON.Env = NewSubstateEnvJSON(substate.Env) + substateJSON.Message = NewSubstateMessageJSON(substate.Message) + substateJSON.Result = NewSubstateResultJSON(substate.Result) + + return &substateJSON +} + +func (substate *Substate) SetJSON(substateJSON *SubstateJSON) { + substate.InputAlloc.SetJSON(substateJSON.InputAlloc) + substate.OutputAlloc.SetJSON(substateJSON.OutputAlloc) + substate.Env.SetJSON(substateJSON.Env) + substate.Message.SetJSON(substateJSON.Message) + substate.Result.SetJSON(substateJSON.Result) +} + +func (substate Substate) MarshalJSON() ([]byte, error) { + return json.Marshal(NewSubstateJSON(&substate)) +} + +func (substate *Substate) UnmarshalJSON(b []byte) error { + var err error + var substateJSON SubstateJSON + + err = json.Unmarshal(b, &substateJSON) + if err != nil { + return err + } + + substate.SetJSON(&substateJSON) + + return nil +} diff --git a/substate/substate_rlp.go b/substate/substate_rlp.go new file mode 100644 index 000000000..3f2ceffef --- /dev/null +++ b/substate/substate_rlp.go @@ -0,0 +1,409 @@ +package substate + +import ( + "math/big" + "sort" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +type SubstateAccountRLP struct { + Nonce uint64 + Balance *big.Int + CodeHash common.Hash + Storage [][2]common.Hash +} + +func NewSubstateAccountRLP(sa *SubstateAccount) *SubstateAccountRLP { + var saRLP SubstateAccountRLP + + saRLP.Nonce = sa.Nonce + saRLP.Balance = new(big.Int).Set(sa.Balance) + saRLP.CodeHash = sa.CodeHash() + sortedKeys := []common.Hash{} + for key := range sa.Storage { + sortedKeys = append(sortedKeys, key) + } + sort.Slice(sortedKeys, func(i, j int) bool { + return sortedKeys[i].Big().Cmp(sortedKeys[j].Big()) < 0 + }) + for _, key := range sortedKeys { + value := sa.Storage[key] + saRLP.Storage = append(saRLP.Storage, [2]common.Hash{key, value}) + } + + return &saRLP +} + +func (sa *SubstateAccount) SetRLP(saRLP *SubstateAccountRLP, db *SubstateDB) { + sa.Balance = saRLP.Balance + sa.Nonce = saRLP.Nonce + sa.Code = db.GetCode(saRLP.CodeHash) + sa.Storage = make(map[common.Hash]common.Hash) + for i := range saRLP.Storage { + sa.Storage[saRLP.Storage[i][0]] = saRLP.Storage[i][1] + } +} + +type SubstateAllocRLP struct { + Addresses []common.Address + Accounts []*SubstateAccountRLP +} + +func NewSubstateAllocRLP(alloc SubstateAlloc) SubstateAllocRLP { + var allocRLP SubstateAllocRLP + + allocRLP.Addresses = []common.Address{} + allocRLP.Accounts = []*SubstateAccountRLP{} + for addr := range alloc { + allocRLP.Addresses = append(allocRLP.Addresses, addr) + } + sort.Slice(allocRLP.Addresses, func(i, j int) bool { + return allocRLP.Addresses[i].Hash().Big().Cmp(allocRLP.Addresses[j].Hash().Big()) < 0 + }) + + for _, addr := range allocRLP.Addresses { + account := alloc[addr] + allocRLP.Accounts = append(allocRLP.Accounts, NewSubstateAccountRLP(account)) + } + + return allocRLP +} + +func (alloc *SubstateAlloc) SetRLP(allocRLP SubstateAllocRLP, db *SubstateDB) { + *alloc = make(SubstateAlloc) + for i, addr := range allocRLP.Addresses { + var sa SubstateAccount + + saRLP := allocRLP.Accounts[i] + sa.Balance = saRLP.Balance + sa.Nonce = saRLP.Nonce + sa.Code = db.GetCode(saRLP.CodeHash) + sa.Storage = make(map[common.Hash]common.Hash) + for i := range saRLP.Storage { + sa.Storage[saRLP.Storage[i][0]] = saRLP.Storage[i][1] + } + + (*alloc)[addr] = &sa + } +} + +type legacySubstateEnvRLP struct { + Coinbase common.Address + Difficulty *big.Int + GasLimit uint64 + Number uint64 + Timestamp uint64 + BlockHashes [][2]common.Hash +} + +func (envRLP *SubstateEnvRLP) setLegacyRLP(lenvRLP *legacySubstateEnvRLP) { + envRLP.Coinbase = lenvRLP.Coinbase + envRLP.Difficulty = lenvRLP.Difficulty + envRLP.GasLimit = lenvRLP.GasLimit + envRLP.Number = lenvRLP.Number + envRLP.Timestamp = lenvRLP.Timestamp + envRLP.BlockHashes = lenvRLP.BlockHashes +} + +type SubstateEnvRLP struct { + Coinbase common.Address + Difficulty *big.Int + GasLimit uint64 + Number uint64 + Timestamp uint64 + BlockHashes [][2]common.Hash + + BaseFee *common.Hash `rlp:"nil"` // missing in substate DB from Geth <= v1.10.3 +} + +func NewSubstateEnvRLP(env *SubstateEnv) *SubstateEnvRLP { + var envRLP SubstateEnvRLP + + envRLP.Coinbase = env.Coinbase + envRLP.Difficulty = env.Difficulty + envRLP.GasLimit = env.GasLimit + envRLP.Number = env.Number + envRLP.Timestamp = env.Timestamp + + sortedNum64 := []uint64{} + for num64 := range env.BlockHashes { + sortedNum64 = append(sortedNum64, num64) + } + for _, num64 := range sortedNum64 { + num := common.BigToHash(new(big.Int).SetUint64(num64)) + bhash := env.BlockHashes[num64] + pair := [2]common.Hash{num, bhash} + envRLP.BlockHashes = append(envRLP.BlockHashes, pair) + } + + envRLP.BaseFee = nil + if env.BaseFee != nil { + baseFeeHash := common.BigToHash(env.BaseFee) + envRLP.BaseFee = &baseFeeHash + } + + return &envRLP +} + +func (env *SubstateEnv) SetRLP(envRLP *SubstateEnvRLP, db *SubstateDB) { + env.Coinbase = envRLP.Coinbase + env.Difficulty = envRLP.Difficulty + env.GasLimit = envRLP.GasLimit + env.Number = envRLP.Number + env.Timestamp = envRLP.Timestamp + env.BlockHashes = make(map[uint64]common.Hash) + for i := range envRLP.BlockHashes { + pair := envRLP.BlockHashes[i] + num64 := pair[0].Big().Uint64() + bhash := pair[1] + env.BlockHashes[num64] = bhash + } + + env.BaseFee = nil + if envRLP.BaseFee != nil { + env.BaseFee = envRLP.BaseFee.Big() + } +} + +type legacySubstateMessageRLP struct { + Nonce uint64 + CheckNonce bool + GasPrice *big.Int + Gas uint64 + + From common.Address + To *common.Address `rlp:"nil"` // nil means contract creation + Value *big.Int + Data []byte + + InitCodeHash *common.Hash `rlp:"nil"` // NOT nil for contract creation +} + +func (msgRLP *SubstateMessageRLP) setLegacyRLP(lmsgRLP *legacySubstateMessageRLP) { + msgRLP.Nonce = lmsgRLP.Nonce + msgRLP.CheckNonce = lmsgRLP.CheckNonce + msgRLP.GasPrice = lmsgRLP.GasPrice + msgRLP.Gas = lmsgRLP.Gas + + msgRLP.From = lmsgRLP.From + msgRLP.To = lmsgRLP.To + msgRLP.Value = new(big.Int).Set(lmsgRLP.Value) + msgRLP.Data = lmsgRLP.Data + + msgRLP.InitCodeHash = lmsgRLP.InitCodeHash + + msgRLP.AccessList = nil + + // Same behavior as LegacyTx.gasFeeCap() and LegacyTx.gasTipCap() + msgRLP.GasFeeCap = lmsgRLP.GasPrice + msgRLP.GasTipCap = lmsgRLP.GasPrice +} + +type berlinSubstateMessageRLP struct { + Nonce uint64 + CheckNonce bool + GasPrice *big.Int + Gas uint64 + + From common.Address + To *common.Address `rlp:"nil"` // nil means contract creation + Value *big.Int + Data []byte + + InitCodeHash *common.Hash `rlp:"nil"` // NOT nil for contract creation + + AccessList types.AccessList // missing in substate DB from Geth v1.9.x +} + +func (msgRLP *SubstateMessageRLP) setBerlinRLP(bmsgRLP *berlinSubstateMessageRLP) { + msgRLP.Nonce = bmsgRLP.Nonce + msgRLP.CheckNonce = bmsgRLP.CheckNonce + msgRLP.GasPrice = bmsgRLP.GasPrice + msgRLP.Gas = bmsgRLP.Gas + + msgRLP.From = bmsgRLP.From + msgRLP.To = bmsgRLP.To + msgRLP.Value = new(big.Int).Set(bmsgRLP.Value) + msgRLP.Data = bmsgRLP.Data + + msgRLP.InitCodeHash = bmsgRLP.InitCodeHash + + msgRLP.AccessList = nil + + // Same behavior as AccessListTx.gasFeeCap() and AccessListTx.gasTipCap() + msgRLP.GasFeeCap = bmsgRLP.GasPrice + msgRLP.GasTipCap = bmsgRLP.GasPrice +} + +type SubstateMessageRLP struct { + Nonce uint64 + CheckNonce bool + GasPrice *big.Int + Gas uint64 + + From common.Address + To *common.Address `rlp:"nil"` // nil means contract creation + Value *big.Int + Data []byte + + InitCodeHash *common.Hash `rlp:"nil"` // NOT nil for contract creation + + AccessList types.AccessList // missing in substate DB from Geth v1.9.x + + GasFeeCap *big.Int // missing in substate DB from Geth <= v1.10.3 + GasTipCap *big.Int // missing in substate DB from Geth <= v1.10.3 +} + +func NewSubstateMessageRLP(msg *SubstateMessage) *SubstateMessageRLP { + var msgRLP SubstateMessageRLP + + msgRLP.Nonce = msg.Nonce + msgRLP.CheckNonce = msg.CheckNonce + msgRLP.GasPrice = msg.GasPrice + msgRLP.Gas = msg.Gas + + msgRLP.From = msg.From + msgRLP.To = msg.To + msgRLP.Value = new(big.Int).Set(msg.Value) + msgRLP.Data = msg.Data + + msgRLP.InitCodeHash = nil + + if msgRLP.To == nil { + // put contract creation init code into codeDB + dataHash := msg.DataHash() + msgRLP.Data = nil + msgRLP.InitCodeHash = &dataHash + } + + msgRLP.AccessList = msg.AccessList + + msgRLP.GasFeeCap = msg.GasFeeCap + msgRLP.GasTipCap = msg.GasTipCap + + return &msgRLP +} + +func (msg *SubstateMessage) SetRLP(msgRLP *SubstateMessageRLP, db *SubstateDB) { + msg.Nonce = msgRLP.Nonce + msg.CheckNonce = msgRLP.CheckNonce + msg.GasPrice = msgRLP.GasPrice + msg.Gas = msgRLP.Gas + + msg.From = msgRLP.From + msg.To = msgRLP.To + msg.Value = msgRLP.Value + msg.Data = msgRLP.Data + + if msgRLP.To == nil { + msg.Data = db.GetCode(*msgRLP.InitCodeHash) + } + + msg.AccessList = msgRLP.AccessList + + msg.GasFeeCap = msgRLP.GasFeeCap + msg.GasTipCap = msgRLP.GasTipCap +} + +type SubstateResultRLP struct { + Status uint64 + Bloom types.Bloom + Logs []*types.Log + + ContractAddress common.Address + GasUsed uint64 +} + +func NewSubstateResultRLP(result *SubstateResult) *SubstateResultRLP { + var resultRLP SubstateResultRLP + + resultRLP.Status = result.Status + resultRLP.Bloom = result.Bloom + resultRLP.Logs = result.Logs + + resultRLP.ContractAddress = result.ContractAddress + resultRLP.GasUsed = result.GasUsed + + return &resultRLP +} + +func (result *SubstateResult) SetRLP(resultRLP *SubstateResultRLP, db *SubstateDB) { + result.Status = resultRLP.Status + result.Bloom = resultRLP.Bloom + result.Logs = resultRLP.Logs + + result.ContractAddress = resultRLP.ContractAddress + result.GasUsed = resultRLP.GasUsed +} + +type legacySubstateRLP struct { + InputAlloc SubstateAllocRLP + OutputAlloc SubstateAllocRLP + Env *legacySubstateEnvRLP + Message *legacySubstateMessageRLP + Result *SubstateResultRLP +} + +func (substateRLP *SubstateRLP) setLegacyRLP(lsubstateRLP *legacySubstateRLP) { + substateRLP.InputAlloc = lsubstateRLP.InputAlloc + substateRLP.OutputAlloc = lsubstateRLP.OutputAlloc + substateRLP.Env = &SubstateEnvRLP{} + substateRLP.Env.setLegacyRLP(lsubstateRLP.Env) + substateRLP.Message = &SubstateMessageRLP{} + substateRLP.Message.setLegacyRLP(lsubstateRLP.Message) + substateRLP.Result = lsubstateRLP.Result +} + +type berlinSubstateRLP struct { + InputAlloc SubstateAllocRLP + OutputAlloc SubstateAllocRLP + Env *legacySubstateEnvRLP + Message *berlinSubstateMessageRLP + Result *SubstateResultRLP +} + +func (substateRLP *SubstateRLP) setBerlinRLP(bsubstateRLP *berlinSubstateRLP) { + substateRLP.InputAlloc = bsubstateRLP.InputAlloc + substateRLP.OutputAlloc = bsubstateRLP.OutputAlloc + substateRLP.Env = &SubstateEnvRLP{} + substateRLP.Env.setLegacyRLP(bsubstateRLP.Env) + substateRLP.Message = &SubstateMessageRLP{} + substateRLP.Message.setBerlinRLP(bsubstateRLP.Message) + substateRLP.Result = bsubstateRLP.Result +} + +type SubstateRLP struct { + InputAlloc SubstateAllocRLP + OutputAlloc SubstateAllocRLP + Env *SubstateEnvRLP + Message *SubstateMessageRLP + Result *SubstateResultRLP +} + +func NewSubstateRLP(substate *Substate) *SubstateRLP { + var substateRLP SubstateRLP + + substateRLP.InputAlloc = NewSubstateAllocRLP(substate.InputAlloc) + substateRLP.OutputAlloc = NewSubstateAllocRLP(substate.OutputAlloc) + substateRLP.Env = NewSubstateEnvRLP(substate.Env) + substateRLP.Message = NewSubstateMessageRLP(substate.Message) + substateRLP.Result = NewSubstateResultRLP(substate.Result) + + return &substateRLP +} + +func (substate *Substate) SetRLP(substateRLP *SubstateRLP, db *SubstateDB) { + substate.InputAlloc = make(SubstateAlloc) + substate.OutputAlloc = make(SubstateAlloc) + substate.Env = &SubstateEnv{} + substate.Message = &SubstateMessage{} + substate.Result = &SubstateResult{} + + substate.InputAlloc.SetRLP(substateRLP.InputAlloc, db) + substate.OutputAlloc.SetRLP(substateRLP.OutputAlloc, db) + substate.Env.SetRLP(substateRLP.Env, db) + substate.Message.SetRLP(substateRLP.Message, db) + substate.Result.SetRLP(substateRLP.Result, db) +} diff --git a/substate/substate_task.go b/substate/substate_task.go new file mode 100644 index 000000000..78aaa46ea --- /dev/null +++ b/substate/substate_task.go @@ -0,0 +1,256 @@ +package substate + +import ( + "fmt" + "runtime" + "sync" + "sync/atomic" + "time" + + "github.com/urfave/cli/v2" +) + +var ( + WorkersFlag = cli.IntFlag{ + Name: "workers", + Usage: "Number of worker threads that execute in parallel", + Value: 4, + } + SkipTransferTxsFlag = cli.BoolFlag{ + Name: "skip-transfer-txs", + Usage: "Skip executing transactions that only transfer ETH", + } + SkipCallTxsFlag = cli.BoolFlag{ + Name: "skip-call-txs", + Usage: "Skip executing CALL transactions to accounts with contract bytecode", + } + SkipCreateTxsFlag = cli.BoolFlag{ + Name: "skip-create-txs", + Usage: "Skip executing CREATE transactions", + } +) + +type SubstateBlockFunc func(block uint64, transactions map[int]*Substate, taskPool *SubstateTaskPool) error +type SubstateTaskFunc func(block uint64, tx int, substate *Substate, taskPool *SubstateTaskPool) error + +type SubstateTaskPool struct { + Name string + BlockFunc SubstateBlockFunc + TaskFunc SubstateTaskFunc + + First uint64 + Last uint64 + + Workers int + SkipTransferTxs bool + SkipCallTxs bool + SkipCreateTxs bool + + Ctx *cli.Context // CLI context required to read additional flags + + DB *SubstateDB +} + +func NewSubstateTaskPool(name string, taskFunc SubstateTaskFunc, first, last uint64, ctx *cli.Context) *SubstateTaskPool { + return &SubstateTaskPool{ + Name: name, + TaskFunc: taskFunc, + + First: first, + Last: last, + + Workers: ctx.Int(WorkersFlag.Name), + SkipTransferTxs: ctx.Bool(SkipTransferTxsFlag.Name), + SkipCallTxs: ctx.Bool(SkipCallTxsFlag.Name), + SkipCreateTxs: ctx.Bool(SkipCreateTxsFlag.Name), + + Ctx: ctx, + + DB: staticSubstateDB, + } +} + +// ExecuteBlock function iterates on substates of a given block call TaskFunc +func (pool *SubstateTaskPool) ExecuteBlock(block uint64) (numTx int64, err error) { + transactions := pool.DB.GetBlockSubstates(block) + if pool.BlockFunc != nil { + err := pool.BlockFunc(block, transactions, pool) + if err != nil { + return numTx, fmt.Errorf("%s: block %v: %v", pool.Name, block, err) + } + } + if pool.TaskFunc == nil { + return int64(len(transactions)), nil + } + for tx, substate := range transactions { + alloc := substate.InputAlloc + msg := substate.Message + + to := msg.To + if pool.SkipTransferTxs && to != nil { + // skip regular transactions (ETH transfer) + if account, exist := alloc[*to]; !exist || len(account.Code) == 0 { + continue + } + } + if pool.SkipCallTxs && to != nil { + // skip CALL trasnactions with contract bytecode + if account, exist := alloc[*to]; exist && len(account.Code) > 0 { + continue + } + } + if pool.SkipCreateTxs && to == nil { + // skip CREATE transactions + continue + } + + err = pool.TaskFunc(block, tx, substate, pool) + if err != nil { + return numTx, fmt.Errorf("%s: %v_%v: %v", pool.Name, block, tx, err) + } + + numTx++ + } + + return numTx, nil +} + +// Execute function spawns worker goroutines and schedule tasks. +func (pool *SubstateTaskPool) Execute() error { + start := time.Now() + + var totalNumBlock, totalNumTx int64 + defer func() { + duration := time.Since(start) + 1*time.Nanosecond + sec := duration.Seconds() + + nb, nt := atomic.LoadInt64(&totalNumBlock), atomic.LoadInt64(&totalNumTx) + blkPerSec := float64(nb) / sec + txPerSec := float64(nt) / sec + fmt.Printf("%s: block range = %v %v\n", pool.Name, pool.First, pool.Last) + fmt.Printf("%s: total #block = %v\n", pool.Name, nb) + fmt.Printf("%s: total #tx = %v\n", pool.Name, nt) + fmt.Printf("%s: %.2f blk/s, %.2f tx/s\n", pool.Name, blkPerSec, txPerSec) + fmt.Printf("%s done in %v\n", pool.Name, duration.Round(1*time.Millisecond)) + }() + + // numProcs = numWorker + work producer (1) + main thread (1) + numProcs := pool.Workers + 2 + if goMaxProcs := runtime.GOMAXPROCS(0); goMaxProcs < numProcs { + runtime.GOMAXPROCS(numProcs) + } + + fmt.Printf("%s: block range = %v %v\n", pool.Name, pool.First, pool.Last) + fmt.Printf("%s: #CPU = %v, #worker = %v\n", pool.Name, runtime.NumCPU(), pool.Workers) + + workChan := make(chan uint64, pool.Workers*10) + doneChan := make(chan interface{}, pool.Workers*10) + stopChan := make(chan struct{}, pool.Workers) + wg := sync.WaitGroup{} + defer func() { + // stop all workers + for i := 0; i < pool.Workers; i++ { + stopChan <- struct{}{} + } + // stop work producer (1) + stopChan <- struct{}{} + + wg.Wait() + close(workChan) + close(doneChan) + }() + // dynamically schedule one block per worker + for i := 0; i < pool.Workers; i++ { + wg.Add(1) + // worker goroutine + go func() { + defer wg.Done() + + for { + select { + + case block := <-workChan: + nt, err := pool.ExecuteBlock(block) + atomic.AddInt64(&totalNumTx, nt) + atomic.AddInt64(&totalNumBlock, 1) + if err != nil { + doneChan <- err + } else { + doneChan <- block + } + + case <-stopChan: + return + + } + } + }() + } + + // wait until all workers finish all tasks + wg.Add(1) + go func() { + defer wg.Done() + + for block := pool.First; block <= pool.Last; block++ { + select { + + case workChan <- block: + continue + + case <-stopChan: + return + + } + } + }() + + // Count finished blocks in order and report execution speed + var lastSec float64 + var lastNumBlock, lastNumTx int64 + waitMap := make(map[uint64]struct{}) + for block := pool.First; block <= pool.Last; { + + // Count finshed blocks from waitMap in order + if _, ok := waitMap[block]; ok { + delete(waitMap, block) + + block++ + continue + } + + duration := time.Since(start) + 1*time.Nanosecond + sec := duration.Seconds() + if block == pool.Last || + (block%10000 == 0 && sec > lastSec+5) || + (block%1000 == 0 && sec > lastSec+10) || + (block%100 == 0 && sec > lastSec+20) || + (block%10 == 0 && sec > lastSec+40) || + (sec > lastSec+60) { + nb, nt := atomic.LoadInt64(&totalNumBlock), atomic.LoadInt64(&totalNumTx) + blkPerSec := float64(nb-lastNumBlock) / (sec - lastSec) + txPerSec := float64(nt-lastNumTx) / (sec - lastSec) + fmt.Printf("%s: elapsed time: %v, number = %v\n", pool.Name, duration.Round(1*time.Millisecond), block) + fmt.Printf("%s: %.2f blk/s, %.2f tx/s\n", pool.Name, blkPerSec, txPerSec) + + lastSec, lastNumBlock, lastNumTx = sec, nb, nt + } + + data := <-doneChan + switch t := data.(type) { + + case uint64: + waitMap[data.(uint64)] = struct{}{} + + case error: + err := data.(error) + return err + + default: + panic(fmt.Errorf("%s: unknown type %T value from doneChan", pool.Name, t)) + + } + } + + return nil +} diff --git a/substate/update_db.go b/substate/update_db.go new file mode 100644 index 000000000..2708e7ae1 --- /dev/null +++ b/substate/update_db.go @@ -0,0 +1,313 @@ +package substate + +import ( + "encoding/binary" + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethdb" + "github.com/ethereum/go-ethereum/rlp" +) + +type UpdateSetRLP struct { + SubstateAlloc SubstateAllocRLP + DeletedAccounts []common.Address +} + +func NewUpdateSetRLP(updateset SubstateAlloc, deletedAccounts []common.Address) UpdateSetRLP { + var rlp UpdateSetRLP + + rlp.SubstateAlloc = NewSubstateAllocRLP(updateset) + rlp.DeletedAccounts = deletedAccounts + return rlp + +} + +const ( + SubstateAllocPrefix = "2s" // SubstateAllocPrefix + block (64-bit) + tx (64-bit) -> substateRLP +) + +func SubstateAllocKey(block uint64) []byte { + prefix := []byte(SubstateAllocPrefix) + blockTx := make([]byte, 8) + binary.BigEndian.PutUint64(blockTx[0:8], block) + return append(prefix, blockTx...) +} + +func DecodeUpdateSetKey(key []byte) (block uint64, err error) { + prefix := SubstateAllocPrefix + if len(key) != len(prefix)+8 { + err = fmt.Errorf("invalid length of updateset key: %v", len(key)) + return + } + if p := string(key[:len(prefix)]); p != prefix { + err = fmt.Errorf("invalid prefix of updateset key: %#x", p) + return + } + blockTx := key[len(prefix):] + block = binary.BigEndian.Uint64(blockTx[0:8]) + return +} + +type UpdateDB struct { + backend BackendDatabase +} + +func NewUpdateDB(backend BackendDatabase) *UpdateDB { + return &UpdateDB{backend: backend} +} + +func OpenUpdateDB(updateSetDir string) (*UpdateDB, error) { + fmt.Println("substate: OpenUpdateSetDB") + backend, err := rawdb.NewLevelDBDatabase(updateSetDir, 1024, 100, "updatesetdir", false) + if err != nil { + return nil, fmt.Errorf("error opening update-set leveldb %s: %v", updateSetDir, err) + } + return NewUpdateDB(backend), nil +} + +func OpenUpdateDBReadOnly(updateSetDir string) (*UpdateDB, error) { + fmt.Println("substate: OpenUpdateSetDB") + backend, err := rawdb.NewLevelDBDatabase(updateSetDir, 1024, 100, "updatesetdir", true) + if err != nil { + return nil, fmt.Errorf("error opening update-set leveldb %s: %v", updateSetDir, err) + } + return NewUpdateDB(backend), nil +} + +func (db *UpdateDB) Compact(start []byte, limit []byte) error { + return db.backend.Compact(start, limit) +} + +func (db *UpdateDB) Close() error { + return db.backend.Close() +} + +func (db *UpdateDB) GetLastKey() uint64 { + var block uint64 + var err error + iter := db.backend.NewIterator([]byte(SubstateAllocPrefix), nil) + for iter.Next() { + block, err = DecodeUpdateSetKey(iter.Key()) + if err != nil { + panic(fmt.Errorf("error iterating updateDB: %v", err)) + } + } + iter.Release() + return block +} + +func (db *UpdateDB) HasCode(codeHash common.Hash) bool { + if codeHash == EmptyCodeHash { + return false + } + key := Stage1CodeKey(codeHash) + has, err := db.backend.Has(key) + if err != nil { + panic(fmt.Errorf("substate: error checking bytecode for codeHash %s: %v", codeHash.Hex(), err)) + } + return has +} + +func (db *UpdateDB) GetCode(codeHash common.Hash) []byte { + if codeHash == EmptyCodeHash { + return nil + } + key := Stage1CodeKey(codeHash) + code, err := db.backend.Get(key) + if err != nil { + panic(fmt.Errorf("substate: error getting code %s: %v", codeHash.Hex(), err)) + } + return code +} + +func (db *UpdateDB) PutCode(code []byte) { + if len(code) == 0 { + return + } + codeHash := crypto.Keccak256Hash(code) + key := Stage1CodeKey(codeHash) + err := db.backend.Put(key, code) + if err != nil { + panic(fmt.Errorf("substate: error putting code %s: %v", codeHash.Hex(), err)) + } +} + +func (db *UpdateDB) HasUpdateSet(block uint64) bool { + key := SubstateAllocKey(block) + has, _ := db.backend.Has(key) + return has +} + +func (up *UpdateSetRLP) GetSubstateAlloc(db *UpdateDB) *SubstateAlloc { + alloc := make(SubstateAlloc) + for i, addr := range up.SubstateAlloc.Addresses { + var sa SubstateAccount + saRLP := up.SubstateAlloc.Accounts[i] + sa.Balance = saRLP.Balance + sa.Nonce = saRLP.Nonce + sa.Code = db.GetCode(saRLP.CodeHash) + sa.Storage = make(map[common.Hash]common.Hash) + for i := range saRLP.Storage { + sa.Storage[saRLP.Storage[i][0]] = saRLP.Storage[i][1] + } + alloc[addr] = &sa + } + return &alloc +} + +func (db *UpdateDB) GetUpdateSet(block uint64) *SubstateAlloc { + var err error + key := SubstateAllocKey(block) + value, err := db.backend.Get(key) + if err != nil { + panic(fmt.Errorf("substate: error getting substate %v from substate DB: %v,", block, err)) + } + // decode value + updateSetRLP := UpdateSetRLP{} + if err := rlp.DecodeBytes(value, &updateSetRLP); err != nil { + panic(fmt.Errorf("substate: failed to decode updateset value at block %v, key %v", block, key)) + } + updateSet := updateSetRLP.GetSubstateAlloc(db) + return updateSet +} + +func (db *UpdateDB) PutUpdateSet(block uint64, updateSet *SubstateAlloc, deletedAccounts []common.Address) { + var err error + + // put deployed/creation code + for _, account := range *updateSet { + db.PutCode(account.Code) + } + key := SubstateAllocKey(block) + defer func() { + if err != nil { + panic(fmt.Errorf("substate: error putting update-set %v into substate DB: %v", block, err)) + } + }() + + updateSetRLP := NewUpdateSetRLP(*updateSet, deletedAccounts) + + value, err := rlp.EncodeToBytes(updateSetRLP) + if err != nil { + panic(err) + } + err = db.backend.Put(key, value) + if err != nil { + panic(err) + } +} + +func (db *UpdateDB) DeleteSubstateAlloc(block uint64) { + key := SubstateAllocKey(block) + err := db.backend.Delete(key) + if err != nil { + panic(err) + } +} + +type UpdateBlock struct { + Block uint64 + UpdateSet *SubstateAlloc + DeletedAccounts []common.Address +} + +func parseUpdateSet(db *UpdateDB, data rawEntry) *UpdateBlock { + key := data.key + value := data.value + + block, err := DecodeUpdateSetKey(data.key) + if err != nil { + panic(fmt.Errorf("substate: invalid update-set key found: %v - issue: %v", key, err)) + } + + updateSetRLP := UpdateSetRLP{} + rlp.DecodeBytes(value, &updateSetRLP) + updateSet := updateSetRLP.GetSubstateAlloc(db) + + return &UpdateBlock{ + Block: block, + UpdateSet: updateSet, + DeletedAccounts: updateSetRLP.DeletedAccounts, + } +} + +type UpdateSetIterator struct { + db *UpdateDB + iter ethdb.Iterator + cur *UpdateBlock + + // Connections to parsing pipeline + source <-chan *UpdateBlock + done chan<- int +} + +func NewUpdateSetIterator(db *UpdateDB, startBlock, endBlock uint64) UpdateSetIterator { + start := BlockToBytes(startBlock) + // updateset prefix is already in start + iter := db.backend.NewIterator([]byte(SubstateAllocPrefix), start) + + done := make(chan int) + result := make(chan *UpdateBlock, 1) + + go func() { + defer close(result) + for iter.Next() { + + key := make([]byte, len(iter.Key())) + copy(key, iter.Key()) + + // Decode key, if past the end block, stop here. + // This avoids filling channels which huge data objects that are not consumed. + block, err := DecodeUpdateSetKey(key) + if err != nil { + panic(fmt.Errorf("worldstate-upate: invalid update-set key found: %v - issue: %v", key, err)) + } + if block > endBlock { + return + } + + value := make([]byte, len(iter.Value())) + copy(value, iter.Value()) + + raw := rawEntry{key, value} + + select { + case <-done: + return + case result <- parseUpdateSet(db, raw): //fall-through + } + } + }() + + return UpdateSetIterator{ + db: db, + iter: iter, + source: result, + done: done, + } +} + +func (i *UpdateSetIterator) Release() { + close(i.done) + + // drain pipeline until the result channel is closed + for open := true; open; _, open = <-i.source { + } + + i.iter.Release() +} + +func (i *UpdateSetIterator) Next() bool { + if i.iter == nil { + return false + } + i.cur = <-i.source + return i.cur != nil +} + +func (i *UpdateSetIterator) Value() *UpdateBlock { + return i.cur +} From 58a5254d39f5cec6e1a5cd1eba0a5785a37b57ad Mon Sep 17 00:00:00 2001 From: Jan Kalina Date: Mon, 3 Jul 2023 11:51:15 +0200 Subject: [PATCH 05/10] Add Len/CountToPop into txs sorting structure (#38) --- core/types/transaction.go | 19 +++++++++++++++++++ core/types/transaction_test.go | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/core/types/transaction.go b/core/types/transaction.go index 793d58857..a08c1c3d8 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -569,6 +569,25 @@ func (t *TransactionsByPriceAndNonce) Pop() { heap.Pop(&t.heads) } +// GetCountToPop provides the amount of txs, which will be removed if Pop is called +func (t *TransactionsByPriceAndNonce) GetCountToPop() int { + acc, _ := Sender(t.signer, t.heads[0].tx) + if txs, ok := t.txs[acc]; ok { + return len(txs) + 1 + } + return 0 +} + +// Len provides the total amount of txs in the structure +func (t *TransactionsByPriceAndNonce) Len() int { + length := 0 + for _, head := range t.heads { + acc, _ := Sender(t.signer, head.tx) + length += len(t.txs[acc]) + 1 + } + return length +} + func (t *TransactionsByPriceAndNonce) Copy() *TransactionsByPriceAndNonce { txsCopy := make(map[common.Address]Transactions, len(t.txs)) for k, v := range t.txs { diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go index 58c95071b..cc1f94a4a 100644 --- a/core/types/transaction_test.go +++ b/core/types/transaction_test.go @@ -527,3 +527,37 @@ func assertEqual(orig *Transaction, cpy *Transaction) error { } return nil } + +func TestTransactionsByPriceAndNonceLen(t *testing.T) { + keys := make([]*ecdsa.PrivateKey, 5) + for i := 0; i < len(keys); i++ { + keys[i], _ = crypto.GenerateKey() + } + signer := HomesteadSigner{} + groups := map[common.Address]Transactions{} + for _, key := range keys { + addr := crypto.PubkeyToAddress(key.PublicKey) + for nonce := uint64(0); nonce < 5; nonce++ { + tx, _ := SignTx(NewTransaction(nonce, common.Address{}, big.NewInt(100), 100, big.NewInt(1), nil), signer, key) + groups[addr] = append(groups[addr], tx) + } + } + txset := NewTransactionsByPriceAndNonce(signer, groups, nil) + if txset.Len() != 25 { + t.Errorf("intial len is %d", txset.Len()) + } + if txset.GetCountToPop() != 5 { + t.Errorf("intial amount to pop is %d", txset.GetCountToPop()) + } + txset.Pop() + if txset.Len() != 20 { + t.Errorf("length after first pop is %d", txset.Len()) + } + txset.Shift() + if txset.Len() != 19 { + t.Errorf("length after shift is %d", txset.Len()) + } + if txset.GetCountToPop() != 4 { + t.Errorf("amount to pop after shift is %d", txset.GetCountToPop()) + } +} From 634958c14f331bd58da8c19243f848fec1269675 Mon Sep 17 00:00:00 2001 From: Egor Lysenko Date: Sat, 15 Jul 2023 19:06:56 +0400 Subject: [PATCH 06/10] fix tx sender caching --- core/types/transaction_signing.go | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go index 33522c873..e47fb5367 100644 --- a/core/types/transaction_signing.go +++ b/core/types/transaction_signing.go @@ -534,20 +534,28 @@ type CachedSigner struct { cache SenderCache } -func WrapWithCachedSigner(signer Signer, cache SenderCache) *CachedSigner { - return &CachedSigner{ +func WrapWithCachedSigner(signer Signer, cache SenderCache) CachedSigner { + return CachedSigner{ Signer: signer, cache: cache, } } + +func (cs CachedSigner) Equal(s2 Signer) bool { + cs2, ok := s2.(CachedSigner) + if ok { + // unwrap the signer + return cs.Signer.Equal(cs2.Signer) + } + return cs.Signer.Equal(s2) +} + func (cs CachedSigner) Sender(tx *Transaction) (common.Address, error) { - if tx.from.Load() == nil { - // try to load the sender from the global cache - cached := cs.cache.Get(tx.Hash()) - if cached != nil && cached.Signer.Equal(cs.Signer) { - return cached.From, nil - } + // try to load the sender from the global cache + cached := cs.cache.Get(tx.Hash()) + if cached != nil && cached.Signer.Equal(cs.Signer) { + return cached.From, nil } from, err := cs.Signer.Sender(tx) if err != nil { From 8b8bb4a2a7fbbc558aff95612585ab5becb58acd Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 7 Sep 2023 14:48:49 +0200 Subject: [PATCH 07/10] log: avoid stack lookups when not needed/used (#28069) Avoids the somewhat expensive stack.Caller invocation by checking if it is needed --- log/format.go | 8 ++++++ log/handler_glog.go | 6 ++++ log/logger.go | 9 ++++-- log/logger_test.go | 67 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 log/logger_test.go diff --git a/log/format.go b/log/format.go index baf8fddac..765b423d7 100644 --- a/log/format.go +++ b/log/format.go @@ -35,8 +35,16 @@ func PrintOrigins(print bool) { } else { atomic.StoreUint32(&locationEnabled, 0) } + if print { + stackEnabled.Store(true) + } } +// stackEnabled is an atomic flag controlling whether the log handler needs +// to store the callsite stack. This is needed in case any handler wants to +// print locations (locationEnabled), use vmodule, or print full stacks (BacktraceAt). +var stackEnabled atomic.Bool + // locationEnabled is an atomic flag controlling whether the terminal formatter // should append the log locations too when printing entries. var locationEnabled uint32 diff --git a/log/handler_glog.go b/log/handler_glog.go index 9b1d4efaf..a71b1981b 100644 --- a/log/handler_glog.go +++ b/log/handler_glog.go @@ -140,6 +140,10 @@ func (h *GlogHandler) Vmodule(ruleset string) error { h.siteCache = make(map[uintptr]Lvl) atomic.StoreUint32(&h.override, uint32(len(filter))) + // Enable location storage (globally) + if len(h.patterns) > 0 { + stackEnabled.Store(true) + } return nil } @@ -173,6 +177,8 @@ func (h *GlogHandler) BacktraceAt(location string) error { h.location = location atomic.StoreUint32(&h.backtrace, uint32(len(location))) + // Enable location storage (globally) + stackEnabled.Store(true) return nil } diff --git a/log/logger.go b/log/logger.go index 276d6969e..2e66d0841 100644 --- a/log/logger.go +++ b/log/logger.go @@ -131,19 +131,22 @@ type logger struct { } func (l *logger) write(msg string, lvl Lvl, ctx []interface{}, skip int) { - l.h.Log(&Record{ + record := &Record{ Time: time.Now(), Lvl: lvl, Msg: msg, Ctx: newContext(l.ctx, ctx), - Call: stack.Caller(skip), KeyNames: RecordKeyNames{ Time: timeKey, Msg: msgKey, Lvl: lvlKey, Ctx: ctxKey, }, - }) + } + if stackEnabled.Load() { + record.Call = stack.Caller(skip) + } + l.h.Log(record) } func (l *logger) New(ctx ...interface{}) Logger { diff --git a/log/logger_test.go b/log/logger_test.go new file mode 100644 index 000000000..2e59b3fdf --- /dev/null +++ b/log/logger_test.go @@ -0,0 +1,67 @@ +package log + +import ( + "bytes" + "os" + "strings" + "testing" +) + +// TestLoggingWithTrace checks that if BackTraceAt is set, then the +// gloghandler is capable of spitting out a stacktrace +func TestLoggingWithTrace(t *testing.T) { + defer stackEnabled.Store(stackEnabled.Load()) + out := new(bytes.Buffer) + logger := New() + { + glog := NewGlogHandler(StreamHandler(out, TerminalFormat(false))) + glog.Verbosity(LvlTrace) + if err := glog.BacktraceAt("logger_test.go:24"); err != nil { + t.Fatal(err) + } + logger.SetHandler(glog) + } + logger.Trace("a message", "foo", "bar") // Will be bumped to INFO + have := out.String() + if !strings.HasPrefix(have, "INFO") { + t.Fatalf("backtraceat should bump level to info: %s", have) + } + // The timestamp is locale-dependent, so we want to trim that off + // "INFO [01-01|00:00:00.000] a messag ..." -> "a messag..." + have = strings.Split(have, "]")[1] + wantPrefix := " a message\n\ngoroutine" + if !strings.HasPrefix(have, wantPrefix) { + t.Errorf("\nhave: %q\nwant: %q\n", have, wantPrefix) + } +} + +// TestLoggingWithVmodule checks that vmodule works. +func TestLoggingWithVmodule(t *testing.T) { + defer stackEnabled.Store(stackEnabled.Load()) + out := new(bytes.Buffer) + logger := New() + { + glog := NewGlogHandler(StreamHandler(out, TerminalFormat(false))) + glog.Verbosity(LvlCrit) + logger.SetHandler(glog) + logger.Warn("This should not be seen", "ignored", "true") + glog.Vmodule("logger_test.go=5") + } + logger.Trace("a message", "foo", "bar") + have := out.String() + // The timestamp is locale-dependent, so we want to trim that off + // "INFO [01-01|00:00:00.000] a messag ..." -> "a messag..." + have = strings.Split(have, "]")[1] + want := " a message foo=bar\n" + if have != want { + t.Errorf("\nhave: %q\nwant: %q\n", have, want) + } +} + +func BenchmarkTraceLogging(b *testing.B) { + Root().SetHandler(LvlFilterHandler(LvlInfo, StreamHandler(os.Stderr, TerminalFormat(true)))) + b.ResetTimer() + for i := 0; i < b.N; i++ { + Trace("a message", "v", i) + } +} From febfe681b4a74450299c8a48d97d13d50108aa69 Mon Sep 17 00:00:00 2001 From: Jan Kalina Date: Tue, 3 Oct 2023 13:23:06 +0100 Subject: [PATCH 08/10] Add Release() method into StateDB interface (#43) --- core/state/adapter.go | 1 + core/state/statedb.go | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/core/state/adapter.go b/core/state/adapter.go index 4e7e0943c..9feddbfd6 100644 --- a/core/state/adapter.go +++ b/core/state/adapter.go @@ -83,6 +83,7 @@ type StateDbInterface interface { GetSubstatePostAlloc() substate.SubstateAlloc BeginBlock(number uint64) EndBlock(number uint64) + Release() } type StateDB struct { diff --git a/core/state/statedb.go b/core/state/statedb.go index 46721668f..52f92d953 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -1137,6 +1137,10 @@ func (s *LegacyStateDB) EndBlock(number uint64) { // not used by LegacyStateDB } +func (s *LegacyStateDB) Release() { + // not used by LegacyStateDB +} + func (s *LegacyStateDB) GetAccountReads() time.Duration { return s.AccountReads } From c0bb0c72b8e0ca5e78a15b102adf6d75f8c4ef3a Mon Sep 17 00:00:00 2001 From: s7v7nislands Date: Thu, 20 Apr 2023 15:36:54 +0800 Subject: [PATCH 09/10] metrics: use atomic type (#27121) --- metrics/counter.go | 14 +++++++------- metrics/ewma.go | 8 ++++---- metrics/gauge.go | 12 ++++++------ metrics/meter.go | 25 ++++++++++++++----------- 4 files changed, 31 insertions(+), 28 deletions(-) diff --git a/metrics/counter.go b/metrics/counter.go index 2f78c90d5..55e1c5954 100644 --- a/metrics/counter.go +++ b/metrics/counter.go @@ -38,13 +38,13 @@ func NewCounter() Counter { if !Enabled { return NilCounter{} } - return &StandardCounter{0} + return &StandardCounter{} } // NewCounterForced constructs a new StandardCounter and returns it no matter if // the global switch is enabled or not. func NewCounterForced() Counter { - return &StandardCounter{0} + return &StandardCounter{} } // NewRegisteredCounter constructs and registers a new StandardCounter. @@ -115,27 +115,27 @@ func (NilCounter) Snapshot() Counter { return NilCounter{} } // StandardCounter is the standard implementation of a Counter and uses the // sync/atomic package to manage a single int64 value. type StandardCounter struct { - count int64 + count atomic.Int64 } // Clear sets the counter to zero. func (c *StandardCounter) Clear() { - atomic.StoreInt64(&c.count, 0) + c.count.Store(0) } // Count returns the current count. func (c *StandardCounter) Count() int64 { - return atomic.LoadInt64(&c.count) + return c.count.Load() } // Dec decrements the counter by the given amount. func (c *StandardCounter) Dec(i int64) { - atomic.AddInt64(&c.count, -i) + c.count.Add(-i) } // Inc increments the counter by the given amount. func (c *StandardCounter) Inc(i int64) { - atomic.AddInt64(&c.count, i) + c.count.Add(i) } // Snapshot returns a read-only copy of the counter. diff --git a/metrics/ewma.go b/metrics/ewma.go index 039286493..ed95cba19 100644 --- a/metrics/ewma.go +++ b/metrics/ewma.go @@ -75,7 +75,7 @@ func (NilEWMA) Update(n int64) {} // of uncounted events and processes them on each tick. It uses the // sync/atomic package to manage uncounted events. type StandardEWMA struct { - uncounted int64 // /!\ this should be the first member to ensure 64-bit alignment + uncounted atomic.Int64 alpha float64 rate float64 init bool @@ -97,8 +97,8 @@ func (a *StandardEWMA) Snapshot() EWMA { // Tick ticks the clock to update the moving average. It assumes it is called // every five seconds. func (a *StandardEWMA) Tick() { - count := atomic.LoadInt64(&a.uncounted) - atomic.AddInt64(&a.uncounted, -count) + count := a.uncounted.Load() + a.uncounted.Add(-count) instantRate := float64(count) / float64(5*time.Second) a.mutex.Lock() defer a.mutex.Unlock() @@ -112,5 +112,5 @@ func (a *StandardEWMA) Tick() { // Update adds n uncounted events. func (a *StandardEWMA) Update(n int64) { - atomic.AddInt64(&a.uncounted, n) + a.uncounted.Add(n) } diff --git a/metrics/gauge.go b/metrics/gauge.go index b6b2758b0..81137d7f7 100644 --- a/metrics/gauge.go +++ b/metrics/gauge.go @@ -25,7 +25,7 @@ func NewGauge() Gauge { if !Enabled { return NilGauge{} } - return &StandardGauge{0} + return &StandardGauge{} } // NewRegisteredGauge constructs and registers a new StandardGauge. @@ -101,7 +101,7 @@ func (NilGauge) Value() int64 { return 0 } // StandardGauge is the standard implementation of a Gauge and uses the // sync/atomic package to manage a single int64 value. type StandardGauge struct { - value int64 + value atomic.Int64 } // Snapshot returns a read-only copy of the gauge. @@ -111,22 +111,22 @@ func (g *StandardGauge) Snapshot() Gauge { // Update updates the gauge's value. func (g *StandardGauge) Update(v int64) { - atomic.StoreInt64(&g.value, v) + g.value.Store(v) } // Value returns the gauge's current value. func (g *StandardGauge) Value() int64 { - return atomic.LoadInt64(&g.value) + return g.value.Load() } // Dec decrements the gauge's current value by the given amount. func (g *StandardGauge) Dec(i int64) { - atomic.AddInt64(&g.value, -i) + g.value.Add(-i) } // Inc increments the gauge's current value by the given amount. func (g *StandardGauge) Inc(i int64) { - atomic.AddInt64(&g.value, i) + g.value.Add(i) } // FunctionalGauge returns value from given function diff --git a/metrics/meter.go b/metrics/meter.go index 60ae919d0..e8564d6a5 100644 --- a/metrics/meter.go +++ b/metrics/meter.go @@ -101,11 +101,7 @@ func NewRegisteredMeterForced(name string, r Registry) Meter { // MeterSnapshot is a read-only copy of another Meter. type MeterSnapshot struct { - // WARNING: The `temp` field is accessed atomically. - // On 32 bit platforms, only 64-bit aligned fields can be atomic. The struct is - // guaranteed to be so aligned, so take advantage of that. For more information, - // see https://golang.org/pkg/sync/atomic/#pkg-note-BUG. - temp int64 + temp atomic.Int64 count int64 rate1, rate5, rate15, rateMean float64 } @@ -173,7 +169,7 @@ type StandardMeter struct { snapshot *MeterSnapshot a1, a5, a15 EWMA startTime time.Time - stopped uint32 + stopped atomic.Bool } func newStandardMeter() *StandardMeter { @@ -188,8 +184,8 @@ func newStandardMeter() *StandardMeter { // Stop stops the meter, Mark() will be a no-op if you use it after being stopped. func (m *StandardMeter) Stop() { - stopped := atomic.SwapUint32(&m.stopped, 1) - if stopped != 1 { + stopped := m.stopped.Swap(true) + if !stopped { arbiter.Lock() delete(arbiter.meters, m) arbiter.Unlock() @@ -207,7 +203,7 @@ func (m *StandardMeter) Count() int64 { // Mark records the occurrence of n events. func (m *StandardMeter) Mark(n int64) { - atomic.AddInt64(&m.snapshot.temp, n) + m.snapshot.temp.Add(n) } // Rate1 returns the one-minute moving average rate of events per second. @@ -241,7 +237,14 @@ func (m *StandardMeter) RateMean() float64 { // Snapshot returns a read-only copy of the meter. func (m *StandardMeter) Snapshot() Meter { m.lock.RLock() - snapshot := *m.snapshot + snapshot := MeterSnapshot{ + count: m.snapshot.count, + rate1: m.snapshot.rate1, + rate5: m.snapshot.rate5, + rate15: m.snapshot.rate15, + rateMean: m.snapshot.rateMean, + } + snapshot.temp.Store(m.snapshot.temp.Load()) m.lock.RUnlock() return &snapshot } @@ -257,7 +260,7 @@ func (m *StandardMeter) updateSnapshot() { func (m *StandardMeter) updateMeter() { // should only run with write lock held on m.lock - n := atomic.SwapInt64(&m.snapshot.temp, 0) + n := m.snapshot.temp.Swap(0) m.snapshot.count += n m.a1.Update(n) m.a5.Update(n) From 74e5aad311f7bea6207a87b3a7b996f1885242d2 Mon Sep 17 00:00:00 2001 From: Herbert Jordan Date: Thu, 14 Mar 2024 14:41:31 +0100 Subject: [PATCH 10/10] Revert "Port to v1.10.8-ftm-rc11" This reverts commit 1a14fdc1d4be9b8f67c0c91655a998256102604b. --- core/state/adapter.go | 2 +- core/state/state_object.go | 2 +- core/state/statedb.go | 2 +- core/vm/instructions.go | 2 +- go.mod | 7 +- go.sum | 122 +++++++-- substate/destroyed_account_db.go | 142 ---------- substate/metadata.go | 47 ---- substate/static_substate_db.go | 107 -------- substate/substate.go | 396 --------------------------- substate/substate_db.go | 447 ------------------------------- substate/substate_json.go | 347 ------------------------ substate/substate_rlp.go | 409 ---------------------------- substate/substate_task.go | 256 ------------------ substate/update_db.go | 313 ---------------------- 15 files changed, 114 insertions(+), 2487 deletions(-) delete mode 100644 substate/destroyed_account_db.go delete mode 100644 substate/metadata.go delete mode 100644 substate/static_substate_db.go delete mode 100644 substate/substate.go delete mode 100644 substate/substate_db.go delete mode 100644 substate/substate_json.go delete mode 100644 substate/substate_rlp.go delete mode 100644 substate/substate_task.go delete mode 100644 substate/update_db.go diff --git a/core/state/adapter.go b/core/state/adapter.go index 9feddbfd6..787846abd 100644 --- a/core/state/adapter.go +++ b/core/state/adapter.go @@ -2,10 +2,10 @@ package state import ( "encoding/json" + substate "github.com/Fantom-foundation/Substate" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state/snapshot" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/substate" "math/big" "time" ) diff --git a/core/state/state_object.go b/core/state/state_object.go index 5ac7c97c8..990deee76 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -19,6 +19,7 @@ package state import ( "bytes" "fmt" + substate "github.com/Fantom-foundation/Substate" "io" "math/big" "time" @@ -27,7 +28,6 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/substate" ) var emptyCodeHash = crypto.Keccak256(nil) diff --git a/core/state/statedb.go b/core/state/statedb.go index 52f92d953..2b1f2711a 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -24,6 +24,7 @@ import ( "sort" "time" + substate "github.com/Fantom-foundation/Substate" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state/snapshot" @@ -32,7 +33,6 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/rlp" - "github.com/ethereum/go-ethereum/substate" "github.com/ethereum/go-ethereum/trie" ) diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 2b5028ab4..5e1189315 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -17,13 +17,13 @@ package vm import ( + substate "github.com/Fantom-foundation/Substate" "time" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/substate" "github.com/holiman/uint256" "golang.org/x/crypto/sha3" ) diff --git a/go.mod b/go.mod index 86ad00d95..4b1d9bd61 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/Azure/azure-pipeline-go v0.2.2 // indirect github.com/Azure/azure-storage-blob-go v0.7.0 github.com/Azure/go-autorest/autorest/adal v0.8.0 // indirect + github.com/Fantom-foundation/Substate v0.0.0-20230224090651-4c8c024214f4 github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect github.com/VictoriaMetrics/fastcache v1.6.0 github.com/aws/aws-sdk-go-v2 v1.2.0 @@ -20,15 +21,13 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set v1.8.0 github.com/deepmap/oapi-codegen v1.8.2 // indirect - github.com/dlclark/regexp2 v1.10.0 // indirect github.com/docker/docker v1.6.2 - github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498 + github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf github.com/edsrzf/mmap-go v1.0.0 github.com/fatih/color v1.7.0 github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff github.com/go-ole/go-ole v1.2.1 // indirect - github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect github.com/go-stack/stack v1.8.0 github.com/golang/mock v1.3.1 github.com/golang/protobuf v1.5.2 @@ -74,4 +73,6 @@ require ( gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 gopkg.in/urfave/cli.v1 v1.20.0 + gopkg.in/yaml.v2 v2.4.0 // indirect + gotest.tools v2.2.0+incompatible // indirect ) diff --git a/go.sum b/go.sum index dc09fc9af..790792b6f 100644 --- a/go.sum +++ b/go.sum @@ -18,34 +18,48 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Azure/azure-pipeline-go v0.2.1 h1:OLBdZJ3yvOn2MezlWvbrBMTEUQC72zAftRZOMdj5HYo= github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= github.com/Azure/azure-pipeline-go v0.2.2 h1:6oiIS9yaG6XCCzhgAgKFfIWyo4LLCiDhZot6ltoThhY= github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1/go.mod h1:fBF9PQNqB8scdgpZ3ufzaLntG0AG7C1WjPMsiFOmfHM= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3/go.mod h1:KLF4gFr6DcKFZwSuH8w8yEK6DpFl3LP5rhdvAb7Yz5I= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0/go.mod h1:tPaiy8S5bQ+S5sOiDlINkp7+Ef339+Nz5L5XO+cnOHo= github.com/Azure/azure-storage-blob-go v0.7.0 h1:MuueVOYkufCxJw5YZzF842DY2MBsp+hLuh2apKY0mck= github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= -github.com/Azure/go-autorest/autorest v0.9.0 h1:MRvx8gncNaXJqOoLmhNjUAKh33JJF8LyxPhomEtOsjs= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= -github.com/Azure/go-autorest/autorest/adal v0.8.0 h1:CxTzQrySOxDnKpLjFJeZAS5Qrv/qFPkgLjx5bOAi//I= github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/adal v0.9.22 h1:/GblQdIudfEM3AWWZ0mrYJQSd7JS4S/Mbzh6F0ov0Xc= +github.com/Azure/go-autorest/autorest/adal v0.9.22/go.mod h1:XuAbAEUv2Tta//+voMI038TrJBqjKam0me7qR+L8Cmk= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSWlm5Ew6bxipnr/tbM= github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= -github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY= +github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= -github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k= +github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/Fantom-foundation/Substate v0.0.0-20230224090651-4c8c024214f4 h1:AA0BtERxmlf7jvDF4fwIB2k/Lsc7HTRE3QHTZnfcSVA= +github.com/Fantom-foundation/Substate v0.0.0-20230224090651-4c8c024214f4/go.mod h1:/yIHWCDDJcdKMJYvOLdYOnHt5eUBF9XWnrvrNE+90ik= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= +github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= @@ -80,6 +94,8 @@ github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+Wji github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= @@ -106,9 +122,11 @@ github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3h github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ= github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f h1:C43yEtQ6NIf4ftFXD/V55gnGFgPbMQobd//YlnLjUJ8= github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -117,32 +135,40 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/deepmap/oapi-codegen v1.6.0 h1:w/d1ntwh91XI0b/8ja7+u5SvA4IFfM0UNNLmiDR1gg0= github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= github.com/deepmap/oapi-codegen v1.8.2 h1:SegyeYGcdi0jLLrpbCMoJxnUUn8GBXHsvr4rbzjuhfU= github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0= -github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 h1:Izz0+t1Z5nI16/II7vuEo/nHjodOg0p7+OiDpjX5t1E= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/docker v1.6.2 h1:HlFGsy+9/xrgMmhmN+NGhCc5SHGJ7I+kHosRR1xc/aI= github.com/docker/docker v1.6.2/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498 h1:Y9vTBSsV4hSwPSj4bacAU/eSnV3dAxVpepaghAdhGoQ= -github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= +github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf h1:Yt+4K30SdjOkRoRRm3vYNQgR+/ZIy0RmeUDZo7Y8zeQ= +github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum/go-ethereum v1.10.25/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= @@ -160,6 +186,8 @@ github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80n github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= @@ -170,6 +198,9 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang-jwt/jwt/v4 v4.0.0 h1:RAqyYixv1p7uEnocuy8P1nru5wprCh/MH2BIlW5z5/o= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -179,6 +210,8 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -192,6 +225,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -224,6 +258,7 @@ github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0U github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0= github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= @@ -245,6 +280,7 @@ github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= github.com/influxdata/influxql v1.1.1-0.20200828144457-65d3ef77d385/go.mod h1:gHp9y86a/pxhjJ+zMjNXiQAA197Xk9wLxaz+fGG+kWk= github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE= +github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU= github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 h1:vilfsDSy7TDxedi9gyBkMvAirat/oRcL0lFdJBf6tdM= github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= @@ -281,11 +317,14 @@ github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH6 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= @@ -301,6 +340,7 @@ github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149 h1:HfxbT6/JcvIljmERptWhwa8XzP7H3T+Z2N26gTsaDaA= github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d h1:oNAwILwmgWKFpuU+dXvI6dl9jG2mAWAZLX3r9s0PPiw= github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= @@ -314,10 +354,15 @@ github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/Qd github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q= github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks= @@ -331,6 +376,7 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= @@ -373,6 +419,7 @@ github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRr github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -381,6 +428,7 @@ github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfP github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -401,17 +449,25 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= +github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= +github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= +github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= +github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y= github.com/urfave/cli/v2 v2.10.2/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo= @@ -423,6 +479,8 @@ github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6Ut github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -442,6 +500,8 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -452,6 +512,7 @@ golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm0 golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -470,6 +531,8 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -488,11 +551,19 @@ golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -523,6 +594,7 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -541,19 +613,29 @@ golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -584,15 +666,19 @@ golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191126055441-b0650ceb63d9/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= @@ -641,8 +727,9 @@ google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/l google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= @@ -658,11 +745,14 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/substate/destroyed_account_db.go b/substate/destroyed_account_db.go deleted file mode 100644 index 4caac18ca..000000000 --- a/substate/destroyed_account_db.go +++ /dev/null @@ -1,142 +0,0 @@ -package substate - -import ( - "encoding/binary" - "fmt" - "log" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/rlp" -) - -type DestroyedAccountDB struct { - backend BackendDatabase -} - -func NewDestroyedAccountDB(backend BackendDatabase) *DestroyedAccountDB { - return &DestroyedAccountDB{backend: backend} -} - -func OpenDestroyedAccountDB(destroyedAccountDir string) (*DestroyedAccountDB, error) { - return openDestroyedAccountDB(destroyedAccountDir, false) -} - -func OpenDestroyedAccountDBReadOnly(destroyedAccountDir string) (*DestroyedAccountDB, error) { - return openDestroyedAccountDB(destroyedAccountDir, true) -} - -func openDestroyedAccountDB(destroyedAccountDir string, readOnly bool) (*DestroyedAccountDB, error) { - log.Println("substate: OpenDestroyedAccountDB") - backend, err := rawdb.NewLevelDBDatabase(destroyedAccountDir, 1024, 100, "destroyed_accounts", readOnly) - if err != nil { - return nil, fmt.Errorf("error opening deletion-db %s: %v", destroyedAccountDir, err) - } - return NewDestroyedAccountDB(backend), nil -} - -func (db *DestroyedAccountDB) Close() error { - return db.backend.Close() -} - -type SuicidedAccountLists struct { - DestroyedAccounts []common.Address - ResurrectedAccounts []common.Address -} - -func (db *DestroyedAccountDB) SetDestroyedAccounts(block uint64, tx int, des []common.Address, res []common.Address) error { - accountList := SuicidedAccountLists{DestroyedAccounts: des, ResurrectedAccounts: res} - value, err := rlp.EncodeToBytes(accountList) - if err != nil { - panic(err) - } - return db.backend.Put(encodeDestroyedAccountKey(block, tx), value) -} - -func (db *DestroyedAccountDB) GetDestroyedAccounts(block uint64, tx int) ([]common.Address, []common.Address, error) { - data, err := db.backend.Get(encodeDestroyedAccountKey(block, tx)) - if err != nil { - return nil, nil, err - } - list, err := decodeAddressList(data) - return list.DestroyedAccounts, list.ResurrectedAccounts, err -} - -func (db *DestroyedAccountDB) getFirstKeyInBlock(block uint64) []byte { - prefix := []byte(DestroyedAccountPrefix) - blockBytes := make([]byte, len(prefix)+8) - copy(blockBytes[0:], prefix) - binary.BigEndian.PutUint64(blockBytes[len(prefix):], block) - iter := db.backend.NewIterator(blockBytes, nil) - defer iter.Release() - if iter.Key() != nil { - return iter.Key()[len(prefix):] - } - return nil -} - -// GetAccountsDestroyedInRange get list of all accounts between block from and to (including from and to). -func (db *DestroyedAccountDB) GetAccountsDestroyedInRange(from, to uint64) ([]common.Address, error) { - firstKey := db.getFirstKeyInBlock(from) - iter := db.backend.NewIterator([]byte(DestroyedAccountPrefix), firstKey) - defer iter.Release() - isDestroyed := make(map[common.Address]bool) - for iter.Next() { - block, _, err := decodeDestroyedAccountKey(iter.Key()) - if err != nil { - return nil, err - } - if block > to { - break - } - list, err := decodeAddressList(iter.Value()) - if err != nil { - return nil, err - } - for _, addr := range list.DestroyedAccounts { - isDestroyed[addr] = true - } - for _, addr := range list.ResurrectedAccounts { - isDestroyed[addr] = false - } - } - - accountList := []common.Address{} - for addr, isDeleted := range isDestroyed { - if isDeleted { - accountList = append(accountList, addr) - } - } - return accountList, nil -} - -const ( - DestroyedAccountPrefix = "da" // DestroyedAccountPrefix + block (64-bit) -> SuicidedAccountLists -) - -func encodeDestroyedAccountKey(block uint64, tx int) []byte { - prefix := []byte(DestroyedAccountPrefix) - key := make([]byte, len(prefix)+12) - copy(key[0:], prefix) - binary.BigEndian.PutUint64(key[len(prefix):], block) - binary.BigEndian.PutUint32(key[len(prefix)+8:], uint32(tx)) - return key -} - -func decodeDestroyedAccountKey(data []byte) (uint64, int, error) { - if len(data) != len(DestroyedAccountPrefix)+12 { - return 0, 0, fmt.Errorf("invalid length of destroyed account key, expected %d, got %d", len(DestroyedAccountPrefix)+12, len(data)) - } - if string(data[0:len(DestroyedAccountPrefix)]) != DestroyedAccountPrefix { - return 0, 0, fmt.Errorf("invalid prefix of destroyed account key") - } - block := binary.BigEndian.Uint64(data[len(DestroyedAccountPrefix):]) - tx := binary.BigEndian.Uint32(data[len(DestroyedAccountPrefix)+8:]) - return block, int(tx), nil -} - -func decodeAddressList(data []byte) (SuicidedAccountLists, error) { - list := SuicidedAccountLists{} - err := rlp.DecodeBytes(data, &list) - return list, err -} diff --git a/substate/metadata.go b/substate/metadata.go deleted file mode 100644 index b61350150..000000000 --- a/substate/metadata.go +++ /dev/null @@ -1,47 +0,0 @@ -package substate - -import ( - "encoding/binary" -) - -const ( - MetadataPrefix = "md" - UpdatesetPrefix = "us" - UpdatesetIntervalKey = MetadataPrefix + UpdatesetPrefix + "in" - UpdatesetSizeKey = MetadataPrefix + UpdatesetPrefix + "si" -) - -// PutMetadata into db -func (db *UpdateDB) PutMetadata(interval, size uint64) error { - - byteInterval := make([]byte, 8) - binary.BigEndian.PutUint64(byteInterval, interval) - - if err := db.backend.Put([]byte(UpdatesetIntervalKey), byteInterval); err != nil { - return err - } - - sizeInterval := make([]byte, 8) - binary.BigEndian.PutUint64(sizeInterval, size) - - if err := db.backend.Put([]byte(UpdatesetSizeKey), sizeInterval); err != nil { - return err - } - - return nil -} - -// GetMetadata from db -func (db *UpdateDB) GetMetadata() (uint64, uint64, error) { - byteInterval, err := db.backend.Get([]byte(UpdatesetIntervalKey)) - if err != nil { - return 0, 0, err - } - - byteSize, err := db.backend.Get([]byte(UpdatesetSizeKey)) - if err != nil { - return 0, 0, err - } - - return binary.BigEndian.Uint64(byteInterval), binary.BigEndian.Uint64(byteSize), nil -} diff --git a/substate/static_substate_db.go b/substate/static_substate_db.go deleted file mode 100644 index 1598ba59f..000000000 --- a/substate/static_substate_db.go +++ /dev/null @@ -1,107 +0,0 @@ -package substate - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/urfave/cli/v2" -) - -var ( - SubstateDbFlag = cli.StringFlag{ - Name: "substate-db", - Usage: "Data directory for substate recorder/replayer", - } - substateDir = SubstateDbFlag.Value - staticSubstateDB *SubstateDB - RecordReplay bool = false -) - -func OpenSubstateDB() { - fmt.Println("record-replay: OpenSubstateDB") - backend, err := rawdb.NewLevelDBDatabase(substateDir, 1024, 100, "substatedir", false) - if err != nil { - panic(fmt.Errorf("error opening substate leveldb %s: %v", substateDir, err)) - } - fmt.Println("record-replay: opened successfully") - staticSubstateDB = NewSubstateDB(backend) -} - -func OpenSubstateDBReadOnly() { - fmt.Println("record-replay: OpenSubstateDB") - backend, err := rawdb.NewLevelDBDatabase(substateDir, 1024, 100, "substatedir", true) - if err != nil { - panic(fmt.Errorf("error opening substate leveldb %s: %v", substateDir, err)) - } - staticSubstateDB = NewSubstateDB(backend) -} - -func CloseSubstateDB() { - defer fmt.Println("record-replay: CloseSubstateDB") - - err := staticSubstateDB.Close() - if err != nil { - panic(fmt.Errorf("error closing substate leveldb %s: %v", substateDir, err)) - } -} - -func CompactSubstateDB() { - fmt.Println("record-replay: CompactSubstateDB") - - // compact entire DB - err := staticSubstateDB.Compact(nil, nil) - if err != nil { - panic(fmt.Errorf("error compacting substate leveldb %s: %v", substateDir, err)) - } -} - -func OpenFakeSubstateDB() { - backend := rawdb.NewMemoryDatabase() - staticSubstateDB = NewSubstateDB(backend) -} - -func CloseFakeSubstateDB() { - staticSubstateDB.Close() -} - -func SetSubstateDbFlags(ctx *cli.Context) { - substateDir = ctx.String(SubstateDbFlag.Name) - fmt.Printf("record-replay: --substatedir=%s\n", substateDir) -} - -func SetSubstateDb(dir string) { - substateDir = dir -} - -func HasCode(codeHash common.Hash) bool { - return staticSubstateDB.HasCode(codeHash) -} - -func GetCode(codeHash common.Hash) []byte { - return staticSubstateDB.GetCode(codeHash) -} - -func PutCode(code []byte) { - staticSubstateDB.PutCode(code) -} - -func HasSubstate(block uint64, tx int) bool { - return staticSubstateDB.HasSubstate(block, tx) -} - -func GetSubstate(block uint64, tx int) *Substate { - return staticSubstateDB.GetSubstate(block, tx) -} - -func GetBlockSubstates(block uint64) map[int]*Substate { - return staticSubstateDB.GetBlockSubstates(block) -} - -func PutSubstate(block uint64, tx int, substate *Substate) { - staticSubstateDB.PutSubstate(block, tx, substate) -} - -func DeleteSubstate(block uint64, tx int) { - staticSubstateDB.DeleteSubstate(block, tx) -} diff --git a/substate/substate.go b/substate/substate.go deleted file mode 100644 index 10dbbbb0b..000000000 --- a/substate/substate.go +++ /dev/null @@ -1,396 +0,0 @@ -package substate - -import ( - "bytes" - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" -) - -// SubstateAccount is modification of GenesisAccount in core/genesis.go -type SubstateAccount struct { - Nonce uint64 - Balance *big.Int - Storage map[common.Hash]common.Hash - Code []byte -} - -func NewSubstateAccount(nonce uint64, balance *big.Int, code []byte) *SubstateAccount { - return &SubstateAccount{ - Nonce: nonce, - Balance: new(big.Int).Set(balance), - Storage: make(map[common.Hash]common.Hash), - Code: code, - } -} - -func (x *SubstateAccount) Equal(y *SubstateAccount) bool { - if x == y { - return true - } - - if (x == nil || y == nil) && x != y { - return false - } - - equal := (x.Nonce == y.Nonce && - x.Balance.Cmp(y.Balance) == 0 && - bytes.Equal(x.Code, y.Code) && - len(x.Storage) == len(y.Storage)) - if !equal { - return false - } - - for k, xv := range x.Storage { - yv, exist := y.Storage[k] - if !(exist && xv == yv) { - return false - } - } - - return true -} - -func (sa *SubstateAccount) Copy() *SubstateAccount { - saCopy := NewSubstateAccount(sa.Nonce, sa.Balance, sa.Code) - - for key, value := range sa.Storage { - saCopy.Storage[key] = value - } - - return saCopy -} - -func (sa *SubstateAccount) CodeHash() common.Hash { - return crypto.Keccak256Hash(sa.Code) -} - -type SubstateAlloc map[common.Address]*SubstateAccount - -// EstinateIncrementalSize returns estimated substate size increase after merge -func (x SubstateAlloc) EstimateIncrementalSize (y SubstateAlloc) uint64 { - var ( - size uint64 = 0 - sizeOfAddress uint64 = 20 - sizeOfHash uint64 = 32 - sizeOfNonce uint64 = 8 - ) - for addr, account := range y { - if xaccount, found := x[addr]; found { - // skip if no diff - if xaccount.Equal(account) { - continue - } - // update storage by y - for key, _ := range account.Storage { - // only add new storage keys - if _, found := x[addr].Storage[key]; !found { - size += sizeOfHash // add sizeof(common.Hash) - } - } - } else { - // add size of new accounts - // address + nonce + balance + codehash - size += sizeOfAddress + sizeOfNonce + uint64(len(account.Balance.Bytes())) + sizeOfHash - // storage slots * sizeof(common.Hash) - size += uint64(len(account.Storage)) * sizeOfHash - } - } - return size -} - -func (x SubstateAlloc) Merge(y SubstateAlloc) { - for addr, account := range y { - if xaccount, found := x[addr]; found { - if xaccount.Equal(account) { - continue - } - // overwrite account details in x by y - x[addr].Nonce = account.Nonce - x[addr].Balance = new(big.Int).Set(account.Balance) - x[addr].Code = make([]byte, len(account.Code)) - copy(x[addr].Code, account.Code) - } else { - // create new account details in x - x[addr] = NewSubstateAccount(account.Nonce, account.Balance, account.Code) - } - // update storage by y - for key, value := range account.Storage { - x[addr].Storage[key] = value - } - } -} - -func (x SubstateAlloc) Equal(y SubstateAlloc) bool { - if len(x) != len(y) { - return false - } - - for k, xv := range x { - yv, exist := y[k] - if !(exist && xv.Equal(yv)) { - return false - } - } - - return true -} - -type SubstateEnv struct { - Coinbase common.Address - Difficulty *big.Int - GasLimit uint64 - Number uint64 - Timestamp uint64 - BlockHashes map[uint64]common.Hash - - // London hard fork, EIP-1559 - BaseFee *big.Int // nil if EIP-1559 is not activated -} - -func NewSubstateEnv(b *types.Block, blockHashes map[uint64]common.Hash) *SubstateEnv { - var env = &SubstateEnv{} - - env.Coinbase = b.Coinbase() - env.Difficulty = new(big.Int).Set(b.Difficulty()) - env.GasLimit = b.GasLimit() - env.Number = b.NumberU64() - env.Timestamp = b.Time() - env.BlockHashes = make(map[uint64]common.Hash) - for num64, bhash := range blockHashes { - env.BlockHashes[num64] = bhash - } - - env.BaseFee = b.BaseFee() - - return env -} - -func (x *SubstateEnv) Equal(y *SubstateEnv) bool { - if x == y { - return true - } - - if (x == nil || y == nil) && x != y { - return false - } - - equal := (x.Coinbase == y.Coinbase && - x.Difficulty.Cmp(y.Difficulty) == 0 && - x.GasLimit == y.GasLimit && - x.Number == y.Number && - x.Timestamp == y.Timestamp && - len(x.BlockHashes) == len(y.BlockHashes) && - x.BaseFee.Cmp(y.BaseFee) == 0) - if !equal { - return false - } - - for k, xv := range x.BlockHashes { - yv, exist := y.BlockHashes[k] - if !(exist && xv == yv) { - return false - } - } - - return true -} - -type SubstateMessage struct { - Nonce uint64 - CheckNonce bool // inversion of IsFake - GasPrice *big.Int - Gas uint64 - - From common.Address - To *common.Address // nil means contract creation - Value *big.Int - Data []byte - - // for memoization - dataHash *common.Hash - - // Berlin hard fork, EIP-2930: Optional access lists - AccessList types.AccessList // nil if EIP-2930 is not activated - - // London hard fork, EIP-1559: Fee market - GasFeeCap *big.Int // GasPrice if EIP-1559 is not activated - GasTipCap *big.Int // GasPrice if EIP-1559 is not activated -} - -func NewSubstateMessage(msg *types.Message) *SubstateMessage { - var smsg = &SubstateMessage{} - - smsg.Nonce = msg.Nonce() - smsg.CheckNonce = !msg.IsFake() - smsg.GasPrice = msg.GasPrice() - smsg.Gas = msg.Gas() - - smsg.From = msg.From() - smsg.To = msg.To() - smsg.Value = msg.Value() - smsg.Data = msg.Data() - - smsg.AccessList = msg.AccessList() - - smsg.GasFeeCap = msg.GasFeeCap() - smsg.GasTipCap = msg.GasTipCap() - - return smsg -} - -func (x *SubstateMessage) Equal(y *SubstateMessage) bool { - if x == y { - return true - } - - if (x == nil || y == nil) && x != y { - return false - } - - equal := (x.Nonce == y.Nonce && - x.CheckNonce == y.CheckNonce && - x.GasPrice.Cmp(y.GasPrice) == 0 && - x.Gas == y.Gas && - x.From == y.From && - (x.To == y.To || (x.To != nil && y.To != nil && *x.To == *y.To)) && - x.Value.Cmp(y.Value) == 0 && - bytes.Equal(x.Data, y.Data) && - len(x.AccessList) == len(y.AccessList) && - x.GasFeeCap.Cmp(y.GasFeeCap) == 0 && - x.GasTipCap.Cmp(y.GasTipCap) == 0) - if !equal { - return false - } - - for i, xa := range x.AccessList { - ya := y.AccessList[i] - equal := (xa.Address == ya.Address && - len(xa.StorageKeys) == len(ya.StorageKeys)) - if !equal { - return false - } - for j, xk := range xa.StorageKeys { - yk := ya.StorageKeys[j] - if xk != yk { - return false - } - } - } - - return true -} - -func (msg *SubstateMessage) DataHash() common.Hash { - if msg.dataHash == nil { - dataHash := crypto.Keccak256Hash(msg.Data) - msg.dataHash = &dataHash - } - return *msg.dataHash -} - -func (msg *SubstateMessage) AsMessage() types.Message { - return types.NewMessage( - msg.From, msg.To, msg.Nonce, msg.Value, - msg.Gas, msg.GasPrice, msg.GasFeeCap, msg.GasTipCap, - msg.Data, msg.AccessList, !msg.CheckNonce) -} - -// modification of types.Receipt -type SubstateResult struct { - Status uint64 - Bloom types.Bloom - Logs []*types.Log - - ContractAddress common.Address - GasUsed uint64 -} - -func NewSubstateResult(receipt *types.Receipt) *SubstateResult { - var sr = &SubstateResult{} - - sr.Status = receipt.Status - sr.Bloom = receipt.Bloom - sr.Logs = receipt.Logs - - sr.ContractAddress = receipt.ContractAddress - sr.GasUsed = receipt.GasUsed - - return sr -} - -func (x *SubstateResult) Equal(y *SubstateResult) bool { - if x == y { - return true - } - - if (x == nil || y == nil) && x != y { - return false - } - - equal := (x.Status == y.Status && - x.Bloom == y.Bloom && - len(x.Logs) == len(y.Logs) && - x.ContractAddress == y.ContractAddress && - x.GasUsed == y.GasUsed) - if !equal { - return false - } - - for i, xl := range x.Logs { - yl := y.Logs[i] - - equal := (xl.Address == yl.Address && - len(xl.Topics) == len(yl.Topics) && - bytes.Equal(xl.Data, yl.Data)) - if !equal { - return false - } - - for i, xt := range xl.Topics { - yt := yl.Topics[i] - if xt != yt { - return false - } - } - } - - return true -} - -type Substate struct { - InputAlloc SubstateAlloc - OutputAlloc SubstateAlloc - Env *SubstateEnv - Message *SubstateMessage - Result *SubstateResult -} - -func NewSubstate(inputAlloc SubstateAlloc, outputAlloc SubstateAlloc, env *SubstateEnv, message *SubstateMessage, result *SubstateResult) *Substate { - return &Substate{ - InputAlloc: inputAlloc, - OutputAlloc: outputAlloc, - Env: env, - Message: message, - Result: result, - } -} - -func (x *Substate) Equal(y *Substate) bool { - if x == y { - return true - } - - if (x == nil || y == nil) && x != y { - return false - } - - equal := (x.InputAlloc.Equal(y.InputAlloc) && - x.OutputAlloc.Equal(y.OutputAlloc) && - x.Env.Equal(y.Env) && - x.Message.Equal(y.Message) && - x.Result.Equal(y.Result)) - return equal -} diff --git a/substate/substate_db.go b/substate/substate_db.go deleted file mode 100644 index 9be0cf008..000000000 --- a/substate/substate_db.go +++ /dev/null @@ -1,447 +0,0 @@ -package substate - -import ( - "encoding/binary" - "fmt" - "io" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/rlp" -) - -const ( - Stage1SubstatePrefix = "1s" // Stage1SubstatePrefix + block (64-bit) + tx (64-bit) -> substateRLP - Stage1CodePrefix = "1c" // Stage1CodePrefix + codeHash (256-bit) -> code -) - -func Stage1SubstateKey(block uint64, tx int) []byte { - prefix := []byte(Stage1SubstatePrefix) - - blockTx := make([]byte, 16) - binary.BigEndian.PutUint64(blockTx[0:8], block) - binary.BigEndian.PutUint64(blockTx[8:16], uint64(tx)) - - return append(prefix, blockTx...) -} - -func DecodeStage1SubstateKey(key []byte) (block uint64, tx int, err error) { - prefix := Stage1SubstatePrefix - if len(key) != len(prefix)+8+8 { - err = fmt.Errorf("invalid length of stage1 substate key: %v", len(key)) - return - } - if p := string(key[:len(prefix)]); p != prefix { - err = fmt.Errorf("invalid prefix of stage1 substate key: %#x", p) - return - } - blockTx := key[len(prefix):] - block = binary.BigEndian.Uint64(blockTx[0:8]) - tx = int(binary.BigEndian.Uint64(blockTx[8:16])) - return -} - -func Stage1SubstateBlockPrefix(block uint64) []byte { - return append([]byte(Stage1SubstatePrefix), BlockToBytes(block)...) -} -func BlockToBytes(block uint64) []byte { - blockBytes := make([]byte, 8) - binary.BigEndian.PutUint64(blockBytes[0:8], block) - return blockBytes -} - -func Stage1CodeKey(codeHash common.Hash) []byte { - prefix := []byte(Stage1CodePrefix) - return append(prefix, codeHash.Bytes()...) -} - -func DecodeStage1CodeKey(key []byte) (codeHash common.Hash, err error) { - prefix := Stage1CodePrefix - if len(key) != len(prefix)+32 { - err = fmt.Errorf("invalid length of stage1 code key: %v", len(key)) - return - } - if p := string(key[:2]); p != prefix { - err = fmt.Errorf("invalid prefix of stage1 code key: %#x", p) - return - } - codeHash = common.BytesToHash(key[len(prefix):]) - return -} - -type BackendDatabase interface { - ethdb.KeyValueReader - ethdb.KeyValueWriter - ethdb.Batcher - ethdb.Iteratee - ethdb.Stater - ethdb.Compacter - io.Closer -} - -type SubstateDB struct { - backend BackendDatabase -} - -func NewSubstateDB(backend BackendDatabase) *SubstateDB { - return &SubstateDB{backend: backend} -} - -func (db *SubstateDB) Compact(start []byte, limit []byte) error { - return db.backend.Compact(start, limit) -} - -func (db *SubstateDB) Close() error { - return db.backend.Close() -} - -func CodeHash(code []byte) common.Hash { - return crypto.Keccak256Hash(code) -} - -var EmptyCodeHash = CodeHash(nil) - -func (db *SubstateDB) HasCode(codeHash common.Hash) bool { - if codeHash == EmptyCodeHash { - return false - } - key := Stage1CodeKey(codeHash) - has, err := db.backend.Has(key) - if err != nil { - panic(fmt.Errorf("record-replay: error checking bytecode for codeHash %s: %v", codeHash.Hex(), err)) - } - return has -} - -func (db *SubstateDB) GetCode(codeHash common.Hash) []byte { - if codeHash == EmptyCodeHash { - return nil - } - key := Stage1CodeKey(codeHash) - code, err := db.backend.Get(key) - if err != nil { - panic(fmt.Errorf("record-replay: error getting code %s: %v", codeHash.Hex(), err)) - } - return code -} - -func (db *SubstateDB) PutCode(code []byte) { - if len(code) == 0 { - return - } - codeHash := crypto.Keccak256Hash(code) - key := Stage1CodeKey(codeHash) - err := db.backend.Put(key, code) - if err != nil { - panic(fmt.Errorf("record-replay: error putting code %s: %v", codeHash.Hex(), err)) - } -} - -func (db *SubstateDB) HasSubstate(block uint64, tx int) bool { - key := Stage1SubstateKey(block, tx) - has, _ := db.backend.Has(key) - return has -} - -func (db *SubstateDB) GetSubstate(block uint64, tx int) *Substate { - var err error - - key := Stage1SubstateKey(block, tx) - value, err := db.backend.Get(key) - if err != nil { - panic(fmt.Errorf("record-replay: error getting substate %v_%v from substate DB: %v,", block, tx, err)) - } - - // try decoding as substates from latest hard forks - substateRLP := SubstateRLP{} - err = rlp.DecodeBytes(value, &substateRLP) - - if err != nil { - // try decoding as legacy substates between Berlin and London hard forks - berlinRLP := berlinSubstateRLP{} - err = rlp.DecodeBytes(value, &berlinRLP) - if err == nil { - substateRLP.setBerlinRLP(&berlinRLP) - } - } - - if err != nil { - // try decoding as legacy substates before Berlin hard fork - legacyRLP := legacySubstateRLP{} - err = rlp.DecodeBytes(value, &legacyRLP) - if err != nil { - panic(fmt.Errorf("error decoding substateRLP %v_%v: %v", block, tx, err)) - } - substateRLP.setLegacyRLP(&legacyRLP) - } - - substate := Substate{} - substate.SetRLP(&substateRLP, db) - - return &substate -} - -func (db *SubstateDB) GetBlockSubstates(block uint64) map[int]*Substate { - var err error - - txSubstate := make(map[int]*Substate) - - prefix := Stage1SubstateBlockPrefix(block) - - iter := db.backend.NewIterator(prefix, nil) - for iter.Next() { - key := iter.Key() - value := iter.Value() - - b, tx, err := DecodeStage1SubstateKey(key) - if err != nil { - panic(fmt.Errorf("record-replay: invalid substate key found for block %v: %v", block, err)) - } - - if block != b { - panic(fmt.Errorf("record-replay: GetBlockSubstates(%v) iterated substates from block %v", block, b)) - } - - // try decoding as substates from latest hard forks - substateRLP := SubstateRLP{} - err = rlp.DecodeBytes(value, &substateRLP) - - if err != nil { - // try decoding as legacy substates between Berlin and London hard forks - berlinRLP := berlinSubstateRLP{} - err = rlp.DecodeBytes(value, &berlinRLP) - if err == nil { - substateRLP.setBerlinRLP(&berlinRLP) - } - } - - if err != nil { - // try decoding as legacy substates before Berlin hard fork - legacyRLP := legacySubstateRLP{} - err = rlp.DecodeBytes(value, &legacyRLP) - if err != nil { - panic(fmt.Errorf("error decoding substateRLP %v_%v: %v", block, tx, err)) - } - substateRLP.setLegacyRLP(&legacyRLP) - } - - substate := Substate{} - substate.SetRLP(&substateRLP, db) - - txSubstate[tx] = &substate - } - iter.Release() - err = iter.Error() - if err != nil { - panic(err) - } - - return txSubstate -} - -func (db *SubstateDB) PutSubstate(block uint64, tx int, substate *Substate) { - var err error - - // put deployed/creation code - for _, account := range substate.InputAlloc { - db.PutCode(account.Code) - } - for _, account := range substate.OutputAlloc { - db.PutCode(account.Code) - } - if msg := substate.Message; msg.To == nil { - db.PutCode(msg.Data) - } - - key := Stage1SubstateKey(block, tx) - defer func() { - if err != nil { - panic(fmt.Errorf("record-replay: error putting substate %v_%v into substate DB: %v", block, tx, err)) - } - }() - - substateRLP := NewSubstateRLP(substate) - value, err := rlp.EncodeToBytes(substateRLP) - if err != nil { - panic(err) - } - - err = db.backend.Put(key, value) - if err != nil { - panic(err) - } -} - -func (db *SubstateDB) DeleteSubstate(block uint64, tx int) { - key := Stage1SubstateKey(block, tx) - err := db.backend.Delete(key) - if err != nil { - panic(err) - } -} - -type Transaction struct { - Block uint64 - Transaction int - Substate *Substate -} - -type rawEntry struct { - key []byte - value []byte -} - -func parseTransaction(db *SubstateDB, data rawEntry) *Transaction { - key := data.key - value := data.value - - block, tx, err := DecodeStage1SubstateKey(data.key) - if err != nil { - panic(fmt.Errorf("record-replay: invalid substate key found: %v - issue: %v", key, err)) - } - - // try decoding as substates from latest hard forks - substateRLP := SubstateRLP{} - err = rlp.DecodeBytes(value, &substateRLP) - - if err != nil { - // try decoding as legacy substates between Berlin and London hard forks - berlinRLP := berlinSubstateRLP{} - err = rlp.DecodeBytes(value, &berlinRLP) - if err == nil { - substateRLP.setBerlinRLP(&berlinRLP) - } - } - - if err != nil { - // try decoding as legacy substates before Berlin hard fork - legacyRLP := legacySubstateRLP{} - err = rlp.DecodeBytes(value, &legacyRLP) - if err != nil { - panic(fmt.Errorf("error decoding substateRLP %v_%v: %v", block, tx, err)) - } - substateRLP.setLegacyRLP(&legacyRLP) - } - - substate := &Substate{} - substate.SetRLP(&substateRLP, db) - - return &Transaction{ - Block: block, - Transaction: tx, - Substate: substate, - } -} - -type SubstateIterator struct { - db *SubstateDB - iter ethdb.Iterator - cur *Transaction - - // Connections to parsing pipeline - source <-chan *Transaction - done chan<- int -} - -func NewSubstateIterator(start_block uint64, num_workers int) SubstateIterator { - db := staticSubstateDB - start := BlockToBytes(start_block) - // substate prefix is already in start - iter := db.backend.NewIterator([]byte(Stage1SubstatePrefix), start) - - // Create channels - done := make(chan int) - raw_data := make([]chan rawEntry, num_workers) - results := make([]chan *Transaction, num_workers) - result := make(chan *Transaction, 10) - - for i := 0; i < num_workers; i++ { - raw_data[i] = make(chan rawEntry, 10) - results[i] = make(chan *Transaction, 10) - } - - // Start iter => raw data stage - go func() { - defer func() { - for _, c := range raw_data { - close(c) - } - }() - step := 0 - for { - if !iter.Next() { - return - } - - key := make([]byte, len(iter.Key())) - copy(key, iter.Key()) - value := make([]byte, len(iter.Value())) - copy(value, iter.Value()) - - res := rawEntry{key, value} - - select { - case <-done: - return - case raw_data[step] <- res: // fall-through - } - step = (step + 1) % num_workers - } - }() - - // Start raw data => parsed transaction stage (parallel) - for i := 0; i < num_workers; i++ { - id := i - go func() { - defer close(results[id]) - for raw := range raw_data[id] { - results[id] <- parseTransaction(db, raw) - } - }() - } - - // Start the go routine moving transactions from parsers to sink in order - go func() { - defer close(result) - step := 0 - for open_producers := num_workers; open_producers > 0; { - next := <-results[step%num_workers] - if next != nil { - result <- next - } else { - open_producers-- - } - step++ - } - }() - - return SubstateIterator{ - db: db, - iter: iter, - source: result, - done: done, - } -} - -func (i *SubstateIterator) Release() { - close(i.done) - - // drain pipeline until the result channel is closed - for open := true; open; _, open = <-i.source { - } - - i.iter.Release() -} - -func (i *SubstateIterator) Next() bool { - if i.iter == nil { - return false - } - i.cur = <-i.source - return i.cur != nil -} - -func (i *SubstateIterator) Value() *Transaction { - return i.cur -} diff --git a/substate/substate_json.go b/substate/substate_json.go deleted file mode 100644 index ec414efad..000000000 --- a/substate/substate_json.go +++ /dev/null @@ -1,347 +0,0 @@ -package substate - -import ( - "encoding/json" - "math/big" - - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/core/types" - - "github.com/ethereum/go-ethereum/common" -) - -// SubstateAccountJSON is modification of core.GenesisAccount -type SubstateAccountJSON struct { - Code hexutil.Bytes `json:"code,omitempty"` - Storage map[common.Hash]common.Hash `json:"storage,omitempty"` - Balance *math.HexOrDecimal256 `json:"balance" gencodec:"required"` - Nonce math.HexOrDecimal64 `json:"nonce,omitempty"` -} - -func NewSubstateAccountJSON(sa *SubstateAccount) *SubstateAccountJSON { - return &SubstateAccountJSON{ - Nonce: math.HexOrDecimal64(sa.Nonce), - Balance: (*math.HexOrDecimal256)(sa.Balance), - Storage: sa.Storage, - Code: sa.Code, - } -} - -func (sa *SubstateAccount) SetJSON(saJSON *SubstateAccountJSON) { - sa.Nonce = uint64(saJSON.Nonce) - sa.Balance = (*big.Int)(saJSON.Balance) - sa.Storage = make(map[common.Hash]common.Hash) - if saJSON.Storage != nil { - sa.Storage = saJSON.Storage - } - sa.Code = saJSON.Code -} - -func (sa SubstateAccount) MarshalJSON() ([]byte, error) { - return json.Marshal(NewSubstateAccountJSON(&sa)) -} - -func (sa *SubstateAccount) UnmarshalJSON(b []byte) error { - var err error - var saJSON SubstateAccountJSON - - err = json.Unmarshal(b, &saJSON) - if err != nil { - return err - } - - sa.SetJSON(&saJSON) - - return nil -} - -type SubstateAllocJSON map[common.Address]*SubstateAccountJSON - -func NewSubstateAllocJSON(alloc SubstateAlloc) SubstateAllocJSON { - allocJSON := make(SubstateAllocJSON) - for addr, account := range alloc { - allocJSON[addr] = NewSubstateAccountJSON(account) - } - - return allocJSON -} - -func (alloc *SubstateAlloc) SetJSON(allocJSON SubstateAllocJSON) { - *alloc = make(SubstateAlloc) - for addr, saJSON := range allocJSON { - var sa SubstateAccount - - sa.Nonce = uint64(saJSON.Nonce) - sa.Balance = (*big.Int)(saJSON.Balance) - sa.Storage = make(map[common.Hash]common.Hash) - if saJSON.Storage != nil { - sa.Storage = saJSON.Storage - } - sa.Code = saJSON.Code - - (*alloc)[addr] = &sa - } -} - -func (alloc SubstateAlloc) MarshalJSON() ([]byte, error) { - return json.Marshal(NewSubstateAllocJSON(alloc)) -} - -func (alloc *SubstateAlloc) UnmarshalJSON(b []byte) error { - var err error - var allocJSON SubstateAllocJSON - - err = json.Unmarshal(b, &allocJSON) - if err != nil { - return err - } - - alloc.SetJSON(allocJSON) - - return nil -} - -// SubstateEnvJSON is modification of t8ntool.stEnv -type SubstateEnvJSON struct { - Coinbase common.Address `json:"coinbase" gencodec:"required"` - Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"` - GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"` - Number math.HexOrDecimal64 `json:"number" gencodec:"required"` - Timestamp math.HexOrDecimal64 `json:"timestamp" gencodec:"required"` - BlockHashes map[math.HexOrDecimal64]common.Hash `json:"blockHashes,omitempty"` - - BaseFee *math.HexOrDecimal256 `json:"baseFee,omitempty"` -} - -func NewSubstateEnvJSON(env *SubstateEnv) *SubstateEnvJSON { - var envJSON SubstateEnvJSON - - envJSON.Coinbase = env.Coinbase - envJSON.Difficulty = (*math.HexOrDecimal256)(env.Difficulty) - envJSON.GasLimit = math.HexOrDecimal64(env.GasLimit) - envJSON.Number = math.HexOrDecimal64(env.Number) - envJSON.Timestamp = math.HexOrDecimal64(env.Timestamp) - envJSON.BlockHashes = make(map[math.HexOrDecimal64]common.Hash) - if env.BlockHashes != nil { - for num64, bhash := range env.BlockHashes { - envJSON.BlockHashes[math.HexOrDecimal64(num64)] = bhash - } - } - - envJSON.BaseFee = (*math.HexOrDecimal256)(env.BaseFee) - - return &envJSON -} - -func (env *SubstateEnv) SetJSON(envJSON *SubstateEnvJSON) { - env.Coinbase = envJSON.Coinbase - env.Difficulty = (*big.Int)(envJSON.Difficulty) - env.GasLimit = uint64(envJSON.GasLimit) - env.Number = uint64(envJSON.Number) - env.Timestamp = uint64(envJSON.Timestamp) - env.BlockHashes = make(map[uint64]common.Hash) - if envJSON.BlockHashes != nil { - for num64, bhash := range envJSON.BlockHashes { - env.BlockHashes[uint64(num64)] = bhash - } - } - - env.BaseFee = (*big.Int)(envJSON.BaseFee) - if env.BaseFee.Cmp(big.NewInt(0)) == 0 { - env.BaseFee = nil - } -} - -func (env SubstateEnv) MarshalJSON() ([]byte, error) { - return json.Marshal(NewSubstateEnvJSON(&env)) -} - -func (env *SubstateEnv) UnmarshalJSON(b []byte) error { - var err error - var envJSON SubstateEnvJSON - - err = json.Unmarshal(b, &envJSON) - if err != nil { - return err - } - - env.SetJSON(&envJSON) - - return nil -} - -// SubstateMessageJSON is modification of types.msgdata -type SubstateMessageJSON struct { - Nonce math.HexOrDecimal64 `json:"nonce" gencodec:"required"` - CheckNonce bool `json:"checkNonce" gencodec:"required"` - GasPrice *math.HexOrDecimal256 `json:"gasPrice" gencodec:"required"` - Gas math.HexOrDecimal64 `json:"gas" gencodec:"required"` - - From common.Address `json:"from"` - To *common.Address `json:"to"` // nil means contract creation - Value *math.HexOrDecimal256 `json:"value" gencodec:"required"` - Data hexutil.Bytes `json:"input" gencodec:"required"` - - AccessList types.AccessList `json:"accessList,omitempty"` - - GasFeeCap *math.HexOrDecimal256 `json:"gasFeeCap,omitempty"` - GasTipCap *math.HexOrDecimal256 `json:"gasTipCap,omitempty"` -} - -func NewSubstateMessageJSON(msg *SubstateMessage) *SubstateMessageJSON { - var msgJSON SubstateMessageJSON - - msgJSON.Nonce = math.HexOrDecimal64(msg.Nonce) - msgJSON.CheckNonce = msg.CheckNonce - msgJSON.GasPrice = (*math.HexOrDecimal256)(msg.GasPrice) - msgJSON.Gas = math.HexOrDecimal64(msg.Gas) - - msgJSON.From = msg.From - msgJSON.To = msg.To - msgJSON.Value = (*math.HexOrDecimal256)(msg.Value) - msgJSON.Data = hexutil.Bytes(msg.Data) - - msgJSON.AccessList = msg.AccessList - - msgJSON.GasFeeCap = (*math.HexOrDecimal256)(msg.GasFeeCap) - msgJSON.GasTipCap = (*math.HexOrDecimal256)(msg.GasTipCap) - - return &msgJSON -} - -func (msg *SubstateMessage) SetJSON(msgJSON *SubstateMessageJSON) { - msg.Nonce = uint64(msgJSON.Nonce) - msg.CheckNonce = msgJSON.CheckNonce - msg.GasPrice = (*big.Int)(msgJSON.GasPrice) - msg.Gas = uint64(msgJSON.Gas) - - msg.From = msgJSON.From - msg.To = msgJSON.To - msg.Value = (*big.Int)(msgJSON.Value) - msg.Data = []byte(msgJSON.Data) - - msg.AccessList = msgJSON.AccessList - - msg.GasFeeCap = (*big.Int)(msgJSON.GasFeeCap) - if msg.GasFeeCap.Cmp(big.NewInt(0)) == 0 { - msg.GasFeeCap = msg.GasPrice - } - msg.GasTipCap = (*big.Int)(msgJSON.GasTipCap) - if msg.GasTipCap.Cmp(big.NewInt(0)) == 0 { - msg.GasTipCap = msg.GasPrice - } -} - -func (msg SubstateMessage) MarshalJSON() ([]byte, error) { - return json.Marshal(NewSubstateMessageJSON(&msg)) -} - -func (msg *SubstateMessage) UnmarshalJSON(b []byte) error { - var err error - var msgJSON SubstateMessageJSON - - err = json.Unmarshal(b, &msgJSON) - if err != nil { - return err - } - - msg.SetJSON(&msgJSON) - - return nil -} - -type SubstateResultJSON struct { - Status math.HexOrDecimal64 `json:"status"` - Bloom types.Bloom `json:"logsBloom"` - Logs []*types.Log `json:"logs"` - - ContractAddress common.Address `json:"contractAddress"` - GasUsed math.HexOrDecimal64 `json:"gasUsed" gencodec:"required"` -} - -func NewSubstateResultJSON(result *SubstateResult) *SubstateResultJSON { - var resultJSON SubstateResultJSON - - resultJSON.Status = math.HexOrDecimal64(result.Status) - resultJSON.Bloom = result.Bloom - resultJSON.Logs = result.Logs - - resultJSON.ContractAddress = result.ContractAddress - resultJSON.GasUsed = math.HexOrDecimal64(result.GasUsed) - - return &resultJSON -} - -func (result *SubstateResult) SetJSON(resultJSON *SubstateResultJSON) { - result.Status = uint64(resultJSON.Status) - result.Bloom = resultJSON.Bloom - result.Logs = resultJSON.Logs - - result.ContractAddress = resultJSON.ContractAddress - result.GasUsed = uint64(resultJSON.GasUsed) -} - -func (result SubstateResult) MarshalJSON() ([]byte, error) { - return json.Marshal(NewSubstateResultJSON(&result)) -} - -func (result *SubstateResult) UnmarshalJSON(b []byte) error { - var err error - var resultJSON SubstateResultJSON - - err = json.Unmarshal(b, &resultJSON) - if err != nil { - return err - } - - result.SetJSON(&resultJSON) - - return nil -} - -type SubstateJSON struct { - InputAlloc SubstateAllocJSON `json:"inputAlloc"` - OutputAlloc SubstateAllocJSON `json:"outputAlloc"` - Env *SubstateEnvJSON `json:"env"` - Message *SubstateMessageJSON `json:"message"` - Result *SubstateResultJSON `json:"result"` -} - -func NewSubstateJSON(substate *Substate) *SubstateJSON { - var substateJSON SubstateJSON - - substateJSON.InputAlloc = NewSubstateAllocJSON(substate.InputAlloc) - substateJSON.OutputAlloc = NewSubstateAllocJSON(substate.OutputAlloc) - substateJSON.Env = NewSubstateEnvJSON(substate.Env) - substateJSON.Message = NewSubstateMessageJSON(substate.Message) - substateJSON.Result = NewSubstateResultJSON(substate.Result) - - return &substateJSON -} - -func (substate *Substate) SetJSON(substateJSON *SubstateJSON) { - substate.InputAlloc.SetJSON(substateJSON.InputAlloc) - substate.OutputAlloc.SetJSON(substateJSON.OutputAlloc) - substate.Env.SetJSON(substateJSON.Env) - substate.Message.SetJSON(substateJSON.Message) - substate.Result.SetJSON(substateJSON.Result) -} - -func (substate Substate) MarshalJSON() ([]byte, error) { - return json.Marshal(NewSubstateJSON(&substate)) -} - -func (substate *Substate) UnmarshalJSON(b []byte) error { - var err error - var substateJSON SubstateJSON - - err = json.Unmarshal(b, &substateJSON) - if err != nil { - return err - } - - substate.SetJSON(&substateJSON) - - return nil -} diff --git a/substate/substate_rlp.go b/substate/substate_rlp.go deleted file mode 100644 index 3f2ceffef..000000000 --- a/substate/substate_rlp.go +++ /dev/null @@ -1,409 +0,0 @@ -package substate - -import ( - "math/big" - "sort" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" -) - -type SubstateAccountRLP struct { - Nonce uint64 - Balance *big.Int - CodeHash common.Hash - Storage [][2]common.Hash -} - -func NewSubstateAccountRLP(sa *SubstateAccount) *SubstateAccountRLP { - var saRLP SubstateAccountRLP - - saRLP.Nonce = sa.Nonce - saRLP.Balance = new(big.Int).Set(sa.Balance) - saRLP.CodeHash = sa.CodeHash() - sortedKeys := []common.Hash{} - for key := range sa.Storage { - sortedKeys = append(sortedKeys, key) - } - sort.Slice(sortedKeys, func(i, j int) bool { - return sortedKeys[i].Big().Cmp(sortedKeys[j].Big()) < 0 - }) - for _, key := range sortedKeys { - value := sa.Storage[key] - saRLP.Storage = append(saRLP.Storage, [2]common.Hash{key, value}) - } - - return &saRLP -} - -func (sa *SubstateAccount) SetRLP(saRLP *SubstateAccountRLP, db *SubstateDB) { - sa.Balance = saRLP.Balance - sa.Nonce = saRLP.Nonce - sa.Code = db.GetCode(saRLP.CodeHash) - sa.Storage = make(map[common.Hash]common.Hash) - for i := range saRLP.Storage { - sa.Storage[saRLP.Storage[i][0]] = saRLP.Storage[i][1] - } -} - -type SubstateAllocRLP struct { - Addresses []common.Address - Accounts []*SubstateAccountRLP -} - -func NewSubstateAllocRLP(alloc SubstateAlloc) SubstateAllocRLP { - var allocRLP SubstateAllocRLP - - allocRLP.Addresses = []common.Address{} - allocRLP.Accounts = []*SubstateAccountRLP{} - for addr := range alloc { - allocRLP.Addresses = append(allocRLP.Addresses, addr) - } - sort.Slice(allocRLP.Addresses, func(i, j int) bool { - return allocRLP.Addresses[i].Hash().Big().Cmp(allocRLP.Addresses[j].Hash().Big()) < 0 - }) - - for _, addr := range allocRLP.Addresses { - account := alloc[addr] - allocRLP.Accounts = append(allocRLP.Accounts, NewSubstateAccountRLP(account)) - } - - return allocRLP -} - -func (alloc *SubstateAlloc) SetRLP(allocRLP SubstateAllocRLP, db *SubstateDB) { - *alloc = make(SubstateAlloc) - for i, addr := range allocRLP.Addresses { - var sa SubstateAccount - - saRLP := allocRLP.Accounts[i] - sa.Balance = saRLP.Balance - sa.Nonce = saRLP.Nonce - sa.Code = db.GetCode(saRLP.CodeHash) - sa.Storage = make(map[common.Hash]common.Hash) - for i := range saRLP.Storage { - sa.Storage[saRLP.Storage[i][0]] = saRLP.Storage[i][1] - } - - (*alloc)[addr] = &sa - } -} - -type legacySubstateEnvRLP struct { - Coinbase common.Address - Difficulty *big.Int - GasLimit uint64 - Number uint64 - Timestamp uint64 - BlockHashes [][2]common.Hash -} - -func (envRLP *SubstateEnvRLP) setLegacyRLP(lenvRLP *legacySubstateEnvRLP) { - envRLP.Coinbase = lenvRLP.Coinbase - envRLP.Difficulty = lenvRLP.Difficulty - envRLP.GasLimit = lenvRLP.GasLimit - envRLP.Number = lenvRLP.Number - envRLP.Timestamp = lenvRLP.Timestamp - envRLP.BlockHashes = lenvRLP.BlockHashes -} - -type SubstateEnvRLP struct { - Coinbase common.Address - Difficulty *big.Int - GasLimit uint64 - Number uint64 - Timestamp uint64 - BlockHashes [][2]common.Hash - - BaseFee *common.Hash `rlp:"nil"` // missing in substate DB from Geth <= v1.10.3 -} - -func NewSubstateEnvRLP(env *SubstateEnv) *SubstateEnvRLP { - var envRLP SubstateEnvRLP - - envRLP.Coinbase = env.Coinbase - envRLP.Difficulty = env.Difficulty - envRLP.GasLimit = env.GasLimit - envRLP.Number = env.Number - envRLP.Timestamp = env.Timestamp - - sortedNum64 := []uint64{} - for num64 := range env.BlockHashes { - sortedNum64 = append(sortedNum64, num64) - } - for _, num64 := range sortedNum64 { - num := common.BigToHash(new(big.Int).SetUint64(num64)) - bhash := env.BlockHashes[num64] - pair := [2]common.Hash{num, bhash} - envRLP.BlockHashes = append(envRLP.BlockHashes, pair) - } - - envRLP.BaseFee = nil - if env.BaseFee != nil { - baseFeeHash := common.BigToHash(env.BaseFee) - envRLP.BaseFee = &baseFeeHash - } - - return &envRLP -} - -func (env *SubstateEnv) SetRLP(envRLP *SubstateEnvRLP, db *SubstateDB) { - env.Coinbase = envRLP.Coinbase - env.Difficulty = envRLP.Difficulty - env.GasLimit = envRLP.GasLimit - env.Number = envRLP.Number - env.Timestamp = envRLP.Timestamp - env.BlockHashes = make(map[uint64]common.Hash) - for i := range envRLP.BlockHashes { - pair := envRLP.BlockHashes[i] - num64 := pair[0].Big().Uint64() - bhash := pair[1] - env.BlockHashes[num64] = bhash - } - - env.BaseFee = nil - if envRLP.BaseFee != nil { - env.BaseFee = envRLP.BaseFee.Big() - } -} - -type legacySubstateMessageRLP struct { - Nonce uint64 - CheckNonce bool - GasPrice *big.Int - Gas uint64 - - From common.Address - To *common.Address `rlp:"nil"` // nil means contract creation - Value *big.Int - Data []byte - - InitCodeHash *common.Hash `rlp:"nil"` // NOT nil for contract creation -} - -func (msgRLP *SubstateMessageRLP) setLegacyRLP(lmsgRLP *legacySubstateMessageRLP) { - msgRLP.Nonce = lmsgRLP.Nonce - msgRLP.CheckNonce = lmsgRLP.CheckNonce - msgRLP.GasPrice = lmsgRLP.GasPrice - msgRLP.Gas = lmsgRLP.Gas - - msgRLP.From = lmsgRLP.From - msgRLP.To = lmsgRLP.To - msgRLP.Value = new(big.Int).Set(lmsgRLP.Value) - msgRLP.Data = lmsgRLP.Data - - msgRLP.InitCodeHash = lmsgRLP.InitCodeHash - - msgRLP.AccessList = nil - - // Same behavior as LegacyTx.gasFeeCap() and LegacyTx.gasTipCap() - msgRLP.GasFeeCap = lmsgRLP.GasPrice - msgRLP.GasTipCap = lmsgRLP.GasPrice -} - -type berlinSubstateMessageRLP struct { - Nonce uint64 - CheckNonce bool - GasPrice *big.Int - Gas uint64 - - From common.Address - To *common.Address `rlp:"nil"` // nil means contract creation - Value *big.Int - Data []byte - - InitCodeHash *common.Hash `rlp:"nil"` // NOT nil for contract creation - - AccessList types.AccessList // missing in substate DB from Geth v1.9.x -} - -func (msgRLP *SubstateMessageRLP) setBerlinRLP(bmsgRLP *berlinSubstateMessageRLP) { - msgRLP.Nonce = bmsgRLP.Nonce - msgRLP.CheckNonce = bmsgRLP.CheckNonce - msgRLP.GasPrice = bmsgRLP.GasPrice - msgRLP.Gas = bmsgRLP.Gas - - msgRLP.From = bmsgRLP.From - msgRLP.To = bmsgRLP.To - msgRLP.Value = new(big.Int).Set(bmsgRLP.Value) - msgRLP.Data = bmsgRLP.Data - - msgRLP.InitCodeHash = bmsgRLP.InitCodeHash - - msgRLP.AccessList = nil - - // Same behavior as AccessListTx.gasFeeCap() and AccessListTx.gasTipCap() - msgRLP.GasFeeCap = bmsgRLP.GasPrice - msgRLP.GasTipCap = bmsgRLP.GasPrice -} - -type SubstateMessageRLP struct { - Nonce uint64 - CheckNonce bool - GasPrice *big.Int - Gas uint64 - - From common.Address - To *common.Address `rlp:"nil"` // nil means contract creation - Value *big.Int - Data []byte - - InitCodeHash *common.Hash `rlp:"nil"` // NOT nil for contract creation - - AccessList types.AccessList // missing in substate DB from Geth v1.9.x - - GasFeeCap *big.Int // missing in substate DB from Geth <= v1.10.3 - GasTipCap *big.Int // missing in substate DB from Geth <= v1.10.3 -} - -func NewSubstateMessageRLP(msg *SubstateMessage) *SubstateMessageRLP { - var msgRLP SubstateMessageRLP - - msgRLP.Nonce = msg.Nonce - msgRLP.CheckNonce = msg.CheckNonce - msgRLP.GasPrice = msg.GasPrice - msgRLP.Gas = msg.Gas - - msgRLP.From = msg.From - msgRLP.To = msg.To - msgRLP.Value = new(big.Int).Set(msg.Value) - msgRLP.Data = msg.Data - - msgRLP.InitCodeHash = nil - - if msgRLP.To == nil { - // put contract creation init code into codeDB - dataHash := msg.DataHash() - msgRLP.Data = nil - msgRLP.InitCodeHash = &dataHash - } - - msgRLP.AccessList = msg.AccessList - - msgRLP.GasFeeCap = msg.GasFeeCap - msgRLP.GasTipCap = msg.GasTipCap - - return &msgRLP -} - -func (msg *SubstateMessage) SetRLP(msgRLP *SubstateMessageRLP, db *SubstateDB) { - msg.Nonce = msgRLP.Nonce - msg.CheckNonce = msgRLP.CheckNonce - msg.GasPrice = msgRLP.GasPrice - msg.Gas = msgRLP.Gas - - msg.From = msgRLP.From - msg.To = msgRLP.To - msg.Value = msgRLP.Value - msg.Data = msgRLP.Data - - if msgRLP.To == nil { - msg.Data = db.GetCode(*msgRLP.InitCodeHash) - } - - msg.AccessList = msgRLP.AccessList - - msg.GasFeeCap = msgRLP.GasFeeCap - msg.GasTipCap = msgRLP.GasTipCap -} - -type SubstateResultRLP struct { - Status uint64 - Bloom types.Bloom - Logs []*types.Log - - ContractAddress common.Address - GasUsed uint64 -} - -func NewSubstateResultRLP(result *SubstateResult) *SubstateResultRLP { - var resultRLP SubstateResultRLP - - resultRLP.Status = result.Status - resultRLP.Bloom = result.Bloom - resultRLP.Logs = result.Logs - - resultRLP.ContractAddress = result.ContractAddress - resultRLP.GasUsed = result.GasUsed - - return &resultRLP -} - -func (result *SubstateResult) SetRLP(resultRLP *SubstateResultRLP, db *SubstateDB) { - result.Status = resultRLP.Status - result.Bloom = resultRLP.Bloom - result.Logs = resultRLP.Logs - - result.ContractAddress = resultRLP.ContractAddress - result.GasUsed = resultRLP.GasUsed -} - -type legacySubstateRLP struct { - InputAlloc SubstateAllocRLP - OutputAlloc SubstateAllocRLP - Env *legacySubstateEnvRLP - Message *legacySubstateMessageRLP - Result *SubstateResultRLP -} - -func (substateRLP *SubstateRLP) setLegacyRLP(lsubstateRLP *legacySubstateRLP) { - substateRLP.InputAlloc = lsubstateRLP.InputAlloc - substateRLP.OutputAlloc = lsubstateRLP.OutputAlloc - substateRLP.Env = &SubstateEnvRLP{} - substateRLP.Env.setLegacyRLP(lsubstateRLP.Env) - substateRLP.Message = &SubstateMessageRLP{} - substateRLP.Message.setLegacyRLP(lsubstateRLP.Message) - substateRLP.Result = lsubstateRLP.Result -} - -type berlinSubstateRLP struct { - InputAlloc SubstateAllocRLP - OutputAlloc SubstateAllocRLP - Env *legacySubstateEnvRLP - Message *berlinSubstateMessageRLP - Result *SubstateResultRLP -} - -func (substateRLP *SubstateRLP) setBerlinRLP(bsubstateRLP *berlinSubstateRLP) { - substateRLP.InputAlloc = bsubstateRLP.InputAlloc - substateRLP.OutputAlloc = bsubstateRLP.OutputAlloc - substateRLP.Env = &SubstateEnvRLP{} - substateRLP.Env.setLegacyRLP(bsubstateRLP.Env) - substateRLP.Message = &SubstateMessageRLP{} - substateRLP.Message.setBerlinRLP(bsubstateRLP.Message) - substateRLP.Result = bsubstateRLP.Result -} - -type SubstateRLP struct { - InputAlloc SubstateAllocRLP - OutputAlloc SubstateAllocRLP - Env *SubstateEnvRLP - Message *SubstateMessageRLP - Result *SubstateResultRLP -} - -func NewSubstateRLP(substate *Substate) *SubstateRLP { - var substateRLP SubstateRLP - - substateRLP.InputAlloc = NewSubstateAllocRLP(substate.InputAlloc) - substateRLP.OutputAlloc = NewSubstateAllocRLP(substate.OutputAlloc) - substateRLP.Env = NewSubstateEnvRLP(substate.Env) - substateRLP.Message = NewSubstateMessageRLP(substate.Message) - substateRLP.Result = NewSubstateResultRLP(substate.Result) - - return &substateRLP -} - -func (substate *Substate) SetRLP(substateRLP *SubstateRLP, db *SubstateDB) { - substate.InputAlloc = make(SubstateAlloc) - substate.OutputAlloc = make(SubstateAlloc) - substate.Env = &SubstateEnv{} - substate.Message = &SubstateMessage{} - substate.Result = &SubstateResult{} - - substate.InputAlloc.SetRLP(substateRLP.InputAlloc, db) - substate.OutputAlloc.SetRLP(substateRLP.OutputAlloc, db) - substate.Env.SetRLP(substateRLP.Env, db) - substate.Message.SetRLP(substateRLP.Message, db) - substate.Result.SetRLP(substateRLP.Result, db) -} diff --git a/substate/substate_task.go b/substate/substate_task.go deleted file mode 100644 index 78aaa46ea..000000000 --- a/substate/substate_task.go +++ /dev/null @@ -1,256 +0,0 @@ -package substate - -import ( - "fmt" - "runtime" - "sync" - "sync/atomic" - "time" - - "github.com/urfave/cli/v2" -) - -var ( - WorkersFlag = cli.IntFlag{ - Name: "workers", - Usage: "Number of worker threads that execute in parallel", - Value: 4, - } - SkipTransferTxsFlag = cli.BoolFlag{ - Name: "skip-transfer-txs", - Usage: "Skip executing transactions that only transfer ETH", - } - SkipCallTxsFlag = cli.BoolFlag{ - Name: "skip-call-txs", - Usage: "Skip executing CALL transactions to accounts with contract bytecode", - } - SkipCreateTxsFlag = cli.BoolFlag{ - Name: "skip-create-txs", - Usage: "Skip executing CREATE transactions", - } -) - -type SubstateBlockFunc func(block uint64, transactions map[int]*Substate, taskPool *SubstateTaskPool) error -type SubstateTaskFunc func(block uint64, tx int, substate *Substate, taskPool *SubstateTaskPool) error - -type SubstateTaskPool struct { - Name string - BlockFunc SubstateBlockFunc - TaskFunc SubstateTaskFunc - - First uint64 - Last uint64 - - Workers int - SkipTransferTxs bool - SkipCallTxs bool - SkipCreateTxs bool - - Ctx *cli.Context // CLI context required to read additional flags - - DB *SubstateDB -} - -func NewSubstateTaskPool(name string, taskFunc SubstateTaskFunc, first, last uint64, ctx *cli.Context) *SubstateTaskPool { - return &SubstateTaskPool{ - Name: name, - TaskFunc: taskFunc, - - First: first, - Last: last, - - Workers: ctx.Int(WorkersFlag.Name), - SkipTransferTxs: ctx.Bool(SkipTransferTxsFlag.Name), - SkipCallTxs: ctx.Bool(SkipCallTxsFlag.Name), - SkipCreateTxs: ctx.Bool(SkipCreateTxsFlag.Name), - - Ctx: ctx, - - DB: staticSubstateDB, - } -} - -// ExecuteBlock function iterates on substates of a given block call TaskFunc -func (pool *SubstateTaskPool) ExecuteBlock(block uint64) (numTx int64, err error) { - transactions := pool.DB.GetBlockSubstates(block) - if pool.BlockFunc != nil { - err := pool.BlockFunc(block, transactions, pool) - if err != nil { - return numTx, fmt.Errorf("%s: block %v: %v", pool.Name, block, err) - } - } - if pool.TaskFunc == nil { - return int64(len(transactions)), nil - } - for tx, substate := range transactions { - alloc := substate.InputAlloc - msg := substate.Message - - to := msg.To - if pool.SkipTransferTxs && to != nil { - // skip regular transactions (ETH transfer) - if account, exist := alloc[*to]; !exist || len(account.Code) == 0 { - continue - } - } - if pool.SkipCallTxs && to != nil { - // skip CALL trasnactions with contract bytecode - if account, exist := alloc[*to]; exist && len(account.Code) > 0 { - continue - } - } - if pool.SkipCreateTxs && to == nil { - // skip CREATE transactions - continue - } - - err = pool.TaskFunc(block, tx, substate, pool) - if err != nil { - return numTx, fmt.Errorf("%s: %v_%v: %v", pool.Name, block, tx, err) - } - - numTx++ - } - - return numTx, nil -} - -// Execute function spawns worker goroutines and schedule tasks. -func (pool *SubstateTaskPool) Execute() error { - start := time.Now() - - var totalNumBlock, totalNumTx int64 - defer func() { - duration := time.Since(start) + 1*time.Nanosecond - sec := duration.Seconds() - - nb, nt := atomic.LoadInt64(&totalNumBlock), atomic.LoadInt64(&totalNumTx) - blkPerSec := float64(nb) / sec - txPerSec := float64(nt) / sec - fmt.Printf("%s: block range = %v %v\n", pool.Name, pool.First, pool.Last) - fmt.Printf("%s: total #block = %v\n", pool.Name, nb) - fmt.Printf("%s: total #tx = %v\n", pool.Name, nt) - fmt.Printf("%s: %.2f blk/s, %.2f tx/s\n", pool.Name, blkPerSec, txPerSec) - fmt.Printf("%s done in %v\n", pool.Name, duration.Round(1*time.Millisecond)) - }() - - // numProcs = numWorker + work producer (1) + main thread (1) - numProcs := pool.Workers + 2 - if goMaxProcs := runtime.GOMAXPROCS(0); goMaxProcs < numProcs { - runtime.GOMAXPROCS(numProcs) - } - - fmt.Printf("%s: block range = %v %v\n", pool.Name, pool.First, pool.Last) - fmt.Printf("%s: #CPU = %v, #worker = %v\n", pool.Name, runtime.NumCPU(), pool.Workers) - - workChan := make(chan uint64, pool.Workers*10) - doneChan := make(chan interface{}, pool.Workers*10) - stopChan := make(chan struct{}, pool.Workers) - wg := sync.WaitGroup{} - defer func() { - // stop all workers - for i := 0; i < pool.Workers; i++ { - stopChan <- struct{}{} - } - // stop work producer (1) - stopChan <- struct{}{} - - wg.Wait() - close(workChan) - close(doneChan) - }() - // dynamically schedule one block per worker - for i := 0; i < pool.Workers; i++ { - wg.Add(1) - // worker goroutine - go func() { - defer wg.Done() - - for { - select { - - case block := <-workChan: - nt, err := pool.ExecuteBlock(block) - atomic.AddInt64(&totalNumTx, nt) - atomic.AddInt64(&totalNumBlock, 1) - if err != nil { - doneChan <- err - } else { - doneChan <- block - } - - case <-stopChan: - return - - } - } - }() - } - - // wait until all workers finish all tasks - wg.Add(1) - go func() { - defer wg.Done() - - for block := pool.First; block <= pool.Last; block++ { - select { - - case workChan <- block: - continue - - case <-stopChan: - return - - } - } - }() - - // Count finished blocks in order and report execution speed - var lastSec float64 - var lastNumBlock, lastNumTx int64 - waitMap := make(map[uint64]struct{}) - for block := pool.First; block <= pool.Last; { - - // Count finshed blocks from waitMap in order - if _, ok := waitMap[block]; ok { - delete(waitMap, block) - - block++ - continue - } - - duration := time.Since(start) + 1*time.Nanosecond - sec := duration.Seconds() - if block == pool.Last || - (block%10000 == 0 && sec > lastSec+5) || - (block%1000 == 0 && sec > lastSec+10) || - (block%100 == 0 && sec > lastSec+20) || - (block%10 == 0 && sec > lastSec+40) || - (sec > lastSec+60) { - nb, nt := atomic.LoadInt64(&totalNumBlock), atomic.LoadInt64(&totalNumTx) - blkPerSec := float64(nb-lastNumBlock) / (sec - lastSec) - txPerSec := float64(nt-lastNumTx) / (sec - lastSec) - fmt.Printf("%s: elapsed time: %v, number = %v\n", pool.Name, duration.Round(1*time.Millisecond), block) - fmt.Printf("%s: %.2f blk/s, %.2f tx/s\n", pool.Name, blkPerSec, txPerSec) - - lastSec, lastNumBlock, lastNumTx = sec, nb, nt - } - - data := <-doneChan - switch t := data.(type) { - - case uint64: - waitMap[data.(uint64)] = struct{}{} - - case error: - err := data.(error) - return err - - default: - panic(fmt.Errorf("%s: unknown type %T value from doneChan", pool.Name, t)) - - } - } - - return nil -} diff --git a/substate/update_db.go b/substate/update_db.go deleted file mode 100644 index 2708e7ae1..000000000 --- a/substate/update_db.go +++ /dev/null @@ -1,313 +0,0 @@ -package substate - -import ( - "encoding/binary" - "fmt" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/rlp" -) - -type UpdateSetRLP struct { - SubstateAlloc SubstateAllocRLP - DeletedAccounts []common.Address -} - -func NewUpdateSetRLP(updateset SubstateAlloc, deletedAccounts []common.Address) UpdateSetRLP { - var rlp UpdateSetRLP - - rlp.SubstateAlloc = NewSubstateAllocRLP(updateset) - rlp.DeletedAccounts = deletedAccounts - return rlp - -} - -const ( - SubstateAllocPrefix = "2s" // SubstateAllocPrefix + block (64-bit) + tx (64-bit) -> substateRLP -) - -func SubstateAllocKey(block uint64) []byte { - prefix := []byte(SubstateAllocPrefix) - blockTx := make([]byte, 8) - binary.BigEndian.PutUint64(blockTx[0:8], block) - return append(prefix, blockTx...) -} - -func DecodeUpdateSetKey(key []byte) (block uint64, err error) { - prefix := SubstateAllocPrefix - if len(key) != len(prefix)+8 { - err = fmt.Errorf("invalid length of updateset key: %v", len(key)) - return - } - if p := string(key[:len(prefix)]); p != prefix { - err = fmt.Errorf("invalid prefix of updateset key: %#x", p) - return - } - blockTx := key[len(prefix):] - block = binary.BigEndian.Uint64(blockTx[0:8]) - return -} - -type UpdateDB struct { - backend BackendDatabase -} - -func NewUpdateDB(backend BackendDatabase) *UpdateDB { - return &UpdateDB{backend: backend} -} - -func OpenUpdateDB(updateSetDir string) (*UpdateDB, error) { - fmt.Println("substate: OpenUpdateSetDB") - backend, err := rawdb.NewLevelDBDatabase(updateSetDir, 1024, 100, "updatesetdir", false) - if err != nil { - return nil, fmt.Errorf("error opening update-set leveldb %s: %v", updateSetDir, err) - } - return NewUpdateDB(backend), nil -} - -func OpenUpdateDBReadOnly(updateSetDir string) (*UpdateDB, error) { - fmt.Println("substate: OpenUpdateSetDB") - backend, err := rawdb.NewLevelDBDatabase(updateSetDir, 1024, 100, "updatesetdir", true) - if err != nil { - return nil, fmt.Errorf("error opening update-set leveldb %s: %v", updateSetDir, err) - } - return NewUpdateDB(backend), nil -} - -func (db *UpdateDB) Compact(start []byte, limit []byte) error { - return db.backend.Compact(start, limit) -} - -func (db *UpdateDB) Close() error { - return db.backend.Close() -} - -func (db *UpdateDB) GetLastKey() uint64 { - var block uint64 - var err error - iter := db.backend.NewIterator([]byte(SubstateAllocPrefix), nil) - for iter.Next() { - block, err = DecodeUpdateSetKey(iter.Key()) - if err != nil { - panic(fmt.Errorf("error iterating updateDB: %v", err)) - } - } - iter.Release() - return block -} - -func (db *UpdateDB) HasCode(codeHash common.Hash) bool { - if codeHash == EmptyCodeHash { - return false - } - key := Stage1CodeKey(codeHash) - has, err := db.backend.Has(key) - if err != nil { - panic(fmt.Errorf("substate: error checking bytecode for codeHash %s: %v", codeHash.Hex(), err)) - } - return has -} - -func (db *UpdateDB) GetCode(codeHash common.Hash) []byte { - if codeHash == EmptyCodeHash { - return nil - } - key := Stage1CodeKey(codeHash) - code, err := db.backend.Get(key) - if err != nil { - panic(fmt.Errorf("substate: error getting code %s: %v", codeHash.Hex(), err)) - } - return code -} - -func (db *UpdateDB) PutCode(code []byte) { - if len(code) == 0 { - return - } - codeHash := crypto.Keccak256Hash(code) - key := Stage1CodeKey(codeHash) - err := db.backend.Put(key, code) - if err != nil { - panic(fmt.Errorf("substate: error putting code %s: %v", codeHash.Hex(), err)) - } -} - -func (db *UpdateDB) HasUpdateSet(block uint64) bool { - key := SubstateAllocKey(block) - has, _ := db.backend.Has(key) - return has -} - -func (up *UpdateSetRLP) GetSubstateAlloc(db *UpdateDB) *SubstateAlloc { - alloc := make(SubstateAlloc) - for i, addr := range up.SubstateAlloc.Addresses { - var sa SubstateAccount - saRLP := up.SubstateAlloc.Accounts[i] - sa.Balance = saRLP.Balance - sa.Nonce = saRLP.Nonce - sa.Code = db.GetCode(saRLP.CodeHash) - sa.Storage = make(map[common.Hash]common.Hash) - for i := range saRLP.Storage { - sa.Storage[saRLP.Storage[i][0]] = saRLP.Storage[i][1] - } - alloc[addr] = &sa - } - return &alloc -} - -func (db *UpdateDB) GetUpdateSet(block uint64) *SubstateAlloc { - var err error - key := SubstateAllocKey(block) - value, err := db.backend.Get(key) - if err != nil { - panic(fmt.Errorf("substate: error getting substate %v from substate DB: %v,", block, err)) - } - // decode value - updateSetRLP := UpdateSetRLP{} - if err := rlp.DecodeBytes(value, &updateSetRLP); err != nil { - panic(fmt.Errorf("substate: failed to decode updateset value at block %v, key %v", block, key)) - } - updateSet := updateSetRLP.GetSubstateAlloc(db) - return updateSet -} - -func (db *UpdateDB) PutUpdateSet(block uint64, updateSet *SubstateAlloc, deletedAccounts []common.Address) { - var err error - - // put deployed/creation code - for _, account := range *updateSet { - db.PutCode(account.Code) - } - key := SubstateAllocKey(block) - defer func() { - if err != nil { - panic(fmt.Errorf("substate: error putting update-set %v into substate DB: %v", block, err)) - } - }() - - updateSetRLP := NewUpdateSetRLP(*updateSet, deletedAccounts) - - value, err := rlp.EncodeToBytes(updateSetRLP) - if err != nil { - panic(err) - } - err = db.backend.Put(key, value) - if err != nil { - panic(err) - } -} - -func (db *UpdateDB) DeleteSubstateAlloc(block uint64) { - key := SubstateAllocKey(block) - err := db.backend.Delete(key) - if err != nil { - panic(err) - } -} - -type UpdateBlock struct { - Block uint64 - UpdateSet *SubstateAlloc - DeletedAccounts []common.Address -} - -func parseUpdateSet(db *UpdateDB, data rawEntry) *UpdateBlock { - key := data.key - value := data.value - - block, err := DecodeUpdateSetKey(data.key) - if err != nil { - panic(fmt.Errorf("substate: invalid update-set key found: %v - issue: %v", key, err)) - } - - updateSetRLP := UpdateSetRLP{} - rlp.DecodeBytes(value, &updateSetRLP) - updateSet := updateSetRLP.GetSubstateAlloc(db) - - return &UpdateBlock{ - Block: block, - UpdateSet: updateSet, - DeletedAccounts: updateSetRLP.DeletedAccounts, - } -} - -type UpdateSetIterator struct { - db *UpdateDB - iter ethdb.Iterator - cur *UpdateBlock - - // Connections to parsing pipeline - source <-chan *UpdateBlock - done chan<- int -} - -func NewUpdateSetIterator(db *UpdateDB, startBlock, endBlock uint64) UpdateSetIterator { - start := BlockToBytes(startBlock) - // updateset prefix is already in start - iter := db.backend.NewIterator([]byte(SubstateAllocPrefix), start) - - done := make(chan int) - result := make(chan *UpdateBlock, 1) - - go func() { - defer close(result) - for iter.Next() { - - key := make([]byte, len(iter.Key())) - copy(key, iter.Key()) - - // Decode key, if past the end block, stop here. - // This avoids filling channels which huge data objects that are not consumed. - block, err := DecodeUpdateSetKey(key) - if err != nil { - panic(fmt.Errorf("worldstate-upate: invalid update-set key found: %v - issue: %v", key, err)) - } - if block > endBlock { - return - } - - value := make([]byte, len(iter.Value())) - copy(value, iter.Value()) - - raw := rawEntry{key, value} - - select { - case <-done: - return - case result <- parseUpdateSet(db, raw): //fall-through - } - } - }() - - return UpdateSetIterator{ - db: db, - iter: iter, - source: result, - done: done, - } -} - -func (i *UpdateSetIterator) Release() { - close(i.done) - - // drain pipeline until the result channel is closed - for open := true; open; _, open = <-i.source { - } - - i.iter.Release() -} - -func (i *UpdateSetIterator) Next() bool { - if i.iter == nil { - return false - } - i.cur = <-i.source - return i.cur != nil -} - -func (i *UpdateSetIterator) Value() *UpdateBlock { - return i.cur -}