Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

all: use uint256 in state #28598

Merged
merged 2 commits into from
Jan 23, 2024
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
9 changes: 5 additions & 4 deletions cmd/evm/internal/t8ntool/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
)

Expand Down Expand Up @@ -308,15 +309,15 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
reward.Sub(reward, new(big.Int).SetUint64(ommer.Delta))
reward.Mul(reward, blockReward)
reward.Div(reward, big.NewInt(8))
statedb.AddBalance(ommer.Address, reward)
statedb.AddBalance(ommer.Address, uint256.MustFromBig(reward))
}
statedb.AddBalance(pre.Env.Coinbase, minerReward)
statedb.AddBalance(pre.Env.Coinbase, uint256.MustFromBig(minerReward))
}
// Apply withdrawals
for _, w := range pre.Env.Withdrawals {
// Amount is in gwei, turn into wei
amount := new(big.Int).Mul(new(big.Int).SetUint64(w.Amount), big.NewInt(params.GWei))
statedb.AddBalance(w.Address, amount)
statedb.AddBalance(w.Address, uint256.MustFromBig(amount))
}
// Commit block
root, err := statedb.Commit(vmContext.BlockNumber.Uint64(), chainConfig.IsEIP158(vmContext.BlockNumber))
Expand Down Expand Up @@ -359,7 +360,7 @@ func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB
for addr, a := range accounts {
statedb.SetCode(addr, a.Code)
statedb.SetNonce(addr, a.Nonce)
statedb.SetBalance(addr, a.Balance)
statedb.SetBalance(addr, uint256.MustFromBig(a.Balance))
for k, v := range a.Storage {
statedb.SetState(addr, k, v)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/evm/internal/t8ntool/transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ func (g Alloc) OnAccount(addr *common.Address, dumpAccount state.DumpAccount) {
if addr == nil {
return
}
balance, _ := new(big.Int).SetString(dumpAccount.Balance, 10)
balance, _ := new(big.Int).SetString(dumpAccount.Balance, 0)
rjl493456442 marked this conversation as resolved.
Show resolved Hide resolved
var storage map[common.Hash]common.Hash
if dumpAccount.Storage != nil {
storage = make(map[common.Hash]common.Hash)
Expand Down
8 changes: 7 additions & 1 deletion common/big.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@

package common

import "math/big"
import (
"math/big"

"github.com/holiman/uint256"
)

// Common big integers often used
var (
Expand All @@ -27,4 +31,6 @@ var (
Big32 = big.NewInt(32)
Big256 = big.NewInt(256)
Big257 = big.NewInt(257)

U2560 = uint256.NewInt(0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
U2560 = uint256.NewInt(0)
U256_0 = uint256.NewInt(0)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I did that originally. But my editor went ahead and changed it. I think there might be something special about numerics and underscores.

)
5 changes: 3 additions & 2 deletions consensus/beacon/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie"
"github.com/holiman/uint256"
)

// Proof-of-stake protocol constants.
Expand Down Expand Up @@ -355,8 +356,8 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.
// Withdrawals processing.
for _, w := range withdrawals {
// Convert amount from gwei to wei.
amount := new(big.Int).SetUint64(w.Amount)
amount = amount.Mul(amount, big.NewInt(params.GWei))
amount := new(uint256.Int).SetUint64(w.Amount)
amount = amount.Mul(amount, uint256.NewInt(params.GWei))
state.AddBalance(w.Address, amount)
}
// No block reward which is issued by consensus layer instead.
Expand Down
29 changes: 16 additions & 13 deletions consensus/ethash/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,17 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/holiman/uint256"
"golang.org/x/crypto/sha3"
)

// Ethash proof-of-work protocol constants.
var (
FrontierBlockReward = big.NewInt(5e+18) // Block reward in wei for successfully mining a block
ByzantiumBlockReward = big.NewInt(3e+18) // Block reward in wei for successfully mining a block upward from Byzantium
ConstantinopleBlockReward = big.NewInt(2e+18) // Block reward in wei for successfully mining a block upward from Constantinople
maxUncles = 2 // Maximum number of uncles allowed in a single block
allowedFutureBlockTimeSeconds = int64(15) // Max seconds from current time allowed for blocks, before they're considered future blocks
FrontierBlockReward = uint256.NewInt(5e+18) // Block reward in wei for successfully mining a block
ByzantiumBlockReward = uint256.NewInt(3e+18) // Block reward in wei for successfully mining a block upward from Byzantium
ConstantinopleBlockReward = uint256.NewInt(2e+18) // Block reward in wei for successfully mining a block upward from Constantinople
maxUncles = 2 // Maximum number of uncles allowed in a single block
allowedFutureBlockTimeSeconds = int64(15) // Max seconds from current time allowed for blocks, before they're considered future blocks

// calcDifficultyEip5133 is the difficulty adjustment algorithm as specified by EIP 5133.
// It offsets the bomb a total of 11.4M blocks.
Expand Down Expand Up @@ -562,8 +563,8 @@ func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) {

// Some weird constants to avoid constant memory allocs for them.
var (
big8 = big.NewInt(8)
big32 = big.NewInt(32)
u256_8 = uint256.NewInt(8)
u256_32 = uint256.NewInt(32)
)

// AccumulateRewards credits the coinbase of the given block with the mining
Expand All @@ -579,16 +580,18 @@ func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header
blockReward = ConstantinopleBlockReward
}
// Accumulate the rewards for the miner and any included uncles
reward := new(big.Int).Set(blockReward)
r := new(big.Int)
reward := new(uint256.Int).Set(blockReward)
r := new(uint256.Int)
hNum, _ := uint256.FromBig(header.Number)
for _, uncle := range uncles {
r.Add(uncle.Number, big8)
r.Sub(r, header.Number)
uNum, _ := uint256.FromBig(uncle.Number)
r.AddUint64(uNum, 8)
r.Sub(r, hNum)
r.Mul(r, blockReward)
r.Div(r, big8)
r.Div(r, u256_8)
state.AddBalance(uncle.Coinbase, r)

r.Div(blockReward, big32)
r.Div(blockReward, u256_32)
reward.Add(reward, r)
}
state.AddBalance(header.Coinbase, reward)
Expand Down
3 changes: 2 additions & 1 deletion consensus/misc/dao.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
)

var (
Expand Down Expand Up @@ -81,6 +82,6 @@ func ApplyDAOHardFork(statedb *state.StateDB) {
// Move every DAO account and extra-balance account funds into the refund contract
for _, addr := range params.DAODrainList() {
statedb.AddBalance(params.DAORefundContract, statedb.GetBalance(addr))
statedb.SetBalance(addr, new(big.Int))
statedb.SetBalance(addr, new(uint256.Int))
}
}
21 changes: 11 additions & 10 deletions core/blockchain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
"github.com/holiman/uint256"
)

// So we can deterministically seed different blockchains
Expand Down Expand Up @@ -3652,7 +3653,7 @@ func testInitThenFailCreateContract(t *testing.T, scheme string) {
defer chain.Stop()

statedb, _ := chain.State()
if got, exp := statedb.GetBalance(aa), big.NewInt(100000); got.Cmp(exp) != 0 {
if got, exp := statedb.GetBalance(aa), uint256.NewInt(100000); got.Cmp(exp) != 0 {
t.Fatalf("Genesis err, got %v exp %v", got, exp)
}
// First block tries to create, but fails
Expand All @@ -3662,7 +3663,7 @@ func testInitThenFailCreateContract(t *testing.T, scheme string) {
t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err)
}
statedb, _ = chain.State()
if got, exp := statedb.GetBalance(aa), big.NewInt(100000); got.Cmp(exp) != 0 {
if got, exp := statedb.GetBalance(aa), uint256.NewInt(100000); got.Cmp(exp) != 0 {
t.Fatalf("block %d: got %v exp %v", block.NumberU64(), got, exp)
}
}
Expand Down Expand Up @@ -3848,17 +3849,17 @@ func testEIP1559Transition(t *testing.T, scheme string) {
state, _ := chain.State()

// 3: Ensure that miner received only the tx's tip.
actual := state.GetBalance(block.Coinbase())
actual := state.GetBalance(block.Coinbase()).ToBig()
expected := new(big.Int).Add(
new(big.Int).SetUint64(block.GasUsed()*block.Transactions()[0].GasTipCap().Uint64()),
ethash.ConstantinopleBlockReward,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is kind of lazy here. Should we just compute the expected value as uint256 as well and then compare?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we do it in big.Int, then the test can simply do the calculations, and not worry about overflows or negatives. You might call it lazy, but on the other hand, it means that the test becomes less encumbered with overflow spot-checks.

All in all, I think it's better the way it is (I started changing it, and didn't find the changed code to be an improvement)

ethash.ConstantinopleBlockReward.ToBig(),
)
if actual.Cmp(expected) != 0 {
t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual)
}

// 4: Ensure the tx sender paid for the gasUsed * (tip + block baseFee).
actual = new(big.Int).Sub(funds, state.GetBalance(addr1))
actual = new(big.Int).Sub(funds, state.GetBalance(addr1).ToBig())
expected = new(big.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GasTipCap().Uint64() + block.BaseFee().Uint64()))
if actual.Cmp(expected) != 0 {
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
Expand Down Expand Up @@ -3888,17 +3889,17 @@ func testEIP1559Transition(t *testing.T, scheme string) {
effectiveTip := block.Transactions()[0].GasTipCap().Uint64() - block.BaseFee().Uint64()

// 6+5: Ensure that miner received only the tx's effective tip.
actual = state.GetBalance(block.Coinbase())
actual = state.GetBalance(block.Coinbase()).ToBig()
expected = new(big.Int).Add(
new(big.Int).SetUint64(block.GasUsed()*effectiveTip),
ethash.ConstantinopleBlockReward,
ethash.ConstantinopleBlockReward.ToBig(),
)
if actual.Cmp(expected) != 0 {
t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual)
}

// 4: Ensure the tx sender paid for the gasUsed * (effectiveTip + block baseFee).
actual = new(big.Int).Sub(funds, state.GetBalance(addr2))
actual = new(big.Int).Sub(funds, state.GetBalance(addr2).ToBig())
expected = new(big.Int).SetUint64(block.GasUsed() * (effectiveTip + block.BaseFee().Uint64()))
if actual.Cmp(expected) != 0 {
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
Expand Down Expand Up @@ -4703,14 +4704,14 @@ func TestEIP3651(t *testing.T) {
state, _ := chain.State()

// 3: Ensure that miner received only the tx's tip.
actual := state.GetBalance(block.Coinbase())
actual := state.GetBalance(block.Coinbase()).ToBig()
expected := new(big.Int).SetUint64(block.GasUsed() * block.Transactions()[0].GasTipCap().Uint64())
if actual.Cmp(expected) != 0 {
t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual)
}

// 4: Ensure the tx sender paid for the gasUsed * (tip + block baseFee).
actual = new(big.Int).Sub(funds, state.GetBalance(addr1))
actual = new(big.Int).Sub(funds, state.GetBalance(addr1).ToBig())
expected = new(big.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GasTipCap().Uint64() + block.BaseFee().Uint64()))
if actual.Cmp(expected) != 0 {
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
Expand Down
3 changes: 2 additions & 1 deletion core/chain_makers.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie"
"github.com/holiman/uint256"
)

// BlockGen creates blocks for testing.
Expand Down Expand Up @@ -157,7 +158,7 @@ func (b *BlockGen) AddTxWithVMConfig(tx *types.Transaction, config vm.Config) {
}

// GetBalance returns the balance of the given address at the generated block.
func (b *BlockGen) GetBalance(addr common.Address) *big.Int {
func (b *BlockGen) GetBalance(addr common.Address) *uint256.Int {
return b.statedb.GetBalance(addr)
}

Expand Down
5 changes: 3 additions & 2 deletions core/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/holiman/uint256"
)

// ChainContext supports retrieving headers and consensus parameters from the
Expand Down Expand Up @@ -129,12 +130,12 @@ func GetHashFn(ref *types.Header, chain ChainContext) func(n uint64) common.Hash

// CanTransfer checks whether there are enough funds in the address' account to make a transfer.
// This does not take the necessary gas in to account to make the transfer valid.
func CanTransfer(db vm.StateDB, addr common.Address, amount *big.Int) bool {
func CanTransfer(db vm.StateDB, addr common.Address, amount *uint256.Int) bool {
return db.GetBalance(addr).Cmp(amount) >= 0
}

// Transfer subtracts amount from sender and adds amount to recipient using the given Db
func Transfer(db vm.StateDB, sender, recipient common.Address, amount *big.Int) {
func Transfer(db vm.StateDB, sender, recipient common.Address, amount *uint256.Int) {
db.SubBalance(sender, amount)
db.AddBalance(recipient, amount)
}
5 changes: 3 additions & 2 deletions core/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
"github.com/holiman/uint256"
)

//go:generate go run github.com/fjl/gencodec -type Genesis -field-override genesisSpecMarshaling -out gen_genesis.go
Expand Down Expand Up @@ -142,7 +143,7 @@ func (ga *GenesisAlloc) hash(isVerkle bool) (common.Hash, error) {
}
for addr, account := range *ga {
if account.Balance != nil {
statedb.AddBalance(addr, account.Balance)
statedb.AddBalance(addr, uint256.MustFromBig(account.Balance))
}
statedb.SetCode(addr, account.Code)
statedb.SetNonce(addr, account.Nonce)
Expand All @@ -163,7 +164,7 @@ func (ga *GenesisAlloc) flush(db ethdb.Database, triedb *trie.Database, blockhas
}
for addr, account := range *ga {
if account.Balance != nil {
statedb.AddBalance(addr, account.Balance)
statedb.AddBalance(addr, uint256.MustFromBig(account.Balance))
}
statedb.SetCode(addr, account.Code)
statedb.SetNonce(addr, account.Nonce)
Expand Down
7 changes: 3 additions & 4 deletions core/state/journal.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@
package state

import (
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/holiman/uint256"
)

// journalEntry is a modification entry in the state change journal that can be
Expand Down Expand Up @@ -103,13 +102,13 @@ type (
selfDestructChange struct {
account *common.Address
prev bool // whether account had already self-destructed
prevbalance *big.Int
prevbalance *uint256.Int
}

// Changes to individual accounts.
balanceChange struct {
account *common.Address
prev *big.Int
prev *uint256.Int
}
nonceChange struct {
account *common.Address
Expand Down
Loading
Loading