diff --git a/accounts/keystore/keystore_wallet.go b/accounts/keystore/keystore_wallet.go index 01ffd75a8e..91ac138786 100644 --- a/accounts/keystore/keystore_wallet.go +++ b/accounts/keystore/keystore_wallet.go @@ -90,7 +90,7 @@ func (w *keystoreWallet) SignHash(account accounts.Account, hash []byte) ([]byte if account.URL != (accounts.URL{}) && account.URL != w.account.URL { return nil, accounts.ErrUnknownAccount } - // Account seems valid, request the keystore to sign + // StateAccount seems valid, request the keystore to sign return w.keystore.SignHash(account, hash) } @@ -106,7 +106,7 @@ func (w *keystoreWallet) SignTx(account accounts.Account, tx *types.Transaction, if account.URL != (accounts.URL{}) && account.URL != w.account.URL { return nil, accounts.ErrUnknownAccount } - // Account seems valid, request the keystore to sign + // StateAccount seems valid, request the keystore to sign return w.keystore.SignTx(account, tx, chainID) } @@ -120,7 +120,7 @@ func (w *keystoreWallet) SignHashWithPassphrase(account accounts.Account, passph if account.URL != (accounts.URL{}) && account.URL != w.account.URL { return nil, accounts.ErrUnknownAccount } - // Account seems valid, request the keystore to sign + // StateAccount seems valid, request the keystore to sign return w.keystore.SignHashWithPassphrase(account, passphrase, hash) } @@ -134,6 +134,6 @@ func (w *keystoreWallet) SignTxWithPassphrase(account accounts.Account, passphra if account.URL != (accounts.URL{}) && account.URL != w.account.URL { return nil, accounts.ErrUnknownAccount } - // Account seems valid, request the keystore to sign + // StateAccount seems valid, request the keystore to sign return w.keystore.SignTxWithPassphrase(account, passphrase, tx, chainID) } diff --git a/accounts/usbwallet/wallet.go b/accounts/usbwallet/wallet.go index d3cda1f21e..2cb2ca2ae7 100644 --- a/accounts/usbwallet/wallet.go +++ b/accounts/usbwallet/wallet.go @@ -319,7 +319,7 @@ func (w *wallet) selfDerive() { // Termination requested continue case reqc = <-w.deriveReq: - // Account discovery requested + // StateAccount discovery requested } // Derivation needs a chain and device access, skip if either unavailable w.stateLock.RLock() diff --git a/cmd/faucet/faucet.go b/cmd/faucet/faucet.go index 6014f3c5a2..45a5e6cb4f 100644 --- a/cmd/faucet/faucet.go +++ b/cmd/faucet/faucet.go @@ -200,7 +200,7 @@ type faucet struct { index []byte // Index page to serve up on the web keystore *keystore.KeyStore // Keystore containing the single signer - account accounts.Account // Account funding user faucet requests + account accounts.Account // StateAccount funding user faucet requests nonce uint64 // Current pending nonce of the faucet price *big.Int // Current gas price to issue funds with diff --git a/cmd/gc/main.go b/cmd/gc/main.go index 567349ee42..7e1fc4e6d9 100644 --- a/cmd/gc/main.go +++ b/cmd/gc/main.go @@ -3,9 +3,6 @@ package main import ( "flag" "fmt" - "github.com/tomochain/tomochain/core/rawdb" - "github.com/tomochain/tomochain/ethdb" - "github.com/tomochain/tomochain/ethdb/leveldb" "os" "os/signal" "runtime" @@ -13,12 +10,15 @@ import ( "sync/atomic" "time" - "github.com/hashicorp/golang-lru" + lru "github.com/hashicorp/golang-lru" "github.com/tomochain/tomochain/cmd/utils" "github.com/tomochain/tomochain/common" "github.com/tomochain/tomochain/core" - "github.com/tomochain/tomochain/core/state" + "github.com/tomochain/tomochain/core/rawdb" + "github.com/tomochain/tomochain/core/types" "github.com/tomochain/tomochain/eth" + "github.com/tomochain/tomochain/ethdb" + "github.com/tomochain/tomochain/ethdb/leveldb" "github.com/tomochain/tomochain/rlp" "github.com/tomochain/tomochain/trie" ) @@ -82,7 +82,7 @@ func main() { if running { for _, address := range cleanAddress { enc := trieRoot.trie.Get(address.Bytes()) - var data state.Account + var data types.StateAccount rlp.DecodeBytes(enc, &data) fmt.Println(time.Now().Format(time.RFC3339), "Start clean state address ", address.Hex(), " at block ", trieRoot.number) signerRoot, err := resolveHash(data.Root[:], db) diff --git a/consensus/clique/snapshot.go b/consensus/clique/snapshot.go index 3c2bf703d8..9a1e9e8846 100644 --- a/consensus/clique/snapshot.go +++ b/consensus/clique/snapshot.go @@ -32,7 +32,7 @@ import ( type Vote struct { Signer common.Address `json:"signer"` // Authorized signer that cast this vote Block uint64 `json:"block"` // Block number the vote was cast in (expire old votes) - Address common.Address `json:"address"` // Account being voted on to change its authorization + Address common.Address `json:"address"` // StateAccount being voted on to change its authorization Authorize bool `json:"authorize"` // Whether to authorize or deauthorize the voted account } diff --git a/consensus/posv/posv.go b/consensus/posv/posv.go index 0027104970..a25bdd764d 100644 --- a/consensus/posv/posv.go +++ b/consensus/posv/posv.go @@ -21,9 +21,6 @@ import ( "encoding/json" "errors" "fmt" - "github.com/tomochain/tomochain/tomox/tradingstate" - "github.com/tomochain/tomochain/tomoxlending/lendingstate" - "gopkg.in/karalabe/cookiejar.v2/collections/prque" "io/ioutil" "math/big" "math/rand" @@ -50,6 +47,9 @@ import ( "github.com/tomochain/tomochain/params" "github.com/tomochain/tomochain/rlp" "github.com/tomochain/tomochain/rpc" + "github.com/tomochain/tomochain/tomox/tradingstate" + "github.com/tomochain/tomochain/tomoxlending/lendingstate" + "gopkg.in/karalabe/cookiejar.v2/collections/prque" ) const ( @@ -181,7 +181,7 @@ var ( // SignerFn is a signer callback function to request a hash to be signed by a // backing account. -//type SignerFn func(accounts.Account, []byte) ([]byte, error) +//type SignerFn func(accounts.StateAccount, []byte) ([]byte, error) // sigHash returns the hash which is used as input for the proof-of-stake-voting // signing. It is the hash of the entire header apart from the 65 byte signature diff --git a/consensus/posv/snapshot.go b/consensus/posv/snapshot.go index aef9e2a39f..01f9d50e42 100644 --- a/consensus/posv/snapshot.go +++ b/consensus/posv/snapshot.go @@ -32,7 +32,7 @@ import ( //type Vote struct { // Signer common.Address `json:"signer"` // Authorized signer that cast this vote // Block uint64 `json:"block"` // Block number the vote was cast in (expire old votes) -// Address common.Address `json:"address"` // Account being voted on to change its authorization +// Address common.Address `json:"address"` // StateAccount being voted on to change its authorization // Authorize bool `json:"authorize"` // Whether to authorize or deauthorize the voted account //} diff --git a/core/state/dump.go b/core/state/dump.go index f08c6e7df3..7368146ca7 100644 --- a/core/state/dump.go +++ b/core/state/dump.go @@ -21,6 +21,7 @@ import ( "fmt" "github.com/tomochain/tomochain/common" + "github.com/tomochain/tomochain/core/types" "github.com/tomochain/tomochain/rlp" "github.com/tomochain/tomochain/trie" ) @@ -48,7 +49,7 @@ func (self *StateDB) RawDump() Dump { it := trie.NewIterator(self.trie.NodeIterator(nil)) for it.Next() { addr := self.trie.GetKey(it.Key) - var data Account + var data types.StateAccount if err := rlp.DecodeBytes(it.Value, &data); err != nil { panic(err) } diff --git a/core/state/iterator.go b/core/state/iterator.go index 3cfc592ecb..d69321f36a 100644 --- a/core/state/iterator.go +++ b/core/state/iterator.go @@ -21,6 +21,7 @@ import ( "fmt" "github.com/tomochain/tomochain/common" + "github.com/tomochain/tomochain/core/types" "github.com/tomochain/tomochain/rlp" "github.com/tomochain/tomochain/trie" ) @@ -104,7 +105,7 @@ func (it *NodeIterator) step() error { return nil } // Otherwise we've reached an account node, initiate data iteration - var account Account + var account types.StateAccount if err := rlp.Decode(bytes.NewReader(it.stateIt.LeafBlob()), &account); err != nil { return err } diff --git a/core/state/state_object.go b/core/state/state_object.go index b03231e23b..478823be58 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -23,6 +23,7 @@ import ( "math/big" "github.com/tomochain/tomochain/common" + "github.com/tomochain/tomochain/core/types" "github.com/tomochain/tomochain/crypto" "github.com/tomochain/tomochain/rlp" ) @@ -58,12 +59,12 @@ func (self Storage) Copy() Storage { // // The usage pattern is as follows: // First you need to obtain a state object. -// Account values can be accessed and modified through the object. +// StateAccount values can be accessed and modified through the object. // Finally, call CommitTrie to write the modified storage trie into a database. type stateObject struct { address common.Address addrHash common.Hash // hash of ethereum address of the account - data Account + data types.StateAccount db *StateDB // DB error. @@ -95,17 +96,8 @@ func (s *stateObject) empty() bool { return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, emptyCodeHash) } -// Account is the Ethereum consensus representation of accounts. -// These objects are stored in the main account trie. -type Account struct { - Nonce uint64 - Balance *big.Int - Root common.Hash // merkle root of the storage trie - CodeHash []byte -} - // newObject creates a state object. -func newObject(db *StateDB, address common.Address, data Account, onDirty func(addr common.Address)) *stateObject { +func newObject(db *StateDB, address common.Address, data types.StateAccount, onDirty func(addr common.Address)) *stateObject { if data.Balance == nil { data.Balance = new(big.Int) } @@ -397,7 +389,7 @@ func (self *stateObject) Nonce() uint64 { } // Never called, but must be present to allow stateObject to be used -// as a vm.Account interface that also satisfies the vm.ContractRef +// as a vm.StateAccount interface that also satisfies the vm.ContractRef // interface. Interfaces are awesome. func (self *stateObject) Value() *big.Int { panic("Value on stateObject should never be called") diff --git a/core/state/statedb.go b/core/state/statedb.go index 7a3357b3e8..818d3d0aaa 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -398,7 +398,7 @@ func (self *StateDB) getStateObject(addr common.Address) (stateObject *stateObje self.setError(err) return nil } - var data Account + var data types.StateAccount if err := rlp.DecodeBytes(enc, &data); err != nil { log.Error("Failed to decode state object", "addr", addr, "err", err) return nil @@ -432,7 +432,7 @@ func (self *StateDB) MarkStateObjectDirty(addr common.Address) { // the given address, it is overwritten and returned as the second return value. func (self *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) { prev = self.getStateObject(addr) - newobj = newObject(self, addr, Account{}, self.MarkStateObjectDirty) + newobj = newObject(self, addr, types.StateAccount{}, self.MarkStateObjectDirty) newobj.setNonce(0) // sets the object to dirty if prev == nil { self.journal = append(self.journal, createObjectChange{account: &addr}) @@ -449,8 +449,8 @@ func (self *StateDB) createObject(addr common.Address) (newobj, prev *stateObjec // CreateAccount is called during the EVM CREATE operation. The situation might arise that // a contract does the following: // -// 1. sends funds to sha(account ++ (nonce + 1)) -// 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1) +// 1. sends funds to sha(account ++ (nonce + 1)) +// 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 (self *StateDB) CreateAccount(addr common.Address) { @@ -636,7 +636,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err error) } // Write trie changes. root, err = s.trie.Commit(func(leaf []byte, parent common.Hash) error { - var account Account + var account types.StateAccount if err := rlp.DecodeBytes(leaf, &account); err != nil { return nil } diff --git a/core/state/sync.go b/core/state/sync.go index 95f29b2879..e26281c7db 100644 --- a/core/state/sync.go +++ b/core/state/sync.go @@ -20,6 +20,7 @@ import ( "bytes" "github.com/tomochain/tomochain/common" + "github.com/tomochain/tomochain/core/types" "github.com/tomochain/tomochain/ethdb" "github.com/tomochain/tomochain/rlp" "github.com/tomochain/tomochain/trie" @@ -29,7 +30,7 @@ import ( func NewStateSync(root common.Hash, database ethdb.KeyValueReader, bloom *trie.SyncBloom) *trie.Sync { var syncer *trie.Sync callback := func(leaf []byte, parent common.Hash) error { - var obj Account + var obj types.StateAccount if err := rlp.Decode(bytes.NewReader(leaf), &obj); err != nil { return err } diff --git a/core/types/block.go b/core/types/block.go index a055ced147..9e95a1d82c 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -33,11 +33,6 @@ import ( "github.com/tomochain/tomochain/rlp" ) -var ( - EmptyRootHash = DeriveSha(Transactions{}) - EmptyUncleHash = CalcUncleHash(nil) -) - // A BlockNonce is a 64-bit hash which proves (combined with the // mix-hash) that a sufficient amount of computation has been carried // out on a block. diff --git a/core/types/hashes.go b/core/types/hashes.go new file mode 100644 index 0000000000..35fc6dc9f9 --- /dev/null +++ b/core/types/hashes.go @@ -0,0 +1,39 @@ +// Copyright 2023 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package types + +import ( + "github.com/tomochain/tomochain/common" + "github.com/tomochain/tomochain/crypto" +) + +var ( + // EmptyRootHash is the known root hash of an empty trie. + EmptyRootHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") + + // EmptyUncleHash is the known hash of the empty uncle set. + EmptyUncleHash = rlpHash([]*Header(nil)) // 1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347 + + // EmptyCodeHash is the known hash of the empty EVM bytecode. + EmptyCodeHash = crypto.Keccak256Hash(nil) // c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 + + // EmptyTxsHash is the known hash of the empty transaction set. + EmptyTxsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") + + // EmptyReceiptsHash is the known hash of the empty receipt set. + EmptyReceiptsHash = common.HexToHash("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421") +) diff --git a/core/types/state_account.go b/core/types/state_account.go new file mode 100644 index 0000000000..01c552a04c --- /dev/null +++ b/core/types/state_account.go @@ -0,0 +1,103 @@ +package types + +import ( + "bytes" + "math/big" + + "github.com/tomochain/tomochain/common" + "github.com/tomochain/tomochain/rlp" +) + +// StateAccount is the Ethereum consensus representation of accounts. +// These objects are stored in the main account trie. +type StateAccount struct { + Nonce uint64 + Balance *big.Int + Root common.Hash // merkle root of the storage trie + CodeHash []byte +} + +// NewEmptyStateAccount constructs an empty state account. +func NewEmptyStateAccount() *StateAccount { + return &StateAccount{ + Balance: new(big.Int), + Root: EmptyRootHash, + CodeHash: EmptyCodeHash.Bytes(), + } +} + +// Copy returns a deep-copied state account object. +func (acct *StateAccount) Copy() *StateAccount { + var balance *big.Int + if acct.Balance != nil { + balance = new(big.Int).Set(acct.Balance) + } + return &StateAccount{ + Nonce: acct.Nonce, + Balance: balance, + Root: acct.Root, + CodeHash: common.CopyBytes(acct.CodeHash), + } +} + +// SlimAccount is a modified version of an Account, where the root is replaced +// with a byte slice. This format can be used to represent full-consensus format +// or slim format which replaces the empty root and code hash as nil byte slice. +type SlimAccount struct { + Nonce uint64 + Balance *big.Int + Root []byte // Nil if root equals to types.EmptyRootHash + CodeHash []byte // Nil if hash equals to types.EmptyCodeHash +} + +// SlimAccountRLP encodes the state account in 'slim RLP' format. +func SlimAccountRLP(account StateAccount) []byte { + slim := SlimAccount{ + Nonce: account.Nonce, + Balance: account.Balance, + } + if account.Root != EmptyRootHash { + slim.Root = account.Root[:] + } + if !bytes.Equal(account.CodeHash, EmptyCodeHash[:]) { + slim.CodeHash = account.CodeHash + } + data, err := rlp.EncodeToBytes(slim) + if err != nil { + panic(err) + } + return data +} + +// FullAccount decodes the data on the 'slim RLP' format and return +// the consensus format account. +func FullAccount(data []byte) (*StateAccount, error) { + var slim SlimAccount + if err := rlp.DecodeBytes(data, &slim); err != nil { + return nil, err + } + var account StateAccount + account.Nonce, account.Balance = slim.Nonce, slim.Balance + + // Interpret the storage root and code hash in slim format. + if len(slim.Root) == 0 { + account.Root = EmptyRootHash + } else { + account.Root = common.BytesToHash(slim.Root) + } + if len(slim.CodeHash) == 0 { + account.CodeHash = EmptyCodeHash[:] + } else { + account.CodeHash = slim.CodeHash + } + return &account, nil +} + +// FullAccountRLP converts data on the 'slim RLP' format into the full RLP-format. +func FullAccountRLP(data []byte) ([]byte, error) { + account, err := FullAccount(data) + if err != nil { + return nil, err + } + return rlp.EncodeToBytes(account) +} diff --git a/les/handler.go b/les/handler.go index b426f7fdd1..d5bd36f470 100644 --- a/les/handler.go +++ b/les/handler.go @@ -21,7 +21,6 @@ import ( "encoding/binary" "errors" "fmt" - "github.com/tomochain/tomochain/core/rawdb" "math/big" "net" "sync" @@ -30,6 +29,7 @@ import ( "github.com/tomochain/tomochain/common" "github.com/tomochain/tomochain/consensus" "github.com/tomochain/tomochain/core" + "github.com/tomochain/tomochain/core/rawdb" "github.com/tomochain/tomochain/core/state" "github.com/tomochain/tomochain/core/types" "github.com/tomochain/tomochain/eth/downloader" @@ -1095,18 +1095,18 @@ func (pm *ProtocolManager) handleMsg(p *peer) error { } // getAccount retrieves an account from the state based at root. -func (pm *ProtocolManager) getAccount(statedb *state.StateDB, root, hash common.Hash) (state.Account, error) { +func (pm *ProtocolManager) getAccount(statedb *state.StateDB, root, hash common.Hash) (types.StateAccount, error) { trie, err := trie.New(root, statedb.Database().TrieDB()) if err != nil { - return state.Account{}, err + return types.StateAccount{}, err } blob, err := trie.TryGet(hash[:]) if err != nil { - return state.Account{}, err + return types.StateAccount{}, err } - var account state.Account + var account types.StateAccount if err = rlp.DecodeBytes(blob, &account); err != nil { - return state.Account{}, err + return types.StateAccount{}, err } return account, nil }