Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions core/state/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/common/lru"
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/ethdb"
"github.com/XinFinOrg/XDPoSChain/trie"
)
Expand Down Expand Up @@ -69,6 +70,9 @@ type Trie interface {
// trie.MissingNodeError is returned.
TryGet(key []byte) ([]byte, error)

// TryUpdateAccount abstract an account write in the trie.
TryUpdateAccount(key []byte, account *types.StateAccount) error

// TryUpdate associates key with value in the trie. If value has length zero, any
// existing value is deleted from the trie. The value bytes must not be modified
// by the caller while they are stored in the trie. If a node was not found in the
Expand Down
3 changes: 2 additions & 1 deletion core/state/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/log"
"github.com/XinFinOrg/XDPoSChain/rlp"
"github.com/XinFinOrg/XDPoSChain/trie"
Expand Down Expand Up @@ -91,7 +92,7 @@ func (s *StateDB) dump(c collector, excludeCode, excludeStorage, excludeMissingP
c.onRoot(s.trie.Hash())
it := trie.NewIterator(s.trie.NodeIterator(nil))
for it.Next() {
var data Account
var data types.StateAccount
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
panic(err)
}
Expand Down
2 changes: 1 addition & 1 deletion core/state/iterator.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,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
}
Expand Down
19 changes: 5 additions & 14 deletions core/state/state_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ func (s Storage) Copy() Storage {
// Finally, call commitTrie to write the modified storage trie into a database.
type stateObject struct {
db *StateDB
address common.Address // address of ethereum account
addrHash common.Hash // hash of ethereum address of the account
data Account // Account data with all mutations applied in the scope of block
address common.Address // address of ethereum account
addrHash common.Hash // hash of ethereum address of the account
data types.StateAccount // Account data with all mutations applied in the scope of block

// DB error.
// State objects are used by the consensus core and VM which are
Expand Down Expand Up @@ -103,17 +103,8 @@ func (s *stateObject) empty() bool {
return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, types.EmptyCodeHash.Bytes())
}

// 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) *stateObject {
func newObject(db *StateDB, address common.Address, data types.StateAccount) *stateObject {
if data.Balance == nil {
data.Balance = new(big.Int)
}
Expand All @@ -136,7 +127,7 @@ func newObject(db *StateDB, address common.Address, data Account) *stateObject {

// EncodeRLP implements rlp.Encoder.
func (s *stateObject) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, s.data)
return rlp.Encode(w, &s.data)
}

// setError remembers the first non-nil error it is called with.
Expand Down
17 changes: 6 additions & 11 deletions core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -492,12 +492,7 @@ func (s *StateDB) updateStateObject(obj *stateObject) {

// Encode the account and update the account trie
addr := obj.Address()

data, err := rlp.EncodeToBytes(obj)
if err != nil {
panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err))
}
if err = s.trie.TryUpdate(addr[:], data); err != nil {
if err := s.trie.TryUpdateAccount(addr[:], &obj.data); err != nil {
s.setError(fmt.Errorf("updateStateObject (%x) error: %v", addr[:], err))
}
}
Expand Down Expand Up @@ -554,13 +549,13 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject {
if len(enc) == 0 {
return nil
}
var data Account
if err := rlp.DecodeBytes(enc, &data); err != nil {
data := new(types.StateAccount)
if err := rlp.DecodeBytes(enc, data); err != nil {
log.Error("Failed to decode state object", "addr", addr, "err", err)
return nil
}
// Insert into the live set
obj := newObject(s, addr, data)
obj := newObject(s, addr, *data)
s.setStateObject(obj)
return obj
}
Expand All @@ -582,7 +577,7 @@ func (s *StateDB) GetOrNewStateObject(addr common.Address) *stateObject {
// the given address, it is overwritten and returned as the second return value.
func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) {
prev = s.getDeletedStateObject(addr) // Note, prev might have been deleted, we need that!
newobj = newObject(s, addr, Account{})
newobj = newObject(s, addr, types.StateAccount{})
if prev == nil {
s.journal.append(createObjectChange{account: &addr})
} else {
Expand Down Expand Up @@ -852,7 +847,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) {
start := time.Now()

root, accountCommitted, err := s.trie.Commit(func(_ [][]byte, _ []byte, leaf []byte, parent common.Hash) error {
var account Account
var account types.StateAccount
if err := rlp.DecodeBytes(leaf, &account); err != nil {
return nil
}
Expand Down
3 changes: 2 additions & 1 deletion core/state/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"bytes"

"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/ethdb"
"github.com/XinFinOrg/XDPoSChain/rlp"
"github.com/XinFinOrg/XDPoSChain/trie"
Expand All @@ -43,7 +44,7 @@ func NewStateSync(root common.Hash, database ethdb.KeyValueReader, bloom *trie.S
return err
}
}
var obj Account
var obj types.StateAccount
if err := rlp.Decode(bytes.NewReader(leaf), &obj); err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion core/state/sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ func testIterativeStateSync(t *testing.T, count int, commit bool, bypath bool) {
}
results[len(hashQueue)+i] = trie.SyncResult{Hash: crypto.Keccak256Hash(data), Data: data}
} else {
var acc Account
var acc types.StateAccount
if err := rlp.DecodeBytes(srcTrie.Get(path[0]), &acc); err != nil {
t.Fatalf("failed to decode account on path %x: %v", path, err)
}
Expand Down
32 changes: 32 additions & 0 deletions core/types/state_account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2021 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 <http://www.gnu.org/licenses/>.

package types

import (
"math/big"

"github.com/XinFinOrg/XDPoSChain/common"
)

// 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
}
17 changes: 17 additions & 0 deletions trie/secure_trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ import (
"fmt"

"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/log"
"github.com/XinFinOrg/XDPoSChain/rlp"
)

// SecureTrie wraps a trie with key hashing. In a secure trie, all
Expand Down Expand Up @@ -85,6 +87,21 @@ func (t *SecureTrie) TryGetNode(path []byte) ([]byte, int, error) {
return t.trie.TryGetNode(path)
}

// TryUpdateAccount will abstract the write of an account to the
// secure trie.
func (t *SecureTrie) TryUpdateAccount(key []byte, acc *types.StateAccount) error {
hk := t.hashKey(key)
data, err := rlp.EncodeToBytes(acc)
if err != nil {
return err
}
if err := t.trie.TryUpdate(hk, data); err != nil {
return err
}
t.getSecKeyCache()[string(hk)] = common.CopyBytes(key)
return nil
}

// Update associates key with value in the trie. Subsequent calls to
// Get will return value. If value has length zero, any existing value
// is deleted from the trie and calls to Get will return nil.
Expand Down
9 changes: 9 additions & 0 deletions trie/trie.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/log"
"github.com/XinFinOrg/XDPoSChain/rlp"
)

// LeafCallback is a callback type invoked when a trie operation reaches a leaf
Expand Down Expand Up @@ -402,6 +403,14 @@ func (t *Trie) Update(key, value []byte) {
}
}

func (t *Trie) TryUpdateAccount(key []byte, acc *types.StateAccount) error {
data, err := rlp.EncodeToBytes(acc)
if err != nil {
return fmt.Errorf("can't encode object at %x: %w", key[:], err)
}
return t.TryUpdate(key, data)
}

// TryUpdate associates key with value in the trie. Subsequent calls to
// Get will return value. If value has length zero, any existing value
// is deleted from the trie and calls to Get will return nil.
Expand Down
11 changes: 2 additions & 9 deletions trie/trie_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -481,13 +481,6 @@ func BenchmarkHash(b *testing.B) {
trie.Hash()
}

type account struct {
Nonce uint64
Balance *big.Int
Root common.Hash
Code []byte
}

// Benchmarks the trie Commit following a Hash. Since the trie caches the result of any operation,
// we cannot use b.N as the number of hashing rounds, since all rounds apart from
// the first one will be NOOP. As such, we'll use b.N as the number of account to
Expand All @@ -496,7 +489,7 @@ func BenchmarkCommitAfterHash(b *testing.B) {
b.Run("no-onleaf", func(b *testing.B) {
benchmarkCommitAfterHash(b, nil)
})
var a account
var a types.StateAccount
onleaf := func(_ [][]byte, _ []byte, leaf []byte, parent common.Hash) error {
rlp.DecodeBytes(leaf, &a)
return nil
Expand Down Expand Up @@ -592,7 +585,7 @@ func makeAccounts(size int) (addresses [][20]byte, accounts [][]byte) {
balanceBytes := make([]byte, numBytes)
random.Read(balanceBytes)
balance := new(big.Int).SetBytes(balanceBytes)
data, _ := rlp.EncodeToBytes(&account{nonce, balance, root, code})
data, _ := rlp.EncodeToBytes(&types.StateAccount{Nonce: nonce, Balance: balance, Root: root, CodeHash: code})
accounts[i] = data
}
return addresses, accounts
Expand Down