a5a4fa7032
This change makes use of uin256 to represent balance in state. It touches primarily upon statedb, stateobject and state processing, trying to avoid changes in transaction pools, core types, rpc and tracers.
122 lines
3.6 KiB
Go
122 lines
3.6 KiB
Go
// 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 (
|
|
"bytes"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/rlp"
|
|
"github.com/holiman/uint256"
|
|
)
|
|
|
|
//go:generate go run ../../rlp/rlpgen -type StateAccount -out gen_account_rlp.go
|
|
|
|
// StateAccount is the Ethereum consensus representation of accounts.
|
|
// These objects are stored in the main account trie.
|
|
type StateAccount struct {
|
|
Nonce uint64
|
|
Balance *uint256.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(uint256.Int),
|
|
Root: EmptyRootHash,
|
|
CodeHash: EmptyCodeHash.Bytes(),
|
|
}
|
|
}
|
|
|
|
// Copy returns a deep-copied state account object.
|
|
func (acct *StateAccount) Copy() *StateAccount {
|
|
var balance *uint256.Int
|
|
if acct.Balance != nil {
|
|
balance = new(uint256.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 *uint256.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 returns
|
|
// 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)
|
|
}
|