From cc1238a1433296fd05fc6b8aa2f76c7d84d27ca1 Mon Sep 17 00:00:00 2001 From: Devon Bear Date: Mon, 16 Jan 2023 18:18:58 -0500 Subject: [PATCH 01/40] stateful --- core/vm/contracts.go | 59 ++++++++++++++++++++++---------------------- core/vm/evm.go | 55 ++++++++++++++++++++++++++++++----------- go.sum | 8 ++++++ 3 files changed, 78 insertions(+), 44 deletions(-) diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 9a52616657bb..162ba6c80413 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -37,8 +37,8 @@ import ( // requires a deterministic gas count based on the input size of the Run method of the // contract. type PrecompiledContract interface { - RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use - Run(input []byte) ([]byte, error) // Run runs the precompiled contract + RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use + Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) // Run runs the precompiled contract } // PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum @@ -152,7 +152,7 @@ func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uin return nil, 0, ErrOutOfGas } suppliedGas -= gasCost - output, err := p.Run(input) + output, err := p.Run(nil, input, common.Address{}, nil, true) return output, suppliedGas, err } @@ -163,7 +163,7 @@ func (c *ecrecover) RequiredGas(input []byte) uint64 { return params.EcrecoverGas } -func (c *ecrecover) Run(input []byte) ([]byte, error) { +func (c *ecrecover) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { const ecRecoverInputLength = 128 input = common.RightPadBytes(input, ecRecoverInputLength) @@ -204,7 +204,7 @@ type sha256hash struct{} func (c *sha256hash) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas } -func (c *sha256hash) Run(input []byte) ([]byte, error) { +func (c *sha256hash) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { h := sha256.Sum256(input) return h[:], nil } @@ -219,7 +219,7 @@ type ripemd160hash struct{} func (c *ripemd160hash) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas } -func (c *ripemd160hash) Run(input []byte) ([]byte, error) { +func (c *ripemd160hash) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { ripemd := ripemd160.New() ripemd.Write(input) return common.LeftPadBytes(ripemd.Sum(nil), 32), nil @@ -235,8 +235,8 @@ type dataCopy struct{} func (c *dataCopy) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas } -func (c *dataCopy) Run(in []byte) ([]byte, error) { - return common.CopyBytes(in), nil +func (c *dataCopy) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { + return input, nil } // bigModExp implements a native big integer exponential modular operation. @@ -264,10 +264,11 @@ var ( // modexpMultComplexity implements bigModexp multComplexity formula, as defined in EIP-198 // -// def mult_complexity(x): -// if x <= 64: return x ** 2 -// elif x <= 1024: return x ** 2 // 4 + 96 * x - 3072 -// else: return x ** 2 // 16 + 480 * x - 199680 +// def mult_complexity(x): +// +// if x <= 64: return x ** 2 +// elif x <= 1024: return x ** 2 // 4 + 96 * x - 3072 +// else: return x ** 2 // 16 + 480 * x - 199680 // // where is x is max(length_of_MODULUS, length_of_BASE) func modexpMultComplexity(x *big.Int) *big.Int { @@ -361,7 +362,7 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 { return gas.Uint64() } -func (c *bigModExp) Run(input []byte) ([]byte, error) { +func (c *bigModExp) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { var ( baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64() expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64() @@ -441,7 +442,7 @@ func (c *bn256AddIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256AddGasIstanbul } -func (c *bn256AddIstanbul) Run(input []byte) ([]byte, error) { +func (c *bn256AddIstanbul) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Add(input) } @@ -454,7 +455,7 @@ func (c *bn256AddByzantium) RequiredGas(input []byte) uint64 { return params.Bn256AddGasByzantium } -func (c *bn256AddByzantium) Run(input []byte) ([]byte, error) { +func (c *bn256AddByzantium) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Add(input) } @@ -479,7 +480,7 @@ func (c *bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256ScalarMulGasIstanbul } -func (c *bn256ScalarMulIstanbul) Run(input []byte) ([]byte, error) { +func (c *bn256ScalarMulIstanbul) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256ScalarMul(input) } @@ -492,7 +493,7 @@ func (c *bn256ScalarMulByzantium) RequiredGas(input []byte) uint64 { return params.Bn256ScalarMulGasByzantium } -func (c *bn256ScalarMulByzantium) Run(input []byte) ([]byte, error) { +func (c *bn256ScalarMulByzantium) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256ScalarMul(input) } @@ -547,7 +548,7 @@ func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul } -func (c *bn256PairingIstanbul) Run(input []byte) ([]byte, error) { +func (c *bn256PairingIstanbul) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Pairing(input) } @@ -560,7 +561,7 @@ func (c *bn256PairingByzantium) RequiredGas(input []byte) uint64 { return params.Bn256PairingBaseGasByzantium + uint64(len(input)/192)*params.Bn256PairingPerPointGasByzantium } -func (c *bn256PairingByzantium) Run(input []byte) ([]byte, error) { +func (c *bn256PairingByzantium) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Pairing(input) } @@ -586,7 +587,7 @@ var ( errBlake2FInvalidFinalFlag = errors.New("invalid final flag") ) -func (c *blake2F) Run(input []byte) ([]byte, error) { +func (c *blake2F) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Make sure the input is valid (correct length and final flag) if len(input) != blake2FInputLength { return nil, errBlake2FInvalidInputLength @@ -640,7 +641,7 @@ func (c *bls12381G1Add) RequiredGas(input []byte) uint64 { return params.Bls12381G1AddGas } -func (c *bls12381G1Add) Run(input []byte) ([]byte, error) { +func (c *bls12381G1Add) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G1Add precompile. // > G1 addition call expects `256` bytes as an input that is interpreted as byte concatenation of two G1 points (`128` bytes each). // > Output is an encoding of addition operation result - single G1 point (`128` bytes). @@ -678,7 +679,7 @@ func (c *bls12381G1Mul) RequiredGas(input []byte) uint64 { return params.Bls12381G1MulGas } -func (c *bls12381G1Mul) Run(input []byte) ([]byte, error) { +func (c *bls12381G1Mul) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G1Mul precompile. // > G1 multiplication call expects `160` bytes as an input that is interpreted as byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). // > Output is an encoding of multiplication operation result - single G1 point (`128` bytes). @@ -728,7 +729,7 @@ func (c *bls12381G1MultiExp) RequiredGas(input []byte) uint64 { return (uint64(k) * params.Bls12381G1MulGas * discount) / 1000 } -func (c *bls12381G1MultiExp) Run(input []byte) ([]byte, error) { +func (c *bls12381G1MultiExp) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G1MultiExp precompile. // G1 multiplication call expects `160*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). // Output is an encoding of multiexponentiation operation result - single G1 point (`128` bytes). @@ -771,7 +772,7 @@ func (c *bls12381G2Add) RequiredGas(input []byte) uint64 { return params.Bls12381G2AddGas } -func (c *bls12381G2Add) Run(input []byte) ([]byte, error) { +func (c *bls12381G2Add) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G2Add precompile. // > G2 addition call expects `512` bytes as an input that is interpreted as byte concatenation of two G2 points (`256` bytes each). // > Output is an encoding of addition operation result - single G2 point (`256` bytes). @@ -809,7 +810,7 @@ func (c *bls12381G2Mul) RequiredGas(input []byte) uint64 { return params.Bls12381G2MulGas } -func (c *bls12381G2Mul) Run(input []byte) ([]byte, error) { +func (c *bls12381G2Mul) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G2MUL precompile logic. // > G2 multiplication call expects `288` bytes as an input that is interpreted as byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). // > Output is an encoding of multiplication operation result - single G2 point (`256` bytes). @@ -859,7 +860,7 @@ func (c *bls12381G2MultiExp) RequiredGas(input []byte) uint64 { return (uint64(k) * params.Bls12381G2MulGas * discount) / 1000 } -func (c *bls12381G2MultiExp) Run(input []byte) ([]byte, error) { +func (c *bls12381G2MultiExp) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G2MultiExp precompile logic // > G2 multiplication call expects `288*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). // > Output is an encoding of multiexponentiation operation result - single G2 point (`256` bytes). @@ -902,7 +903,7 @@ func (c *bls12381Pairing) RequiredGas(input []byte) uint64 { return params.Bls12381PairingBaseGas + uint64(len(input)/384)*params.Bls12381PairingPerPairGas } -func (c *bls12381Pairing) Run(input []byte) ([]byte, error) { +func (c *bls12381Pairing) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 Pairing precompile logic. // > Pairing call expects `384*k` bytes as an inputs that is interpreted as byte concatenation of `k` slices. Each slice has the following structure: // > - `128` bytes of G1 point encoding @@ -981,7 +982,7 @@ func (c *bls12381MapG1) RequiredGas(input []byte) uint64 { return params.Bls12381MapG1Gas } -func (c *bls12381MapG1) Run(input []byte) ([]byte, error) { +func (c *bls12381MapG1) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 Map_To_G1 precompile. // > Field-to-curve call expects `64` bytes an an input that is interpreted as a an element of the base field. // > Output of this call is `128` bytes and is G1 point following respective encoding rules. @@ -1016,7 +1017,7 @@ func (c *bls12381MapG2) RequiredGas(input []byte) uint64 { return params.Bls12381MapG2Gas } -func (c *bls12381MapG2) Run(input []byte) ([]byte, error) { +func (c *bls12381MapG2) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 Map_FP2_TO_G2 precompile logic. // > Field-to-curve call expects `128` bytes an an input that is interpreted as a an element of the quadratic extension field. // > Output of this call is `256` bytes and is G2 point following respective encoding rules. diff --git a/core/vm/evm.go b/core/vm/evm.go index d78ea0792664..5144fc691e3d 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -40,14 +40,22 @@ type ( GetHashFunc func(uint64) common.Hash ) -func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { +type PrecompileRegistry interface { + GetContract(addr common.Address) (PrecompiledContract, bool) +} + +type BasePrecompileRegistry struct { + chainRules params.Rules +} + +func (bpm *BasePrecompileRegistry) GetContract(addr common.Address) (PrecompiledContract, bool) { var precompiles map[common.Address]PrecompiledContract switch { - case evm.chainRules.IsBerlin: + case bpm.chainRules.IsBerlin: precompiles = PrecompiledContractsBerlin - case evm.chainRules.IsIstanbul: + case bpm.chainRules.IsIstanbul: precompiles = PrecompiledContractsIstanbul - case evm.chainRules.IsByzantium: + case bpm.chainRules.IsByzantium: precompiles = PrecompiledContractsByzantium default: precompiles = PrecompiledContractsHomestead @@ -56,6 +64,17 @@ func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) { return p, ok } +func RunContract(sdb StateDB, p PrecompiledContract, input []byte, caller common.Address, + value *big.Int, suppliedGas uint64, readonly bool) (ret []byte, remainingGas uint64, err error) { + gasCost := p.RequiredGas(input) + if suppliedGas < gasCost { + return nil, 0, ErrOutOfGas + } + suppliedGas -= gasCost + output, err := p.Run(sdb, input, caller, value, readonly) + return output, suppliedGas, err +} + // BlockContext provides the EVM with auxiliary information. Once provided // it shouldn't be modified. type BlockContext struct { @@ -100,6 +119,8 @@ type EVM struct { TxContext // StateDB gives access to the underlying state StateDB StateDB + // PrecompileRegistry gives access to the precompiled contracts + PrecompileRegistry PrecompileRegistry // Depth is the current call stack depth int @@ -126,9 +147,12 @@ type EVM struct { // only ever be used *once*. func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *EVM { evm := &EVM{ - Context: blockCtx, - TxContext: txCtx, - StateDB: statedb, + Context: blockCtx, + TxContext: txCtx, + StateDB: statedb, + PrecompileRegistry: &BasePrecompileRegistry{ + chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil), + }, Config: config, chainConfig: chainConfig, chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time), @@ -182,7 +206,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas return nil, gas, ErrInsufficientBalance } snapshot := evm.StateDB.Snapshot() - p, isPrecompile := evm.precompile(addr) + p, isPrecompile := evm.PrecompileRegistry.GetContract(addr) if !evm.StateDB.Exist(addr) { if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 { @@ -219,7 +243,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas } if isPrecompile { - ret, gas, err = RunPrecompiledContract(p, input, gas) + ret, gas, err = RunContract(evm.StateDB, p, input, caller.Address(), value, gas, false) } else { // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. @@ -281,8 +305,8 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, } // It is allowed to call precompiles, even via delegatecall - if p, isPrecompile := evm.precompile(addr); isPrecompile { - ret, gas, err = RunPrecompiledContract(p, input, gas) + if p, isPrecompile := evm.PrecompileRegistry.GetContract(addr); isPrecompile { + ret, gas, err = RunContract(evm.StateDB, p, input, caller.Address(), value, gas, true) } else { addrCopy := addr // Initialise a new contract and set the code that is to be used by the EVM. @@ -326,8 +350,9 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by } // It is allowed to call precompiles, even via delegatecall - if p, isPrecompile := evm.precompile(addr); isPrecompile { - ret, gas, err = RunPrecompiledContract(p, input, gas) + if p, isPrecompile := evm.PrecompileRegistry.GetContract(addr); isPrecompile { + parent := caller.(*Contract) + ret, gas, err = RunContract(evm.StateDB, p, input, parent.CallerAddress, parent.value, gas, false) } else { addrCopy := addr // Initialise a new contract and make initialise the delegate values @@ -375,8 +400,8 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte }(gas) } - if p, isPrecompile := evm.precompile(addr); isPrecompile { - ret, gas, err = RunPrecompiledContract(p, input, gas) + if p, isPrecompile := evm.PrecompileRegistry.GetContract(addr); isPrecompile { + ret, gas, err = RunContract(evm.StateDB, p, input, caller.Address(), new(big.Int), gas, true) } else { // At this point, we use a copy of address. If we don't, the go compiler will // leak the 'contract' to the outer scope, and make allocation for 'contract' diff --git a/go.sum b/go.sum index bf28cd2e24e5..0ddcfe7cce51 100644 --- a/go.sum +++ b/go.sum @@ -169,6 +169,7 @@ github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlK 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/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= @@ -712,6 +713,7 @@ golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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= @@ -729,6 +731,9 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/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/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -781,6 +786,9 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023 h1:0c3L82FDQ5rt1bjTBlchS8t6RQ6299/+5bWMnRLh+uI= +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= From 527b51da3e7fc6165fa905242e408bf50910a1c2 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Wed, 18 Jan 2023 11:57:21 -0500 Subject: [PATCH 02/40] use PrecompileExecutor --- core/vm/contracts.go | 15 --------- core/vm/evm.go | 80 +++++++++++++++----------------------------- 2 files changed, 27 insertions(+), 68 deletions(-) diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 162ba6c80413..83ecd1e20d56 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -141,21 +141,6 @@ func ActivePrecompiles(rules params.Rules) []common.Address { } } -// RunPrecompiledContract runs and evaluates the output of a precompiled contract. -// It returns -// - the returned bytes, -// - the _remaining_ gas, -// - any error that occurred -func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uint64) (ret []byte, remainingGas uint64, err error) { - gasCost := p.RequiredGas(input) - if suppliedGas < gasCost { - return nil, 0, ErrOutOfGas - } - suppliedGas -= gasCost - output, err := p.Run(nil, input, common.Address{}, nil, true) - return output, suppliedGas, err -} - // ECRECOVER implemented as a native contract. type ecrecover struct{} diff --git a/core/vm/evm.go b/core/vm/evm.go index 5144fc691e3d..306177cae951 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -40,39 +40,15 @@ type ( GetHashFunc func(uint64) common.Hash ) -type PrecompileRegistry interface { - GetContract(addr common.Address) (PrecompiledContract, bool) -} - -type BasePrecompileRegistry struct { - chainRules params.Rules -} - -func (bpm *BasePrecompileRegistry) GetContract(addr common.Address) (PrecompiledContract, bool) { - var precompiles map[common.Address]PrecompiledContract - switch { - case bpm.chainRules.IsBerlin: - precompiles = PrecompiledContractsBerlin - case bpm.chainRules.IsIstanbul: - precompiles = PrecompiledContractsIstanbul - case bpm.chainRules.IsByzantium: - precompiles = PrecompiledContractsByzantium - default: - precompiles = PrecompiledContractsHomestead - } - p, ok := precompiles[addr] - return p, ok -} - -func RunContract(sdb StateDB, p PrecompiledContract, input []byte, caller common.Address, - value *big.Int, suppliedGas uint64, readonly bool) (ret []byte, remainingGas uint64, err error) { - gasCost := p.RequiredGas(input) - if suppliedGas < gasCost { - return nil, 0, ErrOutOfGas - } - suppliedGas -= gasCost - output, err := p.Run(sdb, input, caller, value, readonly) - return output, suppliedGas, err +// `PrecompileExecutor` is allows the EVM to execute a precompiled contract. +type PrecompileExecutor interface { + // `Exists` returns if a precompiled contract was found at `addr`. + Exists(addr common.Address) bool + + // `Run` runs a precompiled contract and returns the leftover gas. + Run(sdb StateDB, input []byte, caller common.Address, + value *big.Int, suppliedGas uint64, readonly bool, + ) (ret []byte, leftOverGas uint64, err error) } // BlockContext provides the EVM with auxiliary information. Once provided @@ -119,8 +95,8 @@ type EVM struct { TxContext // StateDB gives access to the underlying state StateDB StateDB - // PrecompileRegistry gives access to the precompiled contracts - PrecompileRegistry PrecompileRegistry + // precompileExecutor gives access to the precompiled contracts + precompileExecutor PrecompileExecutor // Depth is the current call stack depth int @@ -145,17 +121,15 @@ type EVM struct { // NewEVM returns a new EVM. The returned EVM is not thread safe and should // only ever be used *once*. -func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *EVM { +func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config, precompileExecutor PrecompileExecutor) *EVM { evm := &EVM{ - Context: blockCtx, - TxContext: txCtx, - StateDB: statedb, - PrecompileRegistry: &BasePrecompileRegistry{ - chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil), - }, - Config: config, - chainConfig: chainConfig, - chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time), + Context: blockCtx, + TxContext: txCtx, + StateDB: statedb, + precompileExecutor: precompileExecutor, + Config: config, + chainConfig: chainConfig, + chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil), } evm.interpreter = NewEVMInterpreter(evm) return evm @@ -206,7 +180,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas return nil, gas, ErrInsufficientBalance } snapshot := evm.StateDB.Snapshot() - p, isPrecompile := evm.PrecompileRegistry.GetContract(addr) + isPrecompile := evm.precompileExecutor.Exists(addr) if !evm.StateDB.Exist(addr) { if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 { @@ -243,7 +217,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas } if isPrecompile { - ret, gas, err = RunContract(evm.StateDB, p, input, caller.Address(), value, gas, false) + ret, gas, err = evm.precompileExecutor.Run(evm.StateDB, input, caller.Address(), value, gas, false) } else { // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. @@ -305,8 +279,8 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, } // It is allowed to call precompiles, even via delegatecall - if p, isPrecompile := evm.PrecompileRegistry.GetContract(addr); isPrecompile { - ret, gas, err = RunContract(evm.StateDB, p, input, caller.Address(), value, gas, true) + if evm.precompileExecutor.Exists(addr) { + ret, gas, err = evm.precompileExecutor.Run(evm.StateDB, input, caller.Address(), value, gas, true) } else { addrCopy := addr // Initialise a new contract and set the code that is to be used by the EVM. @@ -350,9 +324,9 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by } // It is allowed to call precompiles, even via delegatecall - if p, isPrecompile := evm.PrecompileRegistry.GetContract(addr); isPrecompile { + if evm.precompileExecutor.Exists(addr) { parent := caller.(*Contract) - ret, gas, err = RunContract(evm.StateDB, p, input, parent.CallerAddress, parent.value, gas, false) + ret, gas, err = evm.precompileExecutor.Run(evm.StateDB, input, parent.CallerAddress, parent.value, gas, false) } else { addrCopy := addr // Initialise a new contract and make initialise the delegate values @@ -400,8 +374,8 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte }(gas) } - if p, isPrecompile := evm.PrecompileRegistry.GetContract(addr); isPrecompile { - ret, gas, err = RunContract(evm.StateDB, p, input, caller.Address(), new(big.Int), gas, true) + if evm.precompileExecutor.Exists(addr) { + ret, gas, err = evm.precompileExecutor.Run(evm.StateDB, input, caller.Address(), new(big.Int), gas, true) } else { // At this point, we use a copy of address. If we don't, the go compiler will // leak the 'contract' to the outer scope, and make allocation for 'contract' From fa71e1c7555e5e03b8db82d0b33ebf453e953ebd Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Wed, 18 Jan 2023 12:15:01 -0500 Subject: [PATCH 03/40] use host terminology --- core/vm/evm.go | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index 306177cae951..5fabc9bde73b 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -40,15 +40,15 @@ type ( GetHashFunc func(uint64) common.Hash ) -// `PrecompileExecutor` is allows the EVM to execute a precompiled contract. -type PrecompileExecutor interface { +// `PrecompileHost` is allows the EVM to execute a precompiled contract. +type PrecompileHost interface { // `Exists` returns if a precompiled contract was found at `addr`. Exists(addr common.Address) bool // `Run` runs a precompiled contract and returns the leftover gas. Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, suppliedGas uint64, readonly bool, - ) (ret []byte, leftOverGas uint64, err error) + ) (ret []byte, remainingGas uint64, err error) } // BlockContext provides the EVM with auxiliary information. Once provided @@ -95,8 +95,8 @@ type EVM struct { TxContext // StateDB gives access to the underlying state StateDB StateDB - // precompileExecutor gives access to the precompiled contracts - precompileExecutor PrecompileExecutor + // precompileHost gives access to the precompiled contracts + precompileHost PrecompileHost // Depth is the current call stack depth int @@ -121,15 +121,15 @@ type EVM struct { // NewEVM returns a new EVM. The returned EVM is not thread safe and should // only ever be used *once*. -func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config, precompileExecutor PrecompileExecutor) *EVM { +func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config, precompileHost PrecompileHost) *EVM { evm := &EVM{ - Context: blockCtx, - TxContext: txCtx, - StateDB: statedb, - precompileExecutor: precompileExecutor, - Config: config, - chainConfig: chainConfig, - chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil), + Context: blockCtx, + TxContext: txCtx, + StateDB: statedb, + precompileHost: precompileHost, + Config: config, + chainConfig: chainConfig, + chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil), } evm.interpreter = NewEVMInterpreter(evm) return evm @@ -180,7 +180,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas return nil, gas, ErrInsufficientBalance } snapshot := evm.StateDB.Snapshot() - isPrecompile := evm.precompileExecutor.Exists(addr) + isPrecompile := evm.precompileHost.Exists(addr) if !evm.StateDB.Exist(addr) { if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 { @@ -217,7 +217,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas } if isPrecompile { - ret, gas, err = evm.precompileExecutor.Run(evm.StateDB, input, caller.Address(), value, gas, false) + ret, gas, err = evm.precompileHost.Run(evm.StateDB, input, caller.Address(), value, gas, false) } else { // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. @@ -279,8 +279,8 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, } // It is allowed to call precompiles, even via delegatecall - if evm.precompileExecutor.Exists(addr) { - ret, gas, err = evm.precompileExecutor.Run(evm.StateDB, input, caller.Address(), value, gas, true) + if evm.precompileHost.Exists(addr) { + ret, gas, err = evm.precompileHost.Run(evm.StateDB, input, caller.Address(), value, gas, true) } else { addrCopy := addr // Initialise a new contract and set the code that is to be used by the EVM. @@ -324,9 +324,9 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by } // It is allowed to call precompiles, even via delegatecall - if evm.precompileExecutor.Exists(addr) { + if evm.precompileHost.Exists(addr) { parent := caller.(*Contract) - ret, gas, err = evm.precompileExecutor.Run(evm.StateDB, input, parent.CallerAddress, parent.value, gas, false) + ret, gas, err = evm.precompileHost.Run(evm.StateDB, input, parent.CallerAddress, parent.value, gas, false) } else { addrCopy := addr // Initialise a new contract and make initialise the delegate values @@ -374,8 +374,8 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte }(gas) } - if evm.precompileExecutor.Exists(addr) { - ret, gas, err = evm.precompileExecutor.Run(evm.StateDB, input, caller.Address(), new(big.Int), gas, true) + if evm.precompileHost.Exists(addr) { + ret, gas, err = evm.precompileHost.Run(evm.StateDB, input, caller.Address(), new(big.Int), gas, true) } else { // At this point, we use a copy of address. If we don't, the go compiler will // leak the 'contract' to the outer scope, and make allocation for 'contract' From bd7853d7744b229adc94227fbb6337e2dee51c67 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Wed, 18 Jan 2023 13:38:06 -0500 Subject: [PATCH 04/40] return precompiledContract and bool --- core/vm/evm.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index 5fabc9bde73b..4b9e65c6efd4 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -43,10 +43,10 @@ type ( // `PrecompileHost` is allows the EVM to execute a precompiled contract. type PrecompileHost interface { // `Exists` returns if a precompiled contract was found at `addr`. - Exists(addr common.Address) bool + Exists(addr common.Address) (PrecompiledContract, bool) // `Run` runs a precompiled contract and returns the leftover gas. - Run(sdb StateDB, input []byte, caller common.Address, + Run(p PrecompiledContract, sdb StateDB, input []byte, caller common.Address, value *big.Int, suppliedGas uint64, readonly bool, ) (ret []byte, remainingGas uint64, err error) } @@ -180,7 +180,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas return nil, gas, ErrInsufficientBalance } snapshot := evm.StateDB.Snapshot() - isPrecompile := evm.precompileHost.Exists(addr) + p, isPrecompile := evm.precompileHost.Exists(addr) if !evm.StateDB.Exist(addr) { if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 { @@ -217,7 +217,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas } if isPrecompile { - ret, gas, err = evm.precompileHost.Run(evm.StateDB, input, caller.Address(), value, gas, false) + ret, gas, err = evm.precompileHost.Run(p, evm.StateDB, input, caller.Address(), value, gas, false) } else { // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. @@ -279,8 +279,8 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, } // It is allowed to call precompiles, even via delegatecall - if evm.precompileHost.Exists(addr) { - ret, gas, err = evm.precompileHost.Run(evm.StateDB, input, caller.Address(), value, gas, true) + if p, isPrecompile := evm.precompileHost.Exists(addr); isPrecompile { + ret, gas, err = evm.precompileHost.Run(p, evm.StateDB, input, caller.Address(), value, gas, true) } else { addrCopy := addr // Initialise a new contract and set the code that is to be used by the EVM. @@ -324,9 +324,9 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by } // It is allowed to call precompiles, even via delegatecall - if evm.precompileHost.Exists(addr) { + if p, isPrecompile := evm.precompileHost.Exists(addr); isPrecompile { parent := caller.(*Contract) - ret, gas, err = evm.precompileHost.Run(evm.StateDB, input, parent.CallerAddress, parent.value, gas, false) + ret, gas, err = evm.precompileHost.Run(p, evm.StateDB, input, parent.CallerAddress, parent.value, gas, false) } else { addrCopy := addr // Initialise a new contract and make initialise the delegate values @@ -374,8 +374,8 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte }(gas) } - if evm.precompileHost.Exists(addr) { - ret, gas, err = evm.precompileHost.Run(evm.StateDB, input, caller.Address(), new(big.Int), gas, true) + if p, isPrecompile := evm.precompileHost.Exists(addr); isPrecompile { + ret, gas, err = evm.precompileHost.Run(p, evm.StateDB, input, caller.Address(), new(big.Int), gas, true) } else { // At this point, we use a copy of address. If we don't, the go compiler will // leak the 'contract' to the outer scope, and make allocation for 'contract' From 2e58beb5f2740efeac62479b97205ecd489d3bf1 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Wed, 18 Jan 2023 13:52:25 -0500 Subject: [PATCH 05/40] use ctx in Run instead of statedb --- core/vm/contracts.go | 47 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 83ecd1e20d56..f824ed0221ba 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -17,6 +17,7 @@ package vm import ( + "context" "crypto/sha256" "encoding/binary" "errors" @@ -37,8 +38,8 @@ import ( // requires a deterministic gas count based on the input size of the Run method of the // contract. type PrecompiledContract interface { - RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use - Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) // Run runs the precompiled contract + RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use + Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) // Run runs the precompiled contract } // PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum @@ -148,7 +149,7 @@ func (c *ecrecover) RequiredGas(input []byte) uint64 { return params.EcrecoverGas } -func (c *ecrecover) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *ecrecover) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { const ecRecoverInputLength = 128 input = common.RightPadBytes(input, ecRecoverInputLength) @@ -189,7 +190,7 @@ type sha256hash struct{} func (c *sha256hash) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas } -func (c *sha256hash) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *sha256hash) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { h := sha256.Sum256(input) return h[:], nil } @@ -204,7 +205,7 @@ type ripemd160hash struct{} func (c *ripemd160hash) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas } -func (c *ripemd160hash) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *ripemd160hash) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { ripemd := ripemd160.New() ripemd.Write(input) return common.LeftPadBytes(ripemd.Sum(nil), 32), nil @@ -220,7 +221,7 @@ type dataCopy struct{} func (c *dataCopy) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas } -func (c *dataCopy) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *dataCopy) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return input, nil } @@ -347,7 +348,7 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 { return gas.Uint64() } -func (c *bigModExp) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bigModExp) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { var ( baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64() expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64() @@ -427,7 +428,7 @@ func (c *bn256AddIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256AddGasIstanbul } -func (c *bn256AddIstanbul) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256AddIstanbul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Add(input) } @@ -440,7 +441,7 @@ func (c *bn256AddByzantium) RequiredGas(input []byte) uint64 { return params.Bn256AddGasByzantium } -func (c *bn256AddByzantium) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256AddByzantium) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Add(input) } @@ -465,7 +466,7 @@ func (c *bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256ScalarMulGasIstanbul } -func (c *bn256ScalarMulIstanbul) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256ScalarMulIstanbul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256ScalarMul(input) } @@ -478,7 +479,7 @@ func (c *bn256ScalarMulByzantium) RequiredGas(input []byte) uint64 { return params.Bn256ScalarMulGasByzantium } -func (c *bn256ScalarMulByzantium) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256ScalarMulByzantium) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256ScalarMul(input) } @@ -533,7 +534,7 @@ func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul } -func (c *bn256PairingIstanbul) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256PairingIstanbul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Pairing(input) } @@ -546,7 +547,7 @@ func (c *bn256PairingByzantium) RequiredGas(input []byte) uint64 { return params.Bn256PairingBaseGasByzantium + uint64(len(input)/192)*params.Bn256PairingPerPointGasByzantium } -func (c *bn256PairingByzantium) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256PairingByzantium) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Pairing(input) } @@ -572,7 +573,7 @@ var ( errBlake2FInvalidFinalFlag = errors.New("invalid final flag") ) -func (c *blake2F) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *blake2F) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Make sure the input is valid (correct length and final flag) if len(input) != blake2FInputLength { return nil, errBlake2FInvalidInputLength @@ -626,7 +627,7 @@ func (c *bls12381G1Add) RequiredGas(input []byte) uint64 { return params.Bls12381G1AddGas } -func (c *bls12381G1Add) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G1Add) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G1Add precompile. // > G1 addition call expects `256` bytes as an input that is interpreted as byte concatenation of two G1 points (`128` bytes each). // > Output is an encoding of addition operation result - single G1 point (`128` bytes). @@ -664,7 +665,7 @@ func (c *bls12381G1Mul) RequiredGas(input []byte) uint64 { return params.Bls12381G1MulGas } -func (c *bls12381G1Mul) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G1Mul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G1Mul precompile. // > G1 multiplication call expects `160` bytes as an input that is interpreted as byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). // > Output is an encoding of multiplication operation result - single G1 point (`128` bytes). @@ -714,7 +715,7 @@ func (c *bls12381G1MultiExp) RequiredGas(input []byte) uint64 { return (uint64(k) * params.Bls12381G1MulGas * discount) / 1000 } -func (c *bls12381G1MultiExp) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G1MultiExp) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G1MultiExp precompile. // G1 multiplication call expects `160*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). // Output is an encoding of multiexponentiation operation result - single G1 point (`128` bytes). @@ -757,7 +758,7 @@ func (c *bls12381G2Add) RequiredGas(input []byte) uint64 { return params.Bls12381G2AddGas } -func (c *bls12381G2Add) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G2Add) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G2Add precompile. // > G2 addition call expects `512` bytes as an input that is interpreted as byte concatenation of two G2 points (`256` bytes each). // > Output is an encoding of addition operation result - single G2 point (`256` bytes). @@ -795,7 +796,7 @@ func (c *bls12381G2Mul) RequiredGas(input []byte) uint64 { return params.Bls12381G2MulGas } -func (c *bls12381G2Mul) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G2Mul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G2MUL precompile logic. // > G2 multiplication call expects `288` bytes as an input that is interpreted as byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). // > Output is an encoding of multiplication operation result - single G2 point (`256` bytes). @@ -845,7 +846,7 @@ func (c *bls12381G2MultiExp) RequiredGas(input []byte) uint64 { return (uint64(k) * params.Bls12381G2MulGas * discount) / 1000 } -func (c *bls12381G2MultiExp) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G2MultiExp) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G2MultiExp precompile logic // > G2 multiplication call expects `288*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). // > Output is an encoding of multiexponentiation operation result - single G2 point (`256` bytes). @@ -888,7 +889,7 @@ func (c *bls12381Pairing) RequiredGas(input []byte) uint64 { return params.Bls12381PairingBaseGas + uint64(len(input)/384)*params.Bls12381PairingPerPairGas } -func (c *bls12381Pairing) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381Pairing) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 Pairing precompile logic. // > Pairing call expects `384*k` bytes as an inputs that is interpreted as byte concatenation of `k` slices. Each slice has the following structure: // > - `128` bytes of G1 point encoding @@ -967,7 +968,7 @@ func (c *bls12381MapG1) RequiredGas(input []byte) uint64 { return params.Bls12381MapG1Gas } -func (c *bls12381MapG1) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381MapG1) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 Map_To_G1 precompile. // > Field-to-curve call expects `64` bytes an an input that is interpreted as a an element of the base field. // > Output of this call is `128` bytes and is G1 point following respective encoding rules. @@ -1002,7 +1003,7 @@ func (c *bls12381MapG2) RequiredGas(input []byte) uint64 { return params.Bls12381MapG2Gas } -func (c *bls12381MapG2) Run(sdb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381MapG2) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 Map_FP2_TO_G2 precompile logic. // > Field-to-curve call expects `128` bytes an an input that is interpreted as a an element of the quadratic extension field. // > Output of this call is `256` bytes and is G2 point following respective encoding rules. From 23abedc6783f81f97c028ee842ab98e61d4aca1a Mon Sep 17 00:00:00 2001 From: Devon Bear Date: Thu, 19 Jan 2023 13:45:13 -0500 Subject: [PATCH 06/40] change to ph --- accounts/abi/bind/bind.go | 2 +- core/vm/evm.go | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/accounts/abi/bind/bind.go b/accounts/abi/bind/bind.go index 05cca8e90b3a..c179dbcc925f 100644 --- a/accounts/abi/bind/bind.go +++ b/accounts/abi/bind/bind.go @@ -187,7 +187,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string] } eventIdentifiers[normalizedName] = true normalized.Name = normalizedName - + used := make(map[string]bool) normalized.Inputs = make([]abi.Argument, len(original.Inputs)) copy(normalized.Inputs, original.Inputs) diff --git a/core/vm/evm.go b/core/vm/evm.go index 4b9e65c6efd4..3c04de970d6d 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -46,7 +46,7 @@ type PrecompileHost interface { Exists(addr common.Address) (PrecompiledContract, bool) // `Run` runs a precompiled contract and returns the leftover gas. - Run(p PrecompiledContract, sdb StateDB, input []byte, caller common.Address, + Run(p PrecompiledContract, input []byte, caller common.Address, value *big.Int, suppliedGas uint64, readonly bool, ) (ret []byte, remainingGas uint64, err error) } @@ -217,7 +217,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas } if isPrecompile { - ret, gas, err = evm.precompileHost.Run(p, evm.StateDB, input, caller.Address(), value, gas, false) + ret, gas, err = evm.precompileHost.Run(p, input, caller.Address(), value, gas, false) } else { // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. @@ -280,7 +280,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, // It is allowed to call precompiles, even via delegatecall if p, isPrecompile := evm.precompileHost.Exists(addr); isPrecompile { - ret, gas, err = evm.precompileHost.Run(p, evm.StateDB, input, caller.Address(), value, gas, true) + ret, gas, err = evm.precompileHost.Run(p, input, caller.Address(), value, gas, true) } else { addrCopy := addr // Initialise a new contract and set the code that is to be used by the EVM. @@ -326,7 +326,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by // It is allowed to call precompiles, even via delegatecall if p, isPrecompile := evm.precompileHost.Exists(addr); isPrecompile { parent := caller.(*Contract) - ret, gas, err = evm.precompileHost.Run(p, evm.StateDB, input, parent.CallerAddress, parent.value, gas, false) + ret, gas, err = evm.precompileHost.Run(p, input, parent.CallerAddress, parent.value, gas, false) } else { addrCopy := addr // Initialise a new contract and make initialise the delegate values @@ -375,7 +375,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte } if p, isPrecompile := evm.precompileHost.Exists(addr); isPrecompile { - ret, gas, err = evm.precompileHost.Run(p, evm.StateDB, input, caller.Address(), new(big.Int), gas, true) + ret, gas, err = evm.precompileHost.Run(p, input, caller.Address(), new(big.Int), gas, true) } else { // At this point, we use a copy of address. If we don't, the go compiler will // leak the 'contract' to the outer scope, and make allocation for 'contract' From 252a80701f7ca1ab2e3476726c9ed4d7ca3fd24b Mon Sep 17 00:00:00 2001 From: Devon Bear Date: Thu, 19 Jan 2023 18:35:22 -0500 Subject: [PATCH 07/40] bing bong --- core/vm/evm.go | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index 3c04de970d6d..5da4ba06b3ac 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -121,20 +121,25 @@ type EVM struct { // NewEVM returns a new EVM. The returned EVM is not thread safe and should // only ever be used *once*. -func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config, precompileHost PrecompileHost) *EVM { +func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config) *EVM { evm := &EVM{ - Context: blockCtx, - TxContext: txCtx, - StateDB: statedb, - precompileHost: precompileHost, - Config: config, - chainConfig: chainConfig, - chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil), + Context: blockCtx, + TxContext: txCtx, + StateDB: statedb, + Config: config, + chainConfig: chainConfig, + chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil), } evm.interpreter = NewEVMInterpreter(evm) return evm } +func NewEVMWithPrecompileHost(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config, precompileHost PrecompileHost) *EVM { + evm := NewEVM(blockCtx, txCtx, statedb, chainConfig, config) + evm.precompileHost = precompileHost + return evm +} + // Reset resets the EVM with a new transaction context.Reset // This is not threadsafe and should only be done very cautiously. func (evm *EVM) Reset(txCtx TxContext, statedb StateDB) { From d024addab5f7e386f7ffdf80130bea7324b2db1c Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Mon, 23 Jan 2023 14:43:24 -0500 Subject: [PATCH 08/40] rename to runner --- core/vm/evm.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index 5da4ba06b3ac..1b61f3296b64 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -40,8 +40,8 @@ type ( GetHashFunc func(uint64) common.Hash ) -// `PrecompileHost` is allows the EVM to execute a precompiled contract. -type PrecompileHost interface { +// `PrecompileRunner` is allows the EVM to execute a precompiled contract. +type PrecompileRunner interface { // `Exists` returns if a precompiled contract was found at `addr`. Exists(addr common.Address) (PrecompiledContract, bool) @@ -95,8 +95,8 @@ type EVM struct { TxContext // StateDB gives access to the underlying state StateDB StateDB - // precompileHost gives access to the precompiled contracts - precompileHost PrecompileHost + // precompileRunner gives access to the precompiled contracts + precompileRunner PrecompileRunner // Depth is the current call stack depth int @@ -134,9 +134,9 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig return evm } -func NewEVMWithPrecompileHost(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config, precompileHost PrecompileHost) *EVM { +func NewEVMWithPrecompileHost(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config, precompileRunner PrecompileRunner) *EVM { evm := NewEVM(blockCtx, txCtx, statedb, chainConfig, config) - evm.precompileHost = precompileHost + evm.precompileRunner = precompileRunner return evm } @@ -185,7 +185,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas return nil, gas, ErrInsufficientBalance } snapshot := evm.StateDB.Snapshot() - p, isPrecompile := evm.precompileHost.Exists(addr) + p, isPrecompile := evm.precompileRunner.Exists(addr) if !evm.StateDB.Exist(addr) { if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 { @@ -222,7 +222,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas } if isPrecompile { - ret, gas, err = evm.precompileHost.Run(p, input, caller.Address(), value, gas, false) + ret, gas, err = evm.precompileRunner.Run(p, input, caller.Address(), value, gas, false) } else { // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. @@ -284,8 +284,8 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, } // It is allowed to call precompiles, even via delegatecall - if p, isPrecompile := evm.precompileHost.Exists(addr); isPrecompile { - ret, gas, err = evm.precompileHost.Run(p, input, caller.Address(), value, gas, true) + if p, isPrecompile := evm.precompileRunner.Exists(addr); isPrecompile { + ret, gas, err = evm.precompileRunner.Run(p, input, caller.Address(), value, gas, true) } else { addrCopy := addr // Initialise a new contract and set the code that is to be used by the EVM. @@ -329,9 +329,9 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by } // It is allowed to call precompiles, even via delegatecall - if p, isPrecompile := evm.precompileHost.Exists(addr); isPrecompile { + if p, isPrecompile := evm.precompileRunner.Exists(addr); isPrecompile { parent := caller.(*Contract) - ret, gas, err = evm.precompileHost.Run(p, input, parent.CallerAddress, parent.value, gas, false) + ret, gas, err = evm.precompileRunner.Run(p, input, parent.CallerAddress, parent.value, gas, false) } else { addrCopy := addr // Initialise a new contract and make initialise the delegate values @@ -379,8 +379,8 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte }(gas) } - if p, isPrecompile := evm.precompileHost.Exists(addr); isPrecompile { - ret, gas, err = evm.precompileHost.Run(p, input, caller.Address(), new(big.Int), gas, true) + if p, isPrecompile := evm.precompileRunner.Exists(addr); isPrecompile { + ret, gas, err = evm.precompileRunner.Run(p, input, caller.Address(), new(big.Int), gas, true) } else { // At this point, we use a copy of address. If we don't, the go compiler will // leak the 'contract' to the outer scope, and make allocation for 'contract' From e181e29223fa6ee6c104d103e8481240c47b2df9 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Mon, 23 Jan 2023 14:52:37 -0500 Subject: [PATCH 09/40] rename constructor --- core/vm/evm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index 1b61f3296b64..9be17b6bb4c9 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -134,7 +134,7 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig return evm } -func NewEVMWithPrecompileHost(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config, precompileRunner PrecompileRunner) *EVM { +func NewEVMWithPrecompiles(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config, precompileRunner PrecompileRunner) *EVM { evm := NewEVM(blockCtx, txCtx, statedb, chainConfig, config) evm.precompileRunner = precompileRunner return evm From b68f40663ef1b38248ee80c85f530324c3129a44 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Tue, 24 Jan 2023 12:54:21 -0500 Subject: [PATCH 10/40] new precompile function types --- core/vm/evm.go | 49 +++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index 9be17b6bb4c9..88ec97acac59 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -40,16 +40,14 @@ type ( GetHashFunc func(uint64) common.Hash ) -// `PrecompileRunner` is allows the EVM to execute a precompiled contract. -type PrecompileRunner interface { - // `Exists` returns if a precompiled contract was found at `addr`. - Exists(addr common.Address) (PrecompiledContract, bool) - - // `Run` runs a precompiled contract and returns the leftover gas. - Run(p PrecompiledContract, input []byte, caller common.Address, - value *big.Int, suppliedGas uint64, readonly bool, - ) (ret []byte, remainingGas uint64, err error) -} +// `PrecompileExists` returns if a precompiled contract was found at `addr`. +type PrecompileExists func(addr common.Address) (p PrecompiledContract, found bool) + +// `RunPrecompile` runs a precompiled contract and returns the remaining gas. +type RunPrecompile func( + p PrecompiledContract, input []byte, caller common.Address, + value *big.Int, suppliedGas uint64, readonly bool, +) (ret []byte, remainingGas uint64, err error) // BlockContext provides the EVM with auxiliary information. Once provided // it shouldn't be modified. @@ -95,8 +93,11 @@ type EVM struct { TxContext // StateDB gives access to the underlying state StateDB StateDB - // precompileRunner gives access to the precompiled contracts - precompileRunner PrecompileRunner + // precompileExists searches an address for a precompiled + // contract + precompileExists PrecompileExists + // runPrecompile gives access running a precompiled contract + runPrecompile RunPrecompile // Depth is the current call stack depth int @@ -134,9 +135,13 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig return evm } -func NewEVMWithPrecompiles(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, config Config, precompileRunner PrecompileRunner) *EVM { +func NewEVMWithPrecompiles( + blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, + config Config, precompileExists PrecompileExists, runPrecompile RunPrecompile, +) *EVM { evm := NewEVM(blockCtx, txCtx, statedb, chainConfig, config) - evm.precompileRunner = precompileRunner + evm.precompileExists = precompileExists + evm.runPrecompile = runPrecompile return evm } @@ -185,7 +190,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas return nil, gas, ErrInsufficientBalance } snapshot := evm.StateDB.Snapshot() - p, isPrecompile := evm.precompileRunner.Exists(addr) + p, isPrecompile := evm.precompileExists(addr) if !evm.StateDB.Exist(addr) { if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 { @@ -222,7 +227,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas } if isPrecompile { - ret, gas, err = evm.precompileRunner.Run(p, input, caller.Address(), value, gas, false) + ret, gas, err = evm.runPrecompile(p, input, caller.Address(), value, gas, false) } else { // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. @@ -284,8 +289,8 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, } // It is allowed to call precompiles, even via delegatecall - if p, isPrecompile := evm.precompileRunner.Exists(addr); isPrecompile { - ret, gas, err = evm.precompileRunner.Run(p, input, caller.Address(), value, gas, true) + if p, isPrecompile := evm.precompileExists(addr); isPrecompile { + ret, gas, err = evm.runPrecompile(p, input, caller.Address(), value, gas, true) } else { addrCopy := addr // Initialise a new contract and set the code that is to be used by the EVM. @@ -329,9 +334,9 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by } // It is allowed to call precompiles, even via delegatecall - if p, isPrecompile := evm.precompileRunner.Exists(addr); isPrecompile { + if p, isPrecompile := evm.precompileExists(addr); isPrecompile { parent := caller.(*Contract) - ret, gas, err = evm.precompileRunner.Run(p, input, parent.CallerAddress, parent.value, gas, false) + ret, gas, err = evm.runPrecompile(p, input, parent.CallerAddress, parent.value, gas, false) } else { addrCopy := addr // Initialise a new contract and make initialise the delegate values @@ -379,8 +384,8 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte }(gas) } - if p, isPrecompile := evm.precompileRunner.Exists(addr); isPrecompile { - ret, gas, err = evm.precompileRunner.Run(p, input, caller.Address(), new(big.Int), gas, true) + if p, isPrecompile := evm.precompileExists(addr); isPrecompile { + ret, gas, err = evm.runPrecompile(p, input, caller.Address(), new(big.Int), gas, true) } else { // At this point, we use a copy of address. If we don't, the go compiler will // leak the 'contract' to the outer scope, and make allocation for 'contract' From 6738bc9fbcf684a20c6361330a28d9f159132f99 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Tue, 24 Jan 2023 14:46:22 -0500 Subject: [PATCH 11/40] precompile controller --- core/vm/evm.go | 48 +++++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index 88ec97acac59..8c044e3832d5 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -40,14 +40,16 @@ type ( GetHashFunc func(uint64) common.Hash ) -// `PrecompileExists` returns if a precompiled contract was found at `addr`. -type PrecompileExists func(addr common.Address) (p PrecompiledContract, found bool) - -// `RunPrecompile` runs a precompiled contract and returns the remaining gas. -type RunPrecompile func( - p PrecompiledContract, input []byte, caller common.Address, - value *big.Int, suppliedGas uint64, readonly bool, -) (ret []byte, remainingGas uint64, err error) +// `PrecompileController` allows the EVM to execute a precompiled contract. +type PrecompileController interface { + // `Exists` returns if a precompiled contract was found at `addr`. + Exists(addr common.Address) (p PrecompiledContract, found bool) + + // `Run` runs a precompiled contract and returns the remaining gas. + Run(p PrecompiledContract, input []byte, caller common.Address, + value *big.Int, suppliedGas uint64, readonly bool, + ) (ret []byte, remainingGas uint64, err error) +} // BlockContext provides the EVM with auxiliary information. Once provided // it shouldn't be modified. @@ -93,11 +95,8 @@ type EVM struct { TxContext // StateDB gives access to the underlying state StateDB StateDB - // precompileExists searches an address for a precompiled - // contract - precompileExists PrecompileExists - // runPrecompile gives access running a precompiled contract - runPrecompile RunPrecompile + // precompileController finds and runs precompiled contracts + precompileController PrecompileController // Depth is the current call stack depth int @@ -136,12 +135,11 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig } func NewEVMWithPrecompiles( - blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig *params.ChainConfig, - config Config, precompileExists PrecompileExists, runPrecompile RunPrecompile, + blockCtx BlockContext, txCtx TxContext, statedb StateDB, + chainConfig *params.ChainConfig, config Config, precompileController PrecompileController, ) *EVM { evm := NewEVM(blockCtx, txCtx, statedb, chainConfig, config) - evm.precompileExists = precompileExists - evm.runPrecompile = runPrecompile + evm.precompileController = precompileController return evm } @@ -190,7 +188,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas return nil, gas, ErrInsufficientBalance } snapshot := evm.StateDB.Snapshot() - p, isPrecompile := evm.precompileExists(addr) + p, isPrecompile := evm.precompileController.Exists(addr) if !evm.StateDB.Exist(addr) { if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 { @@ -227,7 +225,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas } if isPrecompile { - ret, gas, err = evm.runPrecompile(p, input, caller.Address(), value, gas, false) + ret, gas, err = evm.precompileController.Run(p, input, caller.Address(), value, gas, false) } else { // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. @@ -289,8 +287,8 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, } // It is allowed to call precompiles, even via delegatecall - if p, isPrecompile := evm.precompileExists(addr); isPrecompile { - ret, gas, err = evm.runPrecompile(p, input, caller.Address(), value, gas, true) + if p, isPrecompile := evm.precompileController.Exists(addr); isPrecompile { + ret, gas, err = evm.precompileController.Run(p, input, caller.Address(), value, gas, true) } else { addrCopy := addr // Initialise a new contract and set the code that is to be used by the EVM. @@ -334,9 +332,9 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by } // It is allowed to call precompiles, even via delegatecall - if p, isPrecompile := evm.precompileExists(addr); isPrecompile { + if p, isPrecompile := evm.precompileController.Exists(addr); isPrecompile { parent := caller.(*Contract) - ret, gas, err = evm.runPrecompile(p, input, parent.CallerAddress, parent.value, gas, false) + ret, gas, err = evm.precompileController.Run(p, input, parent.CallerAddress, parent.value, gas, false) } else { addrCopy := addr // Initialise a new contract and make initialise the delegate values @@ -384,8 +382,8 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte }(gas) } - if p, isPrecompile := evm.precompileExists(addr); isPrecompile { - ret, gas, err = evm.runPrecompile(p, input, caller.Address(), new(big.Int), gas, true) + if p, isPrecompile := evm.precompileController.Exists(addr); isPrecompile { + ret, gas, err = evm.precompileController.Run(p, input, caller.Address(), new(big.Int), gas, true) } else { // At this point, we use a copy of address. If we don't, the go compiler will // leak the 'contract' to the outer scope, and make allocation for 'contract' From c1877f5821eb73c89ba035963dd3ca6cadc541ff Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Wed, 25 Jan 2023 13:43:24 -0500 Subject: [PATCH 12/40] make PrecompileController public --- core/vm/evm.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index 8c044e3832d5..874c0295b683 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -95,8 +95,8 @@ type EVM struct { TxContext // StateDB gives access to the underlying state StateDB StateDB - // precompileController finds and runs precompiled contracts - precompileController PrecompileController + // PrecompileController finds and runs precompiled contracts + PrecompileController PrecompileController // Depth is the current call stack depth int @@ -139,7 +139,7 @@ func NewEVMWithPrecompiles( chainConfig *params.ChainConfig, config Config, precompileController PrecompileController, ) *EVM { evm := NewEVM(blockCtx, txCtx, statedb, chainConfig, config) - evm.precompileController = precompileController + evm.PrecompileController = precompileController return evm } @@ -188,7 +188,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas return nil, gas, ErrInsufficientBalance } snapshot := evm.StateDB.Snapshot() - p, isPrecompile := evm.precompileController.Exists(addr) + p, isPrecompile := evm.PrecompileController.Exists(addr) if !evm.StateDB.Exist(addr) { if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 { @@ -225,7 +225,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas } if isPrecompile { - ret, gas, err = evm.precompileController.Run(p, input, caller.Address(), value, gas, false) + ret, gas, err = evm.PrecompileController.Run(p, input, caller.Address(), value, gas, false) } else { // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. @@ -287,8 +287,8 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, } // It is allowed to call precompiles, even via delegatecall - if p, isPrecompile := evm.precompileController.Exists(addr); isPrecompile { - ret, gas, err = evm.precompileController.Run(p, input, caller.Address(), value, gas, true) + if p, isPrecompile := evm.PrecompileController.Exists(addr); isPrecompile { + ret, gas, err = evm.PrecompileController.Run(p, input, caller.Address(), value, gas, true) } else { addrCopy := addr // Initialise a new contract and set the code that is to be used by the EVM. @@ -332,9 +332,9 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by } // It is allowed to call precompiles, even via delegatecall - if p, isPrecompile := evm.precompileController.Exists(addr); isPrecompile { + if p, isPrecompile := evm.PrecompileController.Exists(addr); isPrecompile { parent := caller.(*Contract) - ret, gas, err = evm.precompileController.Run(p, input, parent.CallerAddress, parent.value, gas, false) + ret, gas, err = evm.PrecompileController.Run(p, input, parent.CallerAddress, parent.value, gas, false) } else { addrCopy := addr // Initialise a new contract and make initialise the delegate values @@ -382,8 +382,8 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte }(gas) } - if p, isPrecompile := evm.precompileController.Exists(addr); isPrecompile { - ret, gas, err = evm.precompileController.Run(p, input, caller.Address(), new(big.Int), gas, true) + if p, isPrecompile := evm.PrecompileController.Exists(addr); isPrecompile { + ret, gas, err = evm.PrecompileController.Run(p, input, caller.Address(), new(big.Int), gas, true) } else { // At this point, we use a copy of address. If we don't, the go compiler will // leak the 'contract' to the outer scope, and make allocation for 'contract' From e677eab1a94465b4e1cae186983b1f20aa6edde1 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Wed, 25 Jan 2023 14:17:25 -0500 Subject: [PATCH 13/40] ctx setter --- core/vm/evm.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/vm/evm.go b/core/vm/evm.go index 874c0295b683..9eac860e5aa0 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -17,6 +17,7 @@ package vm import ( + "context" "math/big" "sync/atomic" @@ -42,6 +43,9 @@ type ( // `PrecompileController` allows the EVM to execute a precompiled contract. type PrecompileController interface { + // `SetEphemeralContext` sets the precompile's native environment context. + SetEphemeralContext(ctx context.Context) + // `Exists` returns if a precompiled contract was found at `addr`. Exists(addr common.Address) (p PrecompiledContract, found bool) From 4500de4c02991130c8b607bba64bf0f2802fa02a Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Wed, 25 Jan 2023 14:28:01 -0500 Subject: [PATCH 14/40] add statedb in contract.Run --- core/vm/contracts.go | 46 ++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/core/vm/contracts.go b/core/vm/contracts.go index f824ed0221ba..b7fbacf34203 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -38,8 +38,8 @@ import ( // requires a deterministic gas count based on the input size of the Run method of the // contract. type PrecompiledContract interface { - RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use - Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) // Run runs the precompiled contract + RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use + Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) // Run runs the precompiled contract } // PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum @@ -149,7 +149,7 @@ func (c *ecrecover) RequiredGas(input []byte) uint64 { return params.EcrecoverGas } -func (c *ecrecover) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *ecrecover) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { const ecRecoverInputLength = 128 input = common.RightPadBytes(input, ecRecoverInputLength) @@ -190,7 +190,7 @@ type sha256hash struct{} func (c *sha256hash) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas } -func (c *sha256hash) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *sha256hash) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { h := sha256.Sum256(input) return h[:], nil } @@ -205,7 +205,7 @@ type ripemd160hash struct{} func (c *ripemd160hash) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas } -func (c *ripemd160hash) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *ripemd160hash) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { ripemd := ripemd160.New() ripemd.Write(input) return common.LeftPadBytes(ripemd.Sum(nil), 32), nil @@ -221,7 +221,7 @@ type dataCopy struct{} func (c *dataCopy) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas } -func (c *dataCopy) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *dataCopy) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return input, nil } @@ -348,7 +348,7 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 { return gas.Uint64() } -func (c *bigModExp) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bigModExp) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { var ( baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64() expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64() @@ -428,7 +428,7 @@ func (c *bn256AddIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256AddGasIstanbul } -func (c *bn256AddIstanbul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256AddIstanbul) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Add(input) } @@ -441,7 +441,7 @@ func (c *bn256AddByzantium) RequiredGas(input []byte) uint64 { return params.Bn256AddGasByzantium } -func (c *bn256AddByzantium) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256AddByzantium) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Add(input) } @@ -466,7 +466,7 @@ func (c *bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256ScalarMulGasIstanbul } -func (c *bn256ScalarMulIstanbul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256ScalarMulIstanbul) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256ScalarMul(input) } @@ -479,7 +479,7 @@ func (c *bn256ScalarMulByzantium) RequiredGas(input []byte) uint64 { return params.Bn256ScalarMulGasByzantium } -func (c *bn256ScalarMulByzantium) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256ScalarMulByzantium) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256ScalarMul(input) } @@ -534,7 +534,7 @@ func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul } -func (c *bn256PairingIstanbul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256PairingIstanbul) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Pairing(input) } @@ -547,7 +547,7 @@ func (c *bn256PairingByzantium) RequiredGas(input []byte) uint64 { return params.Bn256PairingBaseGasByzantium + uint64(len(input)/192)*params.Bn256PairingPerPointGasByzantium } -func (c *bn256PairingByzantium) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256PairingByzantium) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Pairing(input) } @@ -573,7 +573,7 @@ var ( errBlake2FInvalidFinalFlag = errors.New("invalid final flag") ) -func (c *blake2F) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *blake2F) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Make sure the input is valid (correct length and final flag) if len(input) != blake2FInputLength { return nil, errBlake2FInvalidInputLength @@ -627,7 +627,7 @@ func (c *bls12381G1Add) RequiredGas(input []byte) uint64 { return params.Bls12381G1AddGas } -func (c *bls12381G1Add) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G1Add) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G1Add precompile. // > G1 addition call expects `256` bytes as an input that is interpreted as byte concatenation of two G1 points (`128` bytes each). // > Output is an encoding of addition operation result - single G1 point (`128` bytes). @@ -665,7 +665,7 @@ func (c *bls12381G1Mul) RequiredGas(input []byte) uint64 { return params.Bls12381G1MulGas } -func (c *bls12381G1Mul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G1Mul) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G1Mul precompile. // > G1 multiplication call expects `160` bytes as an input that is interpreted as byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). // > Output is an encoding of multiplication operation result - single G1 point (`128` bytes). @@ -715,7 +715,7 @@ func (c *bls12381G1MultiExp) RequiredGas(input []byte) uint64 { return (uint64(k) * params.Bls12381G1MulGas * discount) / 1000 } -func (c *bls12381G1MultiExp) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G1MultiExp) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G1MultiExp precompile. // G1 multiplication call expects `160*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). // Output is an encoding of multiexponentiation operation result - single G1 point (`128` bytes). @@ -758,7 +758,7 @@ func (c *bls12381G2Add) RequiredGas(input []byte) uint64 { return params.Bls12381G2AddGas } -func (c *bls12381G2Add) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G2Add) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G2Add precompile. // > G2 addition call expects `512` bytes as an input that is interpreted as byte concatenation of two G2 points (`256` bytes each). // > Output is an encoding of addition operation result - single G2 point (`256` bytes). @@ -796,7 +796,7 @@ func (c *bls12381G2Mul) RequiredGas(input []byte) uint64 { return params.Bls12381G2MulGas } -func (c *bls12381G2Mul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G2Mul) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G2MUL precompile logic. // > G2 multiplication call expects `288` bytes as an input that is interpreted as byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). // > Output is an encoding of multiplication operation result - single G2 point (`256` bytes). @@ -846,7 +846,7 @@ func (c *bls12381G2MultiExp) RequiredGas(input []byte) uint64 { return (uint64(k) * params.Bls12381G2MulGas * discount) / 1000 } -func (c *bls12381G2MultiExp) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G2MultiExp) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G2MultiExp precompile logic // > G2 multiplication call expects `288*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). // > Output is an encoding of multiexponentiation operation result - single G2 point (`256` bytes). @@ -889,7 +889,7 @@ func (c *bls12381Pairing) RequiredGas(input []byte) uint64 { return params.Bls12381PairingBaseGas + uint64(len(input)/384)*params.Bls12381PairingPerPairGas } -func (c *bls12381Pairing) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381Pairing) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 Pairing precompile logic. // > Pairing call expects `384*k` bytes as an inputs that is interpreted as byte concatenation of `k` slices. Each slice has the following structure: // > - `128` bytes of G1 point encoding @@ -968,7 +968,7 @@ func (c *bls12381MapG1) RequiredGas(input []byte) uint64 { return params.Bls12381MapG1Gas } -func (c *bls12381MapG1) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381MapG1) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 Map_To_G1 precompile. // > Field-to-curve call expects `64` bytes an an input that is interpreted as a an element of the base field. // > Output of this call is `128` bytes and is G1 point following respective encoding rules. @@ -1003,7 +1003,7 @@ func (c *bls12381MapG2) RequiredGas(input []byte) uint64 { return params.Bls12381MapG2Gas } -func (c *bls12381MapG2) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381MapG2) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 Map_FP2_TO_G2 precompile logic. // > Field-to-curve call expects `128` bytes an an input that is interpreted as a an element of the quadratic extension field. // > Output of this call is `256` bytes and is G2 point following respective encoding rules. From 52ba78336d8abaf6180683a25239692cd7b3911b Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Wed, 25 Jan 2023 15:05:38 -0500 Subject: [PATCH 15/40] use Prepare on controller --- core/vm/evm.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index 9eac860e5aa0..7443abfa1c03 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -43,8 +43,8 @@ type ( // `PrecompileController` allows the EVM to execute a precompiled contract. type PrecompileController interface { - // `SetEphemeralContext` sets the precompile's native environment context. - SetEphemeralContext(ctx context.Context) + // `Prepare` sets the precompile's native environment context and stateDB. + Prepare(ctx context.Context, statedb StateDB) // `Exists` returns if a precompiled contract was found at `addr`. Exists(addr common.Address) (p PrecompiledContract, found bool) From 1a7ad275b12a5451cd2201d3a985a29d8113ff79 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Wed, 25 Jan 2023 17:07:28 -0500 Subject: [PATCH 16/40] prepare for state transition --- core/vm/evm.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index 7443abfa1c03..6851c9eaa14d 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -17,7 +17,6 @@ package vm import ( - "context" "math/big" "sync/atomic" @@ -43,8 +42,9 @@ type ( // `PrecompileController` allows the EVM to execute a precompiled contract. type PrecompileController interface { - // `Prepare` sets the precompile's native environment context and stateDB. - Prepare(ctx context.Context, statedb StateDB) + // `PrepareForStateTransition` holds the precompile native statedb + // before beginning a state transition. + PrepareForStateTransition(statedb StateDB) error // `Exists` returns if a precompiled contract was found at `addr`. Exists(addr common.Address) (p PrecompiledContract, found bool) From c40db52d950080c5743e2e874c595562bc98a6ba Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Thu, 2 Feb 2023 11:08:39 -0500 Subject: [PATCH 17/40] contract has registry key --- core/vm/contracts.go | 85 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/core/vm/contracts.go b/core/vm/contracts.go index b7fbacf34203..4096563b1107 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -38,6 +38,7 @@ import ( // requires a deterministic gas count based on the input size of the Run method of the // contract. type PrecompiledContract interface { + RegistryKey() common.Address RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) // Run runs the precompiled contract } @@ -145,6 +146,10 @@ func ActivePrecompiles(rules params.Rules) []common.Address { // ECRECOVER implemented as a native contract. type ecrecover struct{} +func (c *ecrecover) RegistryKey() common.Address { + return common.BytesToAddress([]byte{1}) +} + func (c *ecrecover) RequiredGas(input []byte) uint64 { return params.EcrecoverGas } @@ -183,6 +188,10 @@ func (c *ecrecover) Run(ctx context.Context, statedb StateDB, input []byte, call // SHA256 implemented as a native contract. type sha256hash struct{} +func (c *sha256hash) RegistryKey() common.Address { + return common.BytesToAddress([]byte{2}) +} + // RequiredGas returns the gas required to execute the pre-compiled contract. // // This method does not require any overflow checking as the input size gas costs @@ -198,6 +207,10 @@ func (c *sha256hash) Run(ctx context.Context, statedb StateDB, input []byte, cal // RIPEMD160 implemented as a native contract. type ripemd160hash struct{} +func (c *ripemd160hash) RegistryKey() common.Address { + return common.BytesToAddress([]byte{3}) +} + // RequiredGas returns the gas required to execute the pre-compiled contract. // // This method does not require any overflow checking as the input size gas costs @@ -214,6 +227,10 @@ func (c *ripemd160hash) Run(ctx context.Context, statedb StateDB, input []byte, // data copy implemented as a native contract. type dataCopy struct{} +func (c *dataCopy) RegistryKey() common.Address { + return common.BytesToAddress([]byte{4}) +} + // RequiredGas returns the gas required to execute the pre-compiled contract. // // This method does not require any overflow checking as the input size gas costs @@ -230,6 +247,10 @@ type bigModExp struct { eip2565 bool } +func (c *bigModExp) RegistryKey() common.Address { + return common.BytesToAddress([]byte{5}) +} + var ( big0 = big.NewInt(0) big1 = big.NewInt(1) @@ -423,6 +444,10 @@ func runBn256Add(input []byte) ([]byte, error) { // Istanbul consensus rules. type bn256AddIstanbul struct{} +func (c *bn256AddIstanbul) RegistryKey() common.Address { + return common.BytesToAddress([]byte{6}) +} + // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bn256AddIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256AddGasIstanbul @@ -436,6 +461,10 @@ func (c *bn256AddIstanbul) Run(ctx context.Context, statedb StateDB, input []byt // conforming to Byzantium consensus rules. type bn256AddByzantium struct{} +func (c *bn256AddByzantium) RegistryKey() common.Address { + return common.BytesToAddress([]byte{6}) +} + // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bn256AddByzantium) RequiredGas(input []byte) uint64 { return params.Bn256AddGasByzantium @@ -461,6 +490,10 @@ func runBn256ScalarMul(input []byte) ([]byte, error) { // multiplication conforming to Istanbul consensus rules. type bn256ScalarMulIstanbul struct{} +func (c *bn256ScalarMulIstanbul) RegistryKey() common.Address { + return common.BytesToAddress([]byte{7}) +} + // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256ScalarMulGasIstanbul @@ -474,6 +507,10 @@ func (c *bn256ScalarMulIstanbul) Run(ctx context.Context, statedb StateDB, input // multiplication conforming to Byzantium consensus rules. type bn256ScalarMulByzantium struct{} +func (c *bn256ScalarMulByzantium) RegistryKey() common.Address { + return common.BytesToAddress([]byte{7}) +} + // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bn256ScalarMulByzantium) RequiredGas(input []byte) uint64 { return params.Bn256ScalarMulGasByzantium @@ -529,6 +566,10 @@ func runBn256Pairing(input []byte) ([]byte, error) { // conforming to Istanbul consensus rules. type bn256PairingIstanbul struct{} +func (c *bn256PairingIstanbul) RegistryKey() common.Address { + return common.BytesToAddress([]byte{8}) +} + // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul @@ -542,6 +583,10 @@ func (c *bn256PairingIstanbul) Run(ctx context.Context, statedb StateDB, input [ // conforming to Byzantium consensus rules. type bn256PairingByzantium struct{} +func (c *bn256PairingByzantium) RegistryKey() common.Address { + return common.BytesToAddress([]byte{8}) +} + // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bn256PairingByzantium) RequiredGas(input []byte) uint64 { return params.Bn256PairingBaseGasByzantium + uint64(len(input)/192)*params.Bn256PairingPerPointGasByzantium @@ -553,6 +598,10 @@ func (c *bn256PairingByzantium) Run(ctx context.Context, statedb StateDB, input type blake2F struct{} +func (c *blake2F) RegistryKey() common.Address { + return common.BytesToAddress([]byte{9}) +} + func (c *blake2F) RequiredGas(input []byte) uint64 { // If the input is malformed, we can't calculate the gas, return 0 and let the // actual call choke and fault. @@ -622,6 +671,10 @@ var ( // bls12381G1Add implements EIP-2537 G1Add precompile. type bls12381G1Add struct{} +func (c *bls12381G1Add) RegistryKey() common.Address { + return common.BytesToAddress([]byte{10}) +} + // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bls12381G1Add) RequiredGas(input []byte) uint64 { return params.Bls12381G1AddGas @@ -660,6 +713,10 @@ func (c *bls12381G1Add) Run(ctx context.Context, statedb StateDB, input []byte, // bls12381G1Mul implements EIP-2537 G1Mul precompile. type bls12381G1Mul struct{} +func (c *bls12381G1Mul) RegistryKey() common.Address { + return common.BytesToAddress([]byte{11}) +} + // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bls12381G1Mul) RequiredGas(input []byte) uint64 { return params.Bls12381G1MulGas @@ -696,6 +753,10 @@ func (c *bls12381G1Mul) Run(ctx context.Context, statedb StateDB, input []byte, // bls12381G1MultiExp implements EIP-2537 G1MultiExp precompile. type bls12381G1MultiExp struct{} +func (c *bls12381G1MultiExp) RegistryKey() common.Address { + return common.BytesToAddress([]byte{12}) +} + // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bls12381G1MultiExp) RequiredGas(input []byte) uint64 { // Calculate G1 point, scalar value pair length @@ -753,6 +814,10 @@ func (c *bls12381G1MultiExp) Run(ctx context.Context, statedb StateDB, input []b // bls12381G2Add implements EIP-2537 G2Add precompile. type bls12381G2Add struct{} +func (c *bls12381G2Add) RegistryKey() common.Address { + return common.BytesToAddress([]byte{13}) +} + // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bls12381G2Add) RequiredGas(input []byte) uint64 { return params.Bls12381G2AddGas @@ -791,6 +856,10 @@ func (c *bls12381G2Add) Run(ctx context.Context, statedb StateDB, input []byte, // bls12381G2Mul implements EIP-2537 G2Mul precompile. type bls12381G2Mul struct{} +func (c *bls12381G2Mul) RegistryKey() common.Address { + return common.BytesToAddress([]byte{14}) +} + // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bls12381G2Mul) RequiredGas(input []byte) uint64 { return params.Bls12381G2MulGas @@ -827,6 +896,10 @@ func (c *bls12381G2Mul) Run(ctx context.Context, statedb StateDB, input []byte, // bls12381G2MultiExp implements EIP-2537 G2MultiExp precompile. type bls12381G2MultiExp struct{} +func (c *bls12381G2MultiExp) RegistryKey() common.Address { + return common.BytesToAddress([]byte{15}) +} + // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bls12381G2MultiExp) RequiredGas(input []byte) uint64 { // Calculate G2 point, scalar value pair length @@ -884,6 +957,10 @@ func (c *bls12381G2MultiExp) Run(ctx context.Context, statedb StateDB, input []b // bls12381Pairing implements EIP-2537 Pairing precompile. type bls12381Pairing struct{} +func (c *bls12381Pairing) RegistryKey() common.Address { + return common.BytesToAddress([]byte{16}) +} + // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bls12381Pairing) RequiredGas(input []byte) uint64 { return params.Bls12381PairingBaseGas + uint64(len(input)/384)*params.Bls12381PairingPerPairGas @@ -963,6 +1040,10 @@ func decodeBLS12381FieldElement(in []byte) ([]byte, error) { // bls12381MapG1 implements EIP-2537 MapG1 precompile. type bls12381MapG1 struct{} +func (c *bls12381MapG1) RegistryKey() common.Address { + return common.BytesToAddress([]byte{17}) +} + // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bls12381MapG1) RequiredGas(input []byte) uint64 { return params.Bls12381MapG1Gas @@ -998,6 +1079,10 @@ func (c *bls12381MapG1) Run(ctx context.Context, statedb StateDB, input []byte, // bls12381MapG2 implements EIP-2537 MapG2 precompile. type bls12381MapG2 struct{} +func (c *bls12381MapG2) RegistryKey() common.Address { + return common.BytesToAddress([]byte{18}) +} + // RequiredGas returns the gas required to execute the pre-compiled contract. func (c *bls12381MapG2) RequiredGas(input []byte) uint64 { return params.Bls12381MapG2Gas From 205de5922b49b698f8191d27eac9bb25c83bdb25 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Thu, 2 Feb 2023 12:39:39 -0500 Subject: [PATCH 18/40] has and get --- core/vm/evm.go | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index 6851c9eaa14d..2de023642a70 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -46,8 +46,12 @@ type PrecompileController interface { // before beginning a state transition. PrepareForStateTransition(statedb StateDB) error - // `Exists` returns if a precompiled contract was found at `addr`. - Exists(addr common.Address) (p PrecompiledContract, found bool) + // `Has` returns if a precompiled contract was found at `addr`. + Has(addr common.Address) bool + + // `Get` returns the precompiled contract at `addr`. Returns nil if no + // contract is found at `addr`. + Get(addr common.Address) PrecompiledContract // `Run` runs a precompiled contract and returns the remaining gas. Run(p PrecompiledContract, input []byte, caller common.Address, @@ -192,7 +196,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas return nil, gas, ErrInsufficientBalance } snapshot := evm.StateDB.Snapshot() - p, isPrecompile := evm.PrecompileController.Exists(addr) + isPrecompile := evm.PrecompileController.Has(addr) if !evm.StateDB.Exist(addr) { if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 { @@ -229,7 +233,9 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas } if isPrecompile { - ret, gas, err = evm.PrecompileController.Run(p, input, caller.Address(), value, gas, false) + ret, gas, err = evm.PrecompileController.Run( + evm.PrecompileController.Get(addr), input, caller.Address(), value, gas, false, + ) } else { // Initialise a new contract and set the code that is to be used by the EVM. // The contract is a scoped environment for this execution context only. @@ -291,8 +297,10 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, } // It is allowed to call precompiles, even via delegatecall - if p, isPrecompile := evm.PrecompileController.Exists(addr); isPrecompile { - ret, gas, err = evm.PrecompileController.Run(p, input, caller.Address(), value, gas, true) + if isPrecompile := evm.PrecompileController.Has(addr); isPrecompile { + ret, gas, err = evm.PrecompileController.Run( + evm.PrecompileController.Get(addr), input, caller.Address(), value, gas, true, + ) } else { addrCopy := addr // Initialise a new contract and set the code that is to be used by the EVM. @@ -336,9 +344,11 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by } // It is allowed to call precompiles, even via delegatecall - if p, isPrecompile := evm.PrecompileController.Exists(addr); isPrecompile { + if isPrecompile := evm.PrecompileController.Has(addr); isPrecompile { parent := caller.(*Contract) - ret, gas, err = evm.PrecompileController.Run(p, input, parent.CallerAddress, parent.value, gas, false) + ret, gas, err = evm.PrecompileController.Run( + evm.PrecompileController.Get(addr), input, parent.CallerAddress, parent.value, gas, false, + ) } else { addrCopy := addr // Initialise a new contract and make initialise the delegate values @@ -386,8 +396,10 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte }(gas) } - if p, isPrecompile := evm.PrecompileController.Exists(addr); isPrecompile { - ret, gas, err = evm.PrecompileController.Run(p, input, caller.Address(), new(big.Int), gas, true) + if isPrecompile := evm.PrecompileController.Has(addr); isPrecompile { + ret, gas, err = evm.PrecompileController.Run( + evm.PrecompileController.Get(addr), input, caller.Address(), new(big.Int), gas, true, + ) } else { // At this point, we use a copy of address. If we don't, the go compiler will // leak the 'contract' to the outer scope, and make allocation for 'contract' From ddff03cdb8ef6933ba8e5028d2ddbd4d58328c42 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Thu, 2 Feb 2023 12:47:36 -0500 Subject: [PATCH 19/40] controller > manager --- core/vm/evm.go | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index 2de023642a70..301773e6d2ab 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -40,8 +40,8 @@ type ( GetHashFunc func(uint64) common.Hash ) -// `PrecompileController` allows the EVM to execute a precompiled contract. -type PrecompileController interface { +// `PrecompileManager` allows the EVM to execute a precompiled contract. +type PrecompileManager interface { // `PrepareForStateTransition` holds the precompile native statedb // before beginning a state transition. PrepareForStateTransition(statedb StateDB) error @@ -103,8 +103,8 @@ type EVM struct { TxContext // StateDB gives access to the underlying state StateDB StateDB - // PrecompileController finds and runs precompiled contracts - PrecompileController PrecompileController + // PrecompileManager finds and runs precompiled contracts + PrecompileManager PrecompileManager // Depth is the current call stack depth int @@ -144,10 +144,10 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig func NewEVMWithPrecompiles( blockCtx BlockContext, txCtx TxContext, statedb StateDB, - chainConfig *params.ChainConfig, config Config, precompileController PrecompileController, + chainConfig *params.ChainConfig, config Config, precompileController PrecompileManager, ) *EVM { evm := NewEVM(blockCtx, txCtx, statedb, chainConfig, config) - evm.PrecompileController = precompileController + evm.PrecompileManager = precompileController return evm } @@ -196,7 +196,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas return nil, gas, ErrInsufficientBalance } snapshot := evm.StateDB.Snapshot() - isPrecompile := evm.PrecompileController.Has(addr) + isPrecompile := evm.PrecompileManager.Has(addr) if !evm.StateDB.Exist(addr) { if !isPrecompile && evm.chainRules.IsEIP158 && value.Sign() == 0 { @@ -233,8 +233,8 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas } if isPrecompile { - ret, gas, err = evm.PrecompileController.Run( - evm.PrecompileController.Get(addr), input, caller.Address(), value, gas, false, + ret, gas, err = evm.PrecompileManager.Run( + evm.PrecompileManager.Get(addr), input, caller.Address(), value, gas, false, ) } else { // Initialise a new contract and set the code that is to be used by the EVM. @@ -297,9 +297,9 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, } // It is allowed to call precompiles, even via delegatecall - if isPrecompile := evm.PrecompileController.Has(addr); isPrecompile { - ret, gas, err = evm.PrecompileController.Run( - evm.PrecompileController.Get(addr), input, caller.Address(), value, gas, true, + if isPrecompile := evm.PrecompileManager.Has(addr); isPrecompile { + ret, gas, err = evm.PrecompileManager.Run( + evm.PrecompileManager.Get(addr), input, caller.Address(), value, gas, true, ) } else { addrCopy := addr @@ -344,10 +344,10 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by } // It is allowed to call precompiles, even via delegatecall - if isPrecompile := evm.PrecompileController.Has(addr); isPrecompile { + if isPrecompile := evm.PrecompileManager.Has(addr); isPrecompile { parent := caller.(*Contract) - ret, gas, err = evm.PrecompileController.Run( - evm.PrecompileController.Get(addr), input, parent.CallerAddress, parent.value, gas, false, + ret, gas, err = evm.PrecompileManager.Run( + evm.PrecompileManager.Get(addr), input, parent.CallerAddress, parent.value, gas, false, ) } else { addrCopy := addr @@ -396,9 +396,9 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte }(gas) } - if isPrecompile := evm.PrecompileController.Has(addr); isPrecompile { - ret, gas, err = evm.PrecompileController.Run( - evm.PrecompileController.Get(addr), input, caller.Address(), new(big.Int), gas, true, + if isPrecompile := evm.PrecompileManager.Has(addr); isPrecompile { + ret, gas, err = evm.PrecompileManager.Run( + evm.PrecompileManager.Get(addr), input, caller.Address(), new(big.Int), gas, true, ) } else { // At this point, we use a copy of address. If we don't, the go compiler will From c0328076e2dc3107474c68db9a8f8f4afed44b45 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Thu, 2 Feb 2023 20:21:37 -0500 Subject: [PATCH 20/40] with statedb --- core/vm/contracts.go | 93 +++++++++++++++++++++++++++++++++----------- core/vm/evm.go | 8 ++-- 2 files changed, 74 insertions(+), 27 deletions(-) diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 4096563b1107..93c32f0dd4a3 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -38,9 +38,14 @@ import ( // requires a deterministic gas count based on the input size of the Run method of the // contract. type PrecompiledContract interface { + // RegistryKey returns the address at which the contract will be registered. RegistryKey() common.Address - RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use - Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) // Run runs the precompiled contract + // RequiredGas calculates the contract static gas use. + RequiredGas(input []byte) uint64 + // Run runs the precompiled contract with the given context. + Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) + // WithStateDB sets the statedb for the contract to use. + WithStateDB(sdb StateDB) PrecompiledContract } // PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum @@ -154,7 +159,7 @@ func (c *ecrecover) RequiredGas(input []byte) uint64 { return params.EcrecoverGas } -func (c *ecrecover) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *ecrecover) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { const ecRecoverInputLength = 128 input = common.RightPadBytes(input, ecRecoverInputLength) @@ -185,6 +190,8 @@ func (c *ecrecover) Run(ctx context.Context, statedb StateDB, input []byte, call return common.LeftPadBytes(crypto.Keccak256(pubKey[1:])[12:], 32), nil } +func (c *ecrecover) WithStateDB(StateDB) PrecompiledContract { return c } + // SHA256 implemented as a native contract. type sha256hash struct{} @@ -199,11 +206,13 @@ func (c *sha256hash) RegistryKey() common.Address { func (c *sha256hash) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas } -func (c *sha256hash) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *sha256hash) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { h := sha256.Sum256(input) return h[:], nil } +func (c *sha256hash) WithStateDB(StateDB) PrecompiledContract { return c } + // RIPEMD160 implemented as a native contract. type ripemd160hash struct{} @@ -218,12 +227,14 @@ func (c *ripemd160hash) RegistryKey() common.Address { func (c *ripemd160hash) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas } -func (c *ripemd160hash) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *ripemd160hash) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { ripemd := ripemd160.New() ripemd.Write(input) return common.LeftPadBytes(ripemd.Sum(nil), 32), nil } +func (c *ripemd160hash) WithStateDB(StateDB) PrecompiledContract { return c } + // data copy implemented as a native contract. type dataCopy struct{} @@ -238,10 +249,12 @@ func (c *dataCopy) RegistryKey() common.Address { func (c *dataCopy) RequiredGas(input []byte) uint64 { return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas } -func (c *dataCopy) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *dataCopy) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return input, nil } +func (c *dataCopy) WithStateDB(StateDB) PrecompiledContract { return c } + // bigModExp implements a native big integer exponential modular operation. type bigModExp struct { eip2565 bool @@ -369,7 +382,7 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 { return gas.Uint64() } -func (c *bigModExp) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bigModExp) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { var ( baseLen = new(big.Int).SetBytes(getData(input, 0, 32)).Uint64() expLen = new(big.Int).SetBytes(getData(input, 32, 32)).Uint64() @@ -404,6 +417,8 @@ func (c *bigModExp) Run(ctx context.Context, statedb StateDB, input []byte, call return common.LeftPadBytes(v, int(modLen)), nil } +func (c *bigModExp) WithStateDB(StateDB) PrecompiledContract { return c } + // newCurvePoint unmarshals a binary blob into a bn256 elliptic curve point, // returning it, or an error if the point is invalid. func newCurvePoint(blob []byte) (*bn256.G1, error) { @@ -453,10 +468,12 @@ func (c *bn256AddIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256AddGasIstanbul } -func (c *bn256AddIstanbul) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256AddIstanbul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Add(input) } +func (c *bn256AddIstanbul) WithStateDB(StateDB) PrecompiledContract { return c } + // bn256AddByzantium implements a native elliptic curve point addition // conforming to Byzantium consensus rules. type bn256AddByzantium struct{} @@ -470,10 +487,12 @@ func (c *bn256AddByzantium) RequiredGas(input []byte) uint64 { return params.Bn256AddGasByzantium } -func (c *bn256AddByzantium) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256AddByzantium) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Add(input) } +func (c *bn256AddByzantium) WithStateDB(StateDB) PrecompiledContract { return c } + // runBn256ScalarMul implements the Bn256ScalarMul precompile, referenced by // both Byzantium and Istanbul operations. func runBn256ScalarMul(input []byte) ([]byte, error) { @@ -499,10 +518,12 @@ func (c *bn256ScalarMulIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256ScalarMulGasIstanbul } -func (c *bn256ScalarMulIstanbul) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256ScalarMulIstanbul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256ScalarMul(input) } +func (c *bn256ScalarMulIstanbul) WithStateDB(StateDB) PrecompiledContract { return c } + // bn256ScalarMulByzantium implements a native elliptic curve scalar // multiplication conforming to Byzantium consensus rules. type bn256ScalarMulByzantium struct{} @@ -516,10 +537,12 @@ func (c *bn256ScalarMulByzantium) RequiredGas(input []byte) uint64 { return params.Bn256ScalarMulGasByzantium } -func (c *bn256ScalarMulByzantium) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256ScalarMulByzantium) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256ScalarMul(input) } +func (c *bn256ScalarMulByzantium) WithStateDB(StateDB) PrecompiledContract { return c } + var ( // true32Byte is returned if the bn256 pairing check succeeds. true32Byte = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} @@ -575,10 +598,12 @@ func (c *bn256PairingIstanbul) RequiredGas(input []byte) uint64 { return params.Bn256PairingBaseGasIstanbul + uint64(len(input)/192)*params.Bn256PairingPerPointGasIstanbul } -func (c *bn256PairingIstanbul) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256PairingIstanbul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Pairing(input) } +func (c *bn256PairingIstanbul) WithStateDB(StateDB) PrecompiledContract { return c } + // bn256PairingByzantium implements a pairing pre-compile for the bn256 curve // conforming to Byzantium consensus rules. type bn256PairingByzantium struct{} @@ -592,10 +617,12 @@ func (c *bn256PairingByzantium) RequiredGas(input []byte) uint64 { return params.Bn256PairingBaseGasByzantium + uint64(len(input)/192)*params.Bn256PairingPerPointGasByzantium } -func (c *bn256PairingByzantium) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bn256PairingByzantium) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { return runBn256Pairing(input) } +func (c *bn256PairingByzantium) WithStateDB(StateDB) PrecompiledContract { return c } + type blake2F struct{} func (c *blake2F) RegistryKey() common.Address { @@ -622,7 +649,7 @@ var ( errBlake2FInvalidFinalFlag = errors.New("invalid final flag") ) -func (c *blake2F) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *blake2F) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Make sure the input is valid (correct length and final flag) if len(input) != blake2FInputLength { return nil, errBlake2FInvalidInputLength @@ -661,6 +688,8 @@ func (c *blake2F) Run(ctx context.Context, statedb StateDB, input []byte, caller return output, nil } +func (c *blake2F) WithStateDB(StateDB) PrecompiledContract { return c } + var ( errBLS12381InvalidInputLength = errors.New("invalid input length") errBLS12381InvalidFieldElementTopBytes = errors.New("invalid field element top bytes") @@ -680,7 +709,7 @@ func (c *bls12381G1Add) RequiredGas(input []byte) uint64 { return params.Bls12381G1AddGas } -func (c *bls12381G1Add) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G1Add) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G1Add precompile. // > G1 addition call expects `256` bytes as an input that is interpreted as byte concatenation of two G1 points (`128` bytes each). // > Output is an encoding of addition operation result - single G1 point (`128` bytes). @@ -710,6 +739,8 @@ func (c *bls12381G1Add) Run(ctx context.Context, statedb StateDB, input []byte, return g.EncodePoint(r), nil } +func (c *bls12381G1Add) WithStateDB(StateDB) PrecompiledContract { return c } + // bls12381G1Mul implements EIP-2537 G1Mul precompile. type bls12381G1Mul struct{} @@ -722,7 +753,7 @@ func (c *bls12381G1Mul) RequiredGas(input []byte) uint64 { return params.Bls12381G1MulGas } -func (c *bls12381G1Mul) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G1Mul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G1Mul precompile. // > G1 multiplication call expects `160` bytes as an input that is interpreted as byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). // > Output is an encoding of multiplication operation result - single G1 point (`128` bytes). @@ -750,6 +781,8 @@ func (c *bls12381G1Mul) Run(ctx context.Context, statedb StateDB, input []byte, return g.EncodePoint(r), nil } +func (c *bls12381G1Mul) WithStateDB(StateDB) PrecompiledContract { return c } + // bls12381G1MultiExp implements EIP-2537 G1MultiExp precompile. type bls12381G1MultiExp struct{} @@ -776,7 +809,7 @@ func (c *bls12381G1MultiExp) RequiredGas(input []byte) uint64 { return (uint64(k) * params.Bls12381G1MulGas * discount) / 1000 } -func (c *bls12381G1MultiExp) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G1MultiExp) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G1MultiExp precompile. // G1 multiplication call expects `160*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G1 point (`128` bytes) and encoding of a scalar value (`32` bytes). // Output is an encoding of multiexponentiation operation result - single G1 point (`128` bytes). @@ -811,6 +844,8 @@ func (c *bls12381G1MultiExp) Run(ctx context.Context, statedb StateDB, input []b return g.EncodePoint(r), nil } +func (c *bls12381G1MultiExp) WithStateDB(StateDB) PrecompiledContract { return c } + // bls12381G2Add implements EIP-2537 G2Add precompile. type bls12381G2Add struct{} @@ -823,7 +858,7 @@ func (c *bls12381G2Add) RequiredGas(input []byte) uint64 { return params.Bls12381G2AddGas } -func (c *bls12381G2Add) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G2Add) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G2Add precompile. // > G2 addition call expects `512` bytes as an input that is interpreted as byte concatenation of two G2 points (`256` bytes each). // > Output is an encoding of addition operation result - single G2 point (`256` bytes). @@ -853,6 +888,8 @@ func (c *bls12381G2Add) Run(ctx context.Context, statedb StateDB, input []byte, return g.EncodePoint(r), nil } +func (c *bls12381G2Add) WithStateDB(StateDB) PrecompiledContract { return c } + // bls12381G2Mul implements EIP-2537 G2Mul precompile. type bls12381G2Mul struct{} @@ -865,7 +902,7 @@ func (c *bls12381G2Mul) RequiredGas(input []byte) uint64 { return params.Bls12381G2MulGas } -func (c *bls12381G2Mul) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G2Mul) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G2MUL precompile logic. // > G2 multiplication call expects `288` bytes as an input that is interpreted as byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). // > Output is an encoding of multiplication operation result - single G2 point (`256` bytes). @@ -893,6 +930,8 @@ func (c *bls12381G2Mul) Run(ctx context.Context, statedb StateDB, input []byte, return g.EncodePoint(r), nil } +func (c *bls12381G2Mul) WithStateDB(StateDB) PrecompiledContract { return c } + // bls12381G2MultiExp implements EIP-2537 G2MultiExp precompile. type bls12381G2MultiExp struct{} @@ -919,7 +958,7 @@ func (c *bls12381G2MultiExp) RequiredGas(input []byte) uint64 { return (uint64(k) * params.Bls12381G2MulGas * discount) / 1000 } -func (c *bls12381G2MultiExp) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381G2MultiExp) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 G2MultiExp precompile logic // > G2 multiplication call expects `288*k` bytes as an input that is interpreted as byte concatenation of `k` slices each of them being a byte concatenation of encoding of G2 point (`256` bytes) and encoding of a scalar value (`32` bytes). // > Output is an encoding of multiexponentiation operation result - single G2 point (`256` bytes). @@ -954,6 +993,8 @@ func (c *bls12381G2MultiExp) Run(ctx context.Context, statedb StateDB, input []b return g.EncodePoint(r), nil } +func (c *bls12381G2MultiExp) WithStateDB(StateDB) PrecompiledContract { return c } + // bls12381Pairing implements EIP-2537 Pairing precompile. type bls12381Pairing struct{} @@ -966,7 +1007,7 @@ func (c *bls12381Pairing) RequiredGas(input []byte) uint64 { return params.Bls12381PairingBaseGas + uint64(len(input)/384)*params.Bls12381PairingPerPairGas } -func (c *bls12381Pairing) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381Pairing) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 Pairing precompile logic. // > Pairing call expects `384*k` bytes as an inputs that is interpreted as byte concatenation of `k` slices. Each slice has the following structure: // > - `128` bytes of G1 point encoding @@ -1020,6 +1061,8 @@ func (c *bls12381Pairing) Run(ctx context.Context, statedb StateDB, input []byte return out, nil } +func (c *bls12381Pairing) WithStateDB(StateDB) PrecompiledContract { return c } + // decodeBLS12381FieldElement decodes BLS12-381 elliptic curve field element. // Removes top 16 bytes of 64 byte input. func decodeBLS12381FieldElement(in []byte) ([]byte, error) { @@ -1049,7 +1092,7 @@ func (c *bls12381MapG1) RequiredGas(input []byte) uint64 { return params.Bls12381MapG1Gas } -func (c *bls12381MapG1) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381MapG1) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 Map_To_G1 precompile. // > Field-to-curve call expects `64` bytes an an input that is interpreted as a an element of the base field. // > Output of this call is `128` bytes and is G1 point following respective encoding rules. @@ -1076,6 +1119,8 @@ func (c *bls12381MapG1) Run(ctx context.Context, statedb StateDB, input []byte, return g.EncodePoint(r), nil } +func (c *bls12381MapG1) WithStateDB(StateDB) PrecompiledContract { return c } + // bls12381MapG2 implements EIP-2537 MapG2 precompile. type bls12381MapG2 struct{} @@ -1088,7 +1133,7 @@ func (c *bls12381MapG2) RequiredGas(input []byte) uint64 { return params.Bls12381MapG2Gas } -func (c *bls12381MapG2) Run(ctx context.Context, statedb StateDB, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { +func (c *bls12381MapG2) Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) { // Implements EIP-2537 Map_FP2_TO_G2 precompile logic. // > Field-to-curve call expects `128` bytes an an input that is interpreted as a an element of the quadratic extension field. // > Output of this call is `256` bytes and is G2 point following respective encoding rules. @@ -1121,3 +1166,5 @@ func (c *bls12381MapG2) Run(ctx context.Context, statedb StateDB, input []byte, // Encode the G2 point to 256 bytes return g.EncodePoint(r), nil } + +func (c *bls12381MapG2) WithStateDB(StateDB) PrecompiledContract { return c } diff --git a/core/vm/evm.go b/core/vm/evm.go index 301773e6d2ab..ccba362672f9 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -234,7 +234,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas if isPrecompile { ret, gas, err = evm.PrecompileManager.Run( - evm.PrecompileManager.Get(addr), input, caller.Address(), value, gas, false, + evm.PrecompileManager.Get(addr).WithStateDB(evm.StateDB), input, caller.Address(), value, gas, false, ) } else { // Initialise a new contract and set the code that is to be used by the EVM. @@ -299,7 +299,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, // It is allowed to call precompiles, even via delegatecall if isPrecompile := evm.PrecompileManager.Has(addr); isPrecompile { ret, gas, err = evm.PrecompileManager.Run( - evm.PrecompileManager.Get(addr), input, caller.Address(), value, gas, true, + evm.PrecompileManager.Get(addr).WithStateDB(evm.StateDB), input, caller.Address(), value, gas, true, ) } else { addrCopy := addr @@ -347,7 +347,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by if isPrecompile := evm.PrecompileManager.Has(addr); isPrecompile { parent := caller.(*Contract) ret, gas, err = evm.PrecompileManager.Run( - evm.PrecompileManager.Get(addr), input, parent.CallerAddress, parent.value, gas, false, + evm.PrecompileManager.Get(addr).WithStateDB(evm.StateDB), input, parent.CallerAddress, parent.value, gas, false, ) } else { addrCopy := addr @@ -398,7 +398,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte if isPrecompile := evm.PrecompileManager.Has(addr); isPrecompile { ret, gas, err = evm.PrecompileManager.Run( - evm.PrecompileManager.Get(addr), input, caller.Address(), new(big.Int), gas, true, + evm.PrecompileManager.Get(addr).WithStateDB(evm.StateDB), input, caller.Address(), new(big.Int), gas, true, ) } else { // At this point, we use a copy of address. If we don't, the go compiler will From dfc88fb098210596215f3410e6c65ef876820c0e Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Thu, 2 Feb 2023 20:34:16 -0500 Subject: [PATCH 21/40] with ctx --- core/vm/evm.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index ccba362672f9..7d2ca805d3b6 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -17,6 +17,7 @@ package vm import ( + "context" "math/big" "sync/atomic" @@ -42,9 +43,9 @@ type ( // `PrecompileManager` allows the EVM to execute a precompiled contract. type PrecompileManager interface { - // `PrepareForStateTransition` holds the precompile native statedb + // `PrepareForStateTransition` sets the native precompile context // before beginning a state transition. - PrepareForStateTransition(statedb StateDB) error + PrepareForStateTransition(ctx context.Context) error // `Has` returns if a precompiled contract was found at `addr`. Has(addr common.Address) bool From 3bcbe77f73f6a273aa997786c37dcc3ed9a27115 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Mon, 6 Feb 2023 18:19:37 -0500 Subject: [PATCH 22/40] simple precompile manager --- core/vm/contracts.go | 44 -------------------------------------------- core/vm/evm.go | 15 ++++++++------- 2 files changed, 8 insertions(+), 51 deletions(-) diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 93c32f0dd4a3..95ffaaefada3 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -44,8 +44,6 @@ type PrecompiledContract interface { RequiredGas(input []byte) uint64 // Run runs the precompiled contract with the given context. Run(ctx context.Context, input []byte, caller common.Address, value *big.Int, readonly bool) ([]byte, error) - // WithStateDB sets the statedb for the contract to use. - WithStateDB(sdb StateDB) PrecompiledContract } // PrecompiledContractsHomestead contains the default set of pre-compiled Ethereum @@ -190,8 +188,6 @@ func (c *ecrecover) Run(ctx context.Context, input []byte, caller common.Address return common.LeftPadBytes(crypto.Keccak256(pubKey[1:])[12:], 32), nil } -func (c *ecrecover) WithStateDB(StateDB) PrecompiledContract { return c } - // SHA256 implemented as a native contract. type sha256hash struct{} @@ -211,8 +207,6 @@ func (c *sha256hash) Run(ctx context.Context, input []byte, caller common.Addres return h[:], nil } -func (c *sha256hash) WithStateDB(StateDB) PrecompiledContract { return c } - // RIPEMD160 implemented as a native contract. type ripemd160hash struct{} @@ -233,8 +227,6 @@ func (c *ripemd160hash) Run(ctx context.Context, input []byte, caller common.Add return common.LeftPadBytes(ripemd.Sum(nil), 32), nil } -func (c *ripemd160hash) WithStateDB(StateDB) PrecompiledContract { return c } - // data copy implemented as a native contract. type dataCopy struct{} @@ -253,8 +245,6 @@ func (c *dataCopy) Run(ctx context.Context, input []byte, caller common.Address, return input, nil } -func (c *dataCopy) WithStateDB(StateDB) PrecompiledContract { return c } - // bigModExp implements a native big integer exponential modular operation. type bigModExp struct { eip2565 bool @@ -417,8 +407,6 @@ func (c *bigModExp) Run(ctx context.Context, input []byte, caller common.Address return common.LeftPadBytes(v, int(modLen)), nil } -func (c *bigModExp) WithStateDB(StateDB) PrecompiledContract { return c } - // newCurvePoint unmarshals a binary blob into a bn256 elliptic curve point, // returning it, or an error if the point is invalid. func newCurvePoint(blob []byte) (*bn256.G1, error) { @@ -472,8 +460,6 @@ func (c *bn256AddIstanbul) Run(ctx context.Context, input []byte, caller common. return runBn256Add(input) } -func (c *bn256AddIstanbul) WithStateDB(StateDB) PrecompiledContract { return c } - // bn256AddByzantium implements a native elliptic curve point addition // conforming to Byzantium consensus rules. type bn256AddByzantium struct{} @@ -491,8 +477,6 @@ func (c *bn256AddByzantium) Run(ctx context.Context, input []byte, caller common return runBn256Add(input) } -func (c *bn256AddByzantium) WithStateDB(StateDB) PrecompiledContract { return c } - // runBn256ScalarMul implements the Bn256ScalarMul precompile, referenced by // both Byzantium and Istanbul operations. func runBn256ScalarMul(input []byte) ([]byte, error) { @@ -522,8 +506,6 @@ func (c *bn256ScalarMulIstanbul) Run(ctx context.Context, input []byte, caller c return runBn256ScalarMul(input) } -func (c *bn256ScalarMulIstanbul) WithStateDB(StateDB) PrecompiledContract { return c } - // bn256ScalarMulByzantium implements a native elliptic curve scalar // multiplication conforming to Byzantium consensus rules. type bn256ScalarMulByzantium struct{} @@ -541,8 +523,6 @@ func (c *bn256ScalarMulByzantium) Run(ctx context.Context, input []byte, caller return runBn256ScalarMul(input) } -func (c *bn256ScalarMulByzantium) WithStateDB(StateDB) PrecompiledContract { return c } - var ( // true32Byte is returned if the bn256 pairing check succeeds. true32Byte = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1} @@ -602,8 +582,6 @@ func (c *bn256PairingIstanbul) Run(ctx context.Context, input []byte, caller com return runBn256Pairing(input) } -func (c *bn256PairingIstanbul) WithStateDB(StateDB) PrecompiledContract { return c } - // bn256PairingByzantium implements a pairing pre-compile for the bn256 curve // conforming to Byzantium consensus rules. type bn256PairingByzantium struct{} @@ -621,8 +599,6 @@ func (c *bn256PairingByzantium) Run(ctx context.Context, input []byte, caller co return runBn256Pairing(input) } -func (c *bn256PairingByzantium) WithStateDB(StateDB) PrecompiledContract { return c } - type blake2F struct{} func (c *blake2F) RegistryKey() common.Address { @@ -688,8 +664,6 @@ func (c *blake2F) Run(ctx context.Context, input []byte, caller common.Address, return output, nil } -func (c *blake2F) WithStateDB(StateDB) PrecompiledContract { return c } - var ( errBLS12381InvalidInputLength = errors.New("invalid input length") errBLS12381InvalidFieldElementTopBytes = errors.New("invalid field element top bytes") @@ -739,8 +713,6 @@ func (c *bls12381G1Add) Run(ctx context.Context, input []byte, caller common.Add return g.EncodePoint(r), nil } -func (c *bls12381G1Add) WithStateDB(StateDB) PrecompiledContract { return c } - // bls12381G1Mul implements EIP-2537 G1Mul precompile. type bls12381G1Mul struct{} @@ -781,8 +753,6 @@ func (c *bls12381G1Mul) Run(ctx context.Context, input []byte, caller common.Add return g.EncodePoint(r), nil } -func (c *bls12381G1Mul) WithStateDB(StateDB) PrecompiledContract { return c } - // bls12381G1MultiExp implements EIP-2537 G1MultiExp precompile. type bls12381G1MultiExp struct{} @@ -844,8 +814,6 @@ func (c *bls12381G1MultiExp) Run(ctx context.Context, input []byte, caller commo return g.EncodePoint(r), nil } -func (c *bls12381G1MultiExp) WithStateDB(StateDB) PrecompiledContract { return c } - // bls12381G2Add implements EIP-2537 G2Add precompile. type bls12381G2Add struct{} @@ -888,8 +856,6 @@ func (c *bls12381G2Add) Run(ctx context.Context, input []byte, caller common.Add return g.EncodePoint(r), nil } -func (c *bls12381G2Add) WithStateDB(StateDB) PrecompiledContract { return c } - // bls12381G2Mul implements EIP-2537 G2Mul precompile. type bls12381G2Mul struct{} @@ -930,8 +896,6 @@ func (c *bls12381G2Mul) Run(ctx context.Context, input []byte, caller common.Add return g.EncodePoint(r), nil } -func (c *bls12381G2Mul) WithStateDB(StateDB) PrecompiledContract { return c } - // bls12381G2MultiExp implements EIP-2537 G2MultiExp precompile. type bls12381G2MultiExp struct{} @@ -993,8 +957,6 @@ func (c *bls12381G2MultiExp) Run(ctx context.Context, input []byte, caller commo return g.EncodePoint(r), nil } -func (c *bls12381G2MultiExp) WithStateDB(StateDB) PrecompiledContract { return c } - // bls12381Pairing implements EIP-2537 Pairing precompile. type bls12381Pairing struct{} @@ -1061,8 +1023,6 @@ func (c *bls12381Pairing) Run(ctx context.Context, input []byte, caller common.A return out, nil } -func (c *bls12381Pairing) WithStateDB(StateDB) PrecompiledContract { return c } - // decodeBLS12381FieldElement decodes BLS12-381 elliptic curve field element. // Removes top 16 bytes of 64 byte input. func decodeBLS12381FieldElement(in []byte) ([]byte, error) { @@ -1119,8 +1079,6 @@ func (c *bls12381MapG1) Run(ctx context.Context, input []byte, caller common.Add return g.EncodePoint(r), nil } -func (c *bls12381MapG1) WithStateDB(StateDB) PrecompiledContract { return c } - // bls12381MapG2 implements EIP-2537 MapG2 precompile. type bls12381MapG2 struct{} @@ -1166,5 +1124,3 @@ func (c *bls12381MapG2) Run(ctx context.Context, input []byte, caller common.Add // Encode the G2 point to 256 bytes return g.EncodePoint(r), nil } - -func (c *bls12381MapG2) WithStateDB(StateDB) PrecompiledContract { return c } diff --git a/core/vm/evm.go b/core/vm/evm.go index 7d2ca805d3b6..374adbdefe90 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -43,9 +43,9 @@ type ( // `PrecompileManager` allows the EVM to execute a precompiled contract. type PrecompileManager interface { - // `PrepareForStateTransition` sets the native precompile context - // before beginning a state transition. - PrepareForStateTransition(ctx context.Context) error + // `Reset` sets the native precompile context before beginning a state + // transition. + Reset(ctx context.Context) // `Has` returns if a precompiled contract was found at `addr`. Has(addr common.Address) bool @@ -234,8 +234,9 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas } if isPrecompile { + ret, gas, err = evm.PrecompileManager.Run( - evm.PrecompileManager.Get(addr).WithStateDB(evm.StateDB), input, caller.Address(), value, gas, false, + evm.PrecompileManager.Get(addr), input, caller.Address(), value, gas, false, ) } else { // Initialise a new contract and set the code that is to be used by the EVM. @@ -300,7 +301,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, // It is allowed to call precompiles, even via delegatecall if isPrecompile := evm.PrecompileManager.Has(addr); isPrecompile { ret, gas, err = evm.PrecompileManager.Run( - evm.PrecompileManager.Get(addr).WithStateDB(evm.StateDB), input, caller.Address(), value, gas, true, + evm.PrecompileManager.Get(addr), input, caller.Address(), value, gas, true, ) } else { addrCopy := addr @@ -348,7 +349,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by if isPrecompile := evm.PrecompileManager.Has(addr); isPrecompile { parent := caller.(*Contract) ret, gas, err = evm.PrecompileManager.Run( - evm.PrecompileManager.Get(addr).WithStateDB(evm.StateDB), input, parent.CallerAddress, parent.value, gas, false, + evm.PrecompileManager.Get(addr), input, parent.CallerAddress, parent.value, gas, false, ) } else { addrCopy := addr @@ -399,7 +400,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte if isPrecompile := evm.PrecompileManager.Has(addr); isPrecompile { ret, gas, err = evm.PrecompileManager.Run( - evm.PrecompileManager.Get(addr).WithStateDB(evm.StateDB), input, caller.Address(), new(big.Int), gas, true, + evm.PrecompileManager.Get(addr), input, caller.Address(), new(big.Int), gas, true, ) } else { // At this point, we use a copy of address. If we don't, the go compiler will From d04e4af6cb9bcffb6220ffc3d44c960cc5a29e84 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Fri, 10 Feb 2023 11:16:16 -0500 Subject: [PATCH 23/40] allow setting block context to evm --- core/vm/contracts_test.go | 12 ++++++++++++ core/vm/evm.go | 3 +-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/core/vm/contracts_test.go b/core/vm/contracts_test.go index b22d999e6cd9..4ed94d93a950 100644 --- a/core/vm/contracts_test.go +++ b/core/vm/contracts_test.go @@ -18,8 +18,10 @@ package vm import ( "bytes" + "context" "encoding/json" "fmt" + "math/big" "os" "testing" "time" @@ -91,6 +93,16 @@ var blake2FMalformedInputTests = []precompiledFailureTest{ }, } +func RunPrecompiledContract(p PrecompiledContract, input []byte, suppliedGas uint64) (ret []byte, remainingGas uint64, err error) { + gasCost := p.RequiredGas(input) + if suppliedGas < gasCost { + return nil, 0, ErrOutOfGas + } + suppliedGas -= gasCost + output, err := p.Run(context.Background(), input, common.Address{}, new(big.Int), true) + return output, suppliedGas, err +} + func testPrecompiled(addr string, test precompiledTest, t *testing.T) { p := allPrecompiles[common.HexToAddress(addr)] in := common.Hex2Bytes(test.Input) diff --git a/core/vm/evm.go b/core/vm/evm.go index 374adbdefe90..855f033b2ce1 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -179,8 +179,7 @@ func (evm *EVM) Interpreter() *EVMInterpreter { func (evm *EVM) SetBlockContext(blockCtx BlockContext) { evm.Context = blockCtx num := blockCtx.BlockNumber - timestamp := blockCtx.Time - evm.chainRules = evm.chainConfig.Rules(num, blockCtx.Random != nil, timestamp) + evm.chainRules = evm.chainConfig.Rules(num, blockCtx.Random != nil) } // Call executes the contract associated with the addr with the given input as From f7ab8a687a44cfe95d6e59c7e5809c0580cadf7e Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Fri, 10 Feb 2023 12:34:29 -0500 Subject: [PATCH 24/40] remove unneded evm funcs --- core/vm/evm.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index 855f033b2ce1..caaa7f746a98 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -175,13 +175,6 @@ func (evm *EVM) Interpreter() *EVMInterpreter { return evm.interpreter } -// SetBlockContext updates the block context of the EVM. -func (evm *EVM) SetBlockContext(blockCtx BlockContext) { - evm.Context = blockCtx - num := blockCtx.BlockNumber - evm.chainRules = evm.chainConfig.Rules(num, blockCtx.Random != nil) -} - // Call executes the contract associated with the addr with the given input as // parameters. It also handles any necessary value transfer required and takes // the necessary steps to create accounts and reverses the state in case of an From 7fde4c92bced4baf7bacf421c43a10434fc6fcae Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Wed, 15 Feb 2023 19:28:51 -0500 Subject: [PATCH 25/40] simplify precompile manager --- core/vm/evm.go | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index caaa7f746a98..069ca9e37a10 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -43,8 +43,6 @@ type ( // `PrecompileManager` allows the EVM to execute a precompiled contract. type PrecompileManager interface { - // `Reset` sets the native precompile context before beginning a state - // transition. Reset(ctx context.Context) // `Has` returns if a precompiled contract was found at `addr`. @@ -55,7 +53,7 @@ type PrecompileManager interface { Get(addr common.Address) PrecompiledContract // `Run` runs a precompiled contract and returns the remaining gas. - Run(p PrecompiledContract, input []byte, caller common.Address, + Run(sdb StateDB, p PrecompiledContract, input []byte, caller common.Address, value *big.Int, suppliedGas uint64, readonly bool, ) (ret []byte, remainingGas uint64, err error) } @@ -226,9 +224,8 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas } if isPrecompile { - ret, gas, err = evm.PrecompileManager.Run( - evm.PrecompileManager.Get(addr), input, caller.Address(), value, gas, false, + evm.StateDB, evm.PrecompileManager.Get(addr), input, caller.Address(), value, gas, false, ) } else { // Initialise a new contract and set the code that is to be used by the EVM. @@ -293,7 +290,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, // It is allowed to call precompiles, even via delegatecall if isPrecompile := evm.PrecompileManager.Has(addr); isPrecompile { ret, gas, err = evm.PrecompileManager.Run( - evm.PrecompileManager.Get(addr), input, caller.Address(), value, gas, true, + evm.StateDB, evm.PrecompileManager.Get(addr), input, caller.Address(), value, gas, true, ) } else { addrCopy := addr @@ -341,7 +338,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by if isPrecompile := evm.PrecompileManager.Has(addr); isPrecompile { parent := caller.(*Contract) ret, gas, err = evm.PrecompileManager.Run( - evm.PrecompileManager.Get(addr), input, parent.CallerAddress, parent.value, gas, false, + evm.StateDB, evm.PrecompileManager.Get(addr), input, parent.CallerAddress, parent.value, gas, false, ) } else { addrCopy := addr @@ -392,7 +389,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte if isPrecompile := evm.PrecompileManager.Has(addr); isPrecompile { ret, gas, err = evm.PrecompileManager.Run( - evm.PrecompileManager.Get(addr), input, caller.Address(), new(big.Int), gas, true, + evm.StateDB, evm.PrecompileManager.Get(addr), input, caller.Address(), new(big.Int), gas, true, ) } else { // At this point, we use a copy of address. If we don't, the go compiler will From 553a2028ca3ec9b8862fde7748218c34c0e963c2 Mon Sep 17 00:00:00 2001 From: t12s Date: Thu, 16 Feb 2023 19:32:39 -0500 Subject: [PATCH 26/40] updated go.sum --- go.sum | 5 ----- 1 file changed, 5 deletions(-) diff --git a/go.sum b/go.sum index 0ddcfe7cce51..157dafb112fa 100644 --- a/go.sum +++ b/go.sum @@ -169,7 +169,6 @@ github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlK 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/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= @@ -713,7 +712,6 @@ golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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= @@ -731,9 +729,6 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/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/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 9ca5cc4839fdd50463d196a83bd84c437822790c Mon Sep 17 00:00:00 2001 From: t12s Date: Thu, 16 Feb 2023 19:50:09 -0500 Subject: [PATCH 27/40] removing extra bits --- accounts/abi/bind/bind.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accounts/abi/bind/bind.go b/accounts/abi/bind/bind.go index c179dbcc925f..05cca8e90b3a 100644 --- a/accounts/abi/bind/bind.go +++ b/accounts/abi/bind/bind.go @@ -187,7 +187,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string] } eventIdentifiers[normalizedName] = true normalized.Name = normalizedName - + used := make(map[string]bool) normalized.Inputs = make([]abi.Argument, len(original.Inputs)) copy(normalized.Inputs, original.Inputs) From bd594629bb27369b0493f5fccf47cce576442654 Mon Sep 17 00:00:00 2001 From: t12s Date: Fri, 17 Feb 2023 14:15:48 -0500 Subject: [PATCH 28/40] typo fixes --- eth/protocols/snap/sync.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eth/protocols/snap/sync.go b/eth/protocols/snap/sync.go index 13279fd96c43..5a47979981a0 100644 --- a/eth/protocols/snap/sync.go +++ b/eth/protocols/snap/sync.go @@ -84,8 +84,8 @@ const ( minTrienodeHealThrottle = 1 // maxTrienodeHealThrottle is the maximum divisor for throttling trie node - // heal requests to avoid overloading the local node and exessively expanding - // the state trie bedth wise. + // heal requests to avoid overloading the local node and excessively expanding + // the state trie breadth wise. maxTrienodeHealThrottle = maxTrieRequestCount // trienodeHealThrottleIncrease is the multiplier for the throttle when the From b9c956b5c56ae57876a689a714c1bd2ba9d018c6 Mon Sep 17 00:00:00 2001 From: Devon Bear Date: Sat, 18 Feb 2023 16:24:58 -0500 Subject: [PATCH 29/40] ethapi --- cmd/clef/main.go | 2 +- cmd/geth/config.go | 2 +- cmd/geth/main.go | 2 +- cmd/utils/flags.go | 2 +- eth/api.go | 2 +- eth/backend.go | 2 +- eth/filters/api.go | 2 +- eth/tracers/api.go | 2 +- eth/tracers/api_test.go | 2 +- {internal/ethapi => ethapi}/addrlock.go | 0 {internal/ethapi => ethapi}/api.go | 0 {internal/ethapi => ethapi}/backend.go | 0 {internal/ethapi => ethapi}/dbapi.go | 0 {internal/ethapi => ethapi}/transaction_args.go | 0 {internal/ethapi => ethapi}/transaction_args_test.go | 0 graphql/graphql.go | 2 +- graphql/service.go | 2 +- les/client.go | 2 +- signer/core/api.go | 2 +- signer/core/api_test.go | 2 +- signer/core/auditlog.go | 2 +- signer/core/cliui.go | 2 +- signer/core/stdioui.go | 2 +- signer/rules/rules.go | 2 +- signer/rules/rules_test.go | 2 +- 25 files changed, 19 insertions(+), 19 deletions(-) rename {internal/ethapi => ethapi}/addrlock.go (100%) rename {internal/ethapi => ethapi}/api.go (100%) rename {internal/ethapi => ethapi}/backend.go (100%) rename {internal/ethapi => ethapi}/dbapi.go (100%) rename {internal/ethapi => ethapi}/transaction_args.go (100%) rename {internal/ethapi => ethapi}/transaction_args_test.go (100%) diff --git a/cmd/clef/main.go b/cmd/clef/main.go index 2788ddc33b9e..e71c2e538edc 100644 --- a/cmd/clef/main.go +++ b/cmd/clef/main.go @@ -41,7 +41,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" diff --git a/cmd/geth/config.go b/cmd/geth/config.go index 0b856d1c1b7a..29bd13e9e53a 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -33,7 +33,7 @@ import ( "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/ethconfig" - "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/internal/version" "github.com/ethereum/go-ethereum/log" diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 5ba070249897..d7bdfd995d60 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -32,9 +32,9 @@ import ( "github.com/ethereum/go-ethereum/console/prompt" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth/downloader" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/internal/debug" - "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 08de71ee831b..88a40ffecbda 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -53,11 +53,11 @@ import ( "github.com/ethereum/go-ethereum/eth/filters" "github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/eth/tracers" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb/remotedb" "github.com/ethereum/go-ethereum/ethstats" "github.com/ethereum/go-ethereum/graphql" - "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/les" lescatalyst "github.com/ethereum/go-ethereum/les/catalyst" diff --git a/eth/api.go b/eth/api.go index ceed85ef576b..c1f73037d7d8 100644 --- a/eth/api.go +++ b/eth/api.go @@ -34,7 +34,7 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" diff --git a/eth/backend.go b/eth/backend.go index 6368c0e03c56..9bde9cd34bd1 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -43,9 +43,9 @@ import ( "github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/eth/protocols/eth" "github.com/ethereum/go-ethereum/eth/protocols/snap" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/internal/shutdowncheck" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/miner" diff --git a/eth/filters/api.go b/eth/filters/api.go index f9ae70eba796..e3b1a32d9986 100644 --- a/eth/filters/api.go +++ b/eth/filters/api.go @@ -29,7 +29,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/rpc" ) diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 55c56b40c9f1..6dca581ed74c 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -37,8 +37,8 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/eth/tracers/logger" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index 29ec80868579..bbcb00a5e763 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -41,8 +41,8 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth/tracers/logger" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/ethdb" - "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" ) diff --git a/internal/ethapi/addrlock.go b/ethapi/addrlock.go similarity index 100% rename from internal/ethapi/addrlock.go rename to ethapi/addrlock.go diff --git a/internal/ethapi/api.go b/ethapi/api.go similarity index 100% rename from internal/ethapi/api.go rename to ethapi/api.go diff --git a/internal/ethapi/backend.go b/ethapi/backend.go similarity index 100% rename from internal/ethapi/backend.go rename to ethapi/backend.go diff --git a/internal/ethapi/dbapi.go b/ethapi/dbapi.go similarity index 100% rename from internal/ethapi/dbapi.go rename to ethapi/dbapi.go diff --git a/internal/ethapi/transaction_args.go b/ethapi/transaction_args.go similarity index 100% rename from internal/ethapi/transaction_args.go rename to ethapi/transaction_args.go diff --git a/internal/ethapi/transaction_args_test.go b/ethapi/transaction_args_test.go similarity index 100% rename from internal/ethapi/transaction_args_test.go rename to ethapi/transaction_args_test.go diff --git a/graphql/graphql.go b/graphql/graphql.go index 356ff669fb16..637778e9d0f7 100644 --- a/graphql/graphql.go +++ b/graphql/graphql.go @@ -33,7 +33,7 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/filters" - "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" ) diff --git a/graphql/service.go b/graphql/service.go index 4392dd83e688..332a0d6ca71a 100644 --- a/graphql/service.go +++ b/graphql/service.go @@ -25,7 +25,7 @@ import ( "time" "github.com/ethereum/go-ethereum/eth/filters" - "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/rpc" "github.com/graph-gophers/graphql-go" diff --git a/les/client.go b/les/client.go index 9ac85ecdac6f..60a2a3d2856b 100644 --- a/les/client.go +++ b/les/client.go @@ -33,8 +33,8 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/eth/gasprice" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/internal/shutdowncheck" "github.com/ethereum/go-ethereum/les/downloader" "github.com/ethereum/go-ethereum/les/vflux" diff --git a/signer/core/api.go b/signer/core/api.go index 3c1c94801b11..bdb3f6f7e0a9 100644 --- a/signer/core/api.go +++ b/signer/core/api.go @@ -33,7 +33,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/math" - "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/signer/core/apitypes" diff --git a/signer/core/api_test.go b/signer/core/api_test.go index 9bb55bddca31..16a9cc59b533 100644 --- a/signer/core/api_test.go +++ b/signer/core/api_test.go @@ -31,7 +31,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/signer/core" "github.com/ethereum/go-ethereum/signer/core/apitypes" diff --git a/signer/core/auditlog.go b/signer/core/auditlog.go index a0b292bf714c..f13a42aa1b8f 100644 --- a/signer/core/auditlog.go +++ b/signer/core/auditlog.go @@ -22,7 +22,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/signer/core/apitypes" ) diff --git a/signer/core/cliui.go b/signer/core/cliui.go index b1bd3206ed3f..4569260bdaf8 100644 --- a/signer/core/cliui.go +++ b/signer/core/cliui.go @@ -27,7 +27,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/console/prompt" - "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/log" ) diff --git a/signer/core/stdioui.go b/signer/core/stdioui.go index 6963a89122f6..9bd271c1345d 100644 --- a/signer/core/stdioui.go +++ b/signer/core/stdioui.go @@ -19,7 +19,7 @@ package core import ( "context" - "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" ) diff --git a/signer/rules/rules.go b/signer/rules/rules.go index 5ed4514e0227..6ebe23148e5f 100644 --- a/signer/rules/rules.go +++ b/signer/rules/rules.go @@ -23,7 +23,7 @@ import ( "strings" "github.com/dop251/goja" - "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/internal/jsre/deps" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/signer/core" diff --git a/signer/rules/rules_test.go b/signer/rules/rules_test.go index c35da8ecc188..a8dea13131d7 100644 --- a/signer/rules/rules_test.go +++ b/signer/rules/rules_test.go @@ -26,7 +26,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/internal/ethapi" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/signer/core" "github.com/ethereum/go-ethereum/signer/core/apitypes" "github.com/ethereum/go-ethereum/signer/storage" From 6f9e9af718bd4041f771ede788a1233d5da3568c Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Sun, 19 Feb 2023 16:56:13 -0500 Subject: [PATCH 30/40] cleanup precomp manager --- core/vm/evm.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/vm/evm.go b/core/vm/evm.go index 069ca9e37a10..a5b106b63b28 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -17,7 +17,6 @@ package vm import ( - "context" "math/big" "sync/atomic" @@ -43,8 +42,6 @@ type ( // `PrecompileManager` allows the EVM to execute a precompiled contract. type PrecompileManager interface { - Reset(ctx context.Context) - // `Has` returns if a precompiled contract was found at `addr`. Has(addr common.Address) bool From c90cd3759f3b1227f0e5d90138c6a2a9c809ce8a Mon Sep 17 00:00:00 2001 From: Devon Bear Date: Tue, 21 Feb 2023 22:21:41 -0500 Subject: [PATCH 31/40] add get chain id --- core/types/transaction.go | 1 + core/types/tx_access_list.go | 1 + core/types/tx_dynamic_fee.go | 1 + core/types/tx_legacy.go | 1 + 4 files changed, 4 insertions(+) diff --git a/core/types/transaction.go b/core/types/transaction.go index 353e0e599c68..412a9810dfb7 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -85,6 +85,7 @@ type TxData interface { rawSignatureValues() (v, r, s *big.Int) setSignatureValues(chainID, v, r, s *big.Int) + GetChainID() *big.Int } // EncodeRLP implements rlp.Encoder diff --git a/core/types/tx_access_list.go b/core/types/tx_access_list.go index 620848fe624a..79692bb4206e 100644 --- a/core/types/tx_access_list.go +++ b/core/types/tx_access_list.go @@ -96,6 +96,7 @@ func (tx *AccessListTx) copy() TxData { // accessors for innerTx. func (tx *AccessListTx) txType() byte { return AccessListTxType } func (tx *AccessListTx) chainID() *big.Int { return tx.ChainID } +func (tx *AccessListTx) GetChainID() *big.Int { return tx.ChainID } func (tx *AccessListTx) accessList() AccessList { return tx.AccessList } func (tx *AccessListTx) data() []byte { return tx.Data } func (tx *AccessListTx) gas() uint64 { return tx.Gas } diff --git a/core/types/tx_dynamic_fee.go b/core/types/tx_dynamic_fee.go index 53f246ea1fad..6e1329854adb 100644 --- a/core/types/tx_dynamic_fee.go +++ b/core/types/tx_dynamic_fee.go @@ -84,6 +84,7 @@ func (tx *DynamicFeeTx) copy() TxData { // accessors for innerTx. func (tx *DynamicFeeTx) txType() byte { return DynamicFeeTxType } func (tx *DynamicFeeTx) chainID() *big.Int { return tx.ChainID } +func (tx *DynamicFeeTx) GetChainID() *big.Int { return tx.ChainID } func (tx *DynamicFeeTx) accessList() AccessList { return tx.AccessList } func (tx *DynamicFeeTx) data() []byte { return tx.Data } func (tx *DynamicFeeTx) gas() uint64 { return tx.Gas } diff --git a/core/types/tx_legacy.go b/core/types/tx_legacy.go index 14d307829cc9..0a488431c130 100644 --- a/core/types/tx_legacy.go +++ b/core/types/tx_legacy.go @@ -93,6 +93,7 @@ func (tx *LegacyTx) copy() TxData { // accessors for innerTx. func (tx *LegacyTx) txType() byte { return LegacyTxType } func (tx *LegacyTx) chainID() *big.Int { return deriveChainId(tx.V) } +func (tx *LegacyTx) GetChainID() *big.Int { return deriveChainId(tx.V) } func (tx *LegacyTx) accessList() AccessList { return nil } func (tx *LegacyTx) data() []byte { return tx.Data } func (tx *LegacyTx) gas() uint64 { return tx.Gas } From 85c513b40491f220100823fa9627b70967177119 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Thu, 23 Feb 2023 10:35:50 -0500 Subject: [PATCH 32/40] make access list public --- core/state/access_list.go | 6 +++--- core/state/statedb.go | 4 ++-- core/state/statedb_test.go | 2 +- eth/tracers/logger/access_list_tracer.go | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/core/state/access_list.go b/core/state/access_list.go index 419469134595..ef42e2303631 100644 --- a/core/state/access_list.go +++ b/core/state/access_list.go @@ -47,8 +47,8 @@ func (al *accessList) Contains(address common.Address, slot common.Hash) (addres return true, slotPresent } -// newAccessList creates a new accessList. -func newAccessList() *accessList { +// NewAccessList creates a new accessList. +func NewAccessList() *accessList { return &accessList{ addresses: make(map[common.Address]int), } @@ -56,7 +56,7 @@ func newAccessList() *accessList { // Copy creates an independent copy of an accessList. func (a *accessList) Copy() *accessList { - cp := newAccessList() + cp := NewAccessList() for k, v := range a.addresses { cp.addresses[k] = v } diff --git a/core/state/statedb.go b/core/state/statedb.go index 3d8fd15bbd25..9e3d08ece756 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -145,7 +145,7 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) logs: make(map[common.Hash][]*types.Log), preimages: make(map[common.Hash][]byte), journal: newJournal(), - accessList: newAccessList(), + accessList: NewAccessList(), transientStorage: newTransientStorage(), hasher: crypto.NewKeccakState(), } @@ -1096,7 +1096,7 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) { func (s *StateDB) Prepare(rules params.Rules, sender, coinbase common.Address, dst *common.Address, precompiles []common.Address, list types.AccessList) { if rules.IsBerlin { // Clear out any leftover from previous executions - al := newAccessList() + al := NewAccessList() s.accessList = al al.AddAddress(sender) diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go index 8aa59e3ee592..f8fc4ac20a22 100644 --- a/core/state/statedb_test.go +++ b/core/state/statedb_test.go @@ -763,7 +763,7 @@ func TestStateDBAccessList(t *testing.T) { memDb := rawdb.NewMemoryDatabase() db := NewDatabase(memDb) state, _ := New(common.Hash{}, db, nil) - state.accessList = newAccessList() + state.accessList = NewAccessList() verifyAddrs := func(astrings ...string) { t.Helper() diff --git a/eth/tracers/logger/access_list_tracer.go b/eth/tracers/logger/access_list_tracer.go index 766ee4e4b95c..e4829bf5bba4 100644 --- a/eth/tracers/logger/access_list_tracer.go +++ b/eth/tracers/logger/access_list_tracer.go @@ -32,8 +32,8 @@ type accessList map[common.Address]accessListSlots // contract that an EVM contract execution touches. type accessListSlots map[common.Hash]struct{} -// newAccessList creates a new accessList. -func newAccessList() accessList { +// NewAccessList creates a new accessList. +func NewAccessList() accessList { return make(map[common.Address]accessListSlots) } @@ -117,7 +117,7 @@ func NewAccessListTracer(acl types.AccessList, from, to common.Address, precompi for _, addr := range precompiles { excl[addr] = struct{}{} } - list := newAccessList() + list := NewAccessList() for _, al := range acl { if _, ok := excl[al.Address]; !ok { list.addAddress(al.Address) From becca166a549722bc817ece5bef47c9acb6fb971 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Thu, 23 Feb 2023 10:52:48 -0500 Subject: [PATCH 33/40] make access list struct public --- core/state/access_list.go | 24 ++++++++++++------------ core/state/journal.go | 4 ++-- core/state/statedb.go | 24 ++++++++++++------------ core/state/statedb_test.go | 16 ++++++++-------- 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/core/state/access_list.go b/core/state/access_list.go index ef42e2303631..0a61223b4b75 100644 --- a/core/state/access_list.go +++ b/core/state/access_list.go @@ -20,20 +20,20 @@ import ( "github.com/ethereum/go-ethereum/common" ) -type accessList struct { +type AccessList struct { addresses map[common.Address]int slots []map[common.Hash]struct{} } // ContainsAddress returns true if the address is in the access list. -func (al *accessList) ContainsAddress(address common.Address) bool { +func (al *AccessList) ContainsAddress(address common.Address) bool { _, ok := al.addresses[address] return ok } // Contains checks if a slot within an account is present in the access list, returning // separate flags for the presence of the account and the slot respectively. -func (al *accessList) Contains(address common.Address, slot common.Hash) (addressPresent bool, slotPresent bool) { +func (al *AccessList) Contains(address common.Address, slot common.Hash) (addressPresent bool, slotPresent bool) { idx, ok := al.addresses[address] if !ok { // no such address (and hence zero slots) @@ -47,15 +47,15 @@ func (al *accessList) Contains(address common.Address, slot common.Hash) (addres return true, slotPresent } -// NewAccessList creates a new accessList. -func NewAccessList() *accessList { - return &accessList{ +// NewAccessList creates a new AccessList. +func NewAccessList() *AccessList { + return &AccessList{ addresses: make(map[common.Address]int), } } -// Copy creates an independent copy of an accessList. -func (a *accessList) Copy() *accessList { +// Copy creates an independent copy of an AccessList. +func (a *AccessList) Copy() *AccessList { cp := NewAccessList() for k, v := range a.addresses { cp.addresses[k] = v @@ -73,7 +73,7 @@ func (a *accessList) Copy() *accessList { // AddAddress adds an address to the access list, and returns 'true' if the operation // caused a change (addr was not previously in the list). -func (al *accessList) AddAddress(address common.Address) bool { +func (al *AccessList) AddAddress(address common.Address) bool { if _, present := al.addresses[address]; present { return false } @@ -86,7 +86,7 @@ func (al *accessList) AddAddress(address common.Address) bool { // - address added // - slot added // For any 'true' value returned, a corresponding journal entry must be made. -func (al *accessList) AddSlot(address common.Address, slot common.Hash) (addrChange bool, slotChange bool) { +func (al *AccessList) AddSlot(address common.Address, slot common.Hash) (addrChange bool, slotChange bool) { idx, addrPresent := al.addresses[address] if !addrPresent || idx == -1 { // Address not present, or addr present but no slots there @@ -110,7 +110,7 @@ func (al *accessList) AddSlot(address common.Address, slot common.Hash) (addrCha // This operation needs to be performed in the same order as the addition happened. // This method is meant to be used by the journal, which maintains ordering of // operations. -func (al *accessList) DeleteSlot(address common.Address, slot common.Hash) { +func (al *AccessList) DeleteSlot(address common.Address, slot common.Hash) { idx, addrOk := al.addresses[address] // There are two ways this can fail if !addrOk { @@ -131,6 +131,6 @@ func (al *accessList) DeleteSlot(address common.Address, slot common.Hash) { // needs to be performed in the same order as the addition happened. // This method is meant to be used by the journal, which maintains ordering of // operations. -func (al *accessList) DeleteAddress(address common.Address) { +func (al *AccessList) DeleteAddress(address common.Address) { delete(al.addresses, address) } diff --git a/core/state/journal.go b/core/state/journal.go index 1722fb4c02e1..4e15f9da2b9e 100644 --- a/core/state/journal.go +++ b/core/state/journal.go @@ -266,7 +266,7 @@ func (ch accessListAddAccountChange) revert(s *StateDB) { (addr) at this point, since no storage adds can remain when come upon a single (addr) change. */ - s.accessList.DeleteAddress(*ch.address) + s.AccessList.DeleteAddress(*ch.address) } func (ch accessListAddAccountChange) dirtied() *common.Address { @@ -274,7 +274,7 @@ func (ch accessListAddAccountChange) dirtied() *common.Address { } func (ch accessListAddSlotChange) revert(s *StateDB) { - s.accessList.DeleteSlot(*ch.address, *ch.slot) + s.AccessList.DeleteSlot(*ch.address, *ch.slot) } func (ch accessListAddSlotChange) dirtied() *common.Address { diff --git a/core/state/statedb.go b/core/state/statedb.go index 9e3d08ece756..f6facd712a04 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -96,7 +96,7 @@ type StateDB struct { preimages map[common.Hash][]byte // Per-transaction access list - accessList *accessList + accessList *AccessList // Transient storage transientStorage transientStorage @@ -145,7 +145,7 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) logs: make(map[common.Hash][]*types.Log), preimages: make(map[common.Hash][]byte), journal: newJournal(), - accessList: NewAccessList(), + accessList: NewaccessList(), transientStorage: newTransientStorage(), hasher: crypto.NewKeccakState(), } @@ -1093,10 +1093,10 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) { // - Reset access list (Berlin) // - Add coinbase to access list (EIP-3651) // - Reset transient storage (EIP-1153) -func (s *StateDB) Prepare(rules params.Rules, sender, coinbase common.Address, dst *common.Address, precompiles []common.Address, list types.AccessList) { +func (s *StateDB) Prepare(rules params.Rules, sender, coinbase common.Address, dst *common.Address, precompiles []common.Address, list types.accessList) { if rules.IsBerlin { // Clear out any leftover from previous executions - al := NewAccessList() + al := NewaccessList() s.accessList = al al.AddAddress(sender) @@ -1121,15 +1121,15 @@ func (s *StateDB) Prepare(rules params.Rules, sender, coinbase common.Address, d s.transientStorage = newTransientStorage() } -// AddAddressToAccessList adds the given address to the access list -func (s *StateDB) AddAddressToAccessList(addr common.Address) { +// AddAddressToaccessList adds the given address to the access list +func (s *StateDB) 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) { +// AddSlotToaccessList adds the given (address, slot)-tuple to the access list +func (s *StateDB) 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 @@ -1146,13 +1146,13 @@ 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 { +// AddressInaccessList returns true if the given address is in the access list. +func (s *StateDB) 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) { +// 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) { return s.accessList.Contains(addr, slot) } diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go index f8fc4ac20a22..eaf2c4dc9912 100644 --- a/core/state/statedb_test.go +++ b/core/state/statedb_test.go @@ -763,7 +763,7 @@ func TestStateDBAccessList(t *testing.T) { memDb := rawdb.NewMemoryDatabase() db := NewDatabase(memDb) state, _ := New(common.Hash{}, db, nil) - state.accessList = NewAccessList() + state.AccessList = NewAccessList() verifyAddrs := func(astrings ...string) { t.Helper() @@ -782,7 +782,7 @@ func TestStateDBAccessList(t *testing.T) { } } // Check that only the expected addresses are present in the access list - for address := range state.accessList.addresses { + for address := range state.AccessList.addresses { if _, exist := addressMap[address]; !exist { t.Fatalf("extra address %x in access list", address) } @@ -808,9 +808,9 @@ func TestStateDBAccessList(t *testing.T) { } } // Check that no extra elements are in the access list - index := state.accessList.addresses[address] + index := state.AccessList.addresses[address] if index >= 0 { - stateSlots := state.accessList.slots[index] + stateSlots := state.AccessList.slots[index] for s := range stateSlots { if _, slotPresent := slotMap[s]; !slotPresent { t.Fatalf("scope has extra slot %v (address %v)", s, addrString) @@ -906,10 +906,10 @@ func TestStateDBAccessList(t *testing.T) { if state.AddressInAccessList(addr("aa")) { t.Fatalf("addr present, expected missing") } - if got, exp := len(state.accessList.addresses), 0; got != exp { + if got, exp := len(state.AccessList.addresses), 0; got != exp { t.Fatalf("expected empty, got %d", got) } - if got, exp := len(state.accessList.slots), 0; got != exp { + if got, exp := len(state.AccessList.slots), 0; got != exp { t.Fatalf("expected empty, got %d", got) } // Check the copy @@ -917,10 +917,10 @@ func TestStateDBAccessList(t *testing.T) { state = stateCopy1 verifyAddrs("aa", "bb") verifySlots("bb", "01", "02") - if got, exp := len(state.accessList.addresses), 2; got != exp { + if got, exp := len(state.AccessList.addresses), 2; got != exp { t.Fatalf("expected empty, got %d", got) } - if got, exp := len(state.accessList.slots), 1; got != exp { + if got, exp := len(state.AccessList.slots), 1; got != exp { t.Fatalf("expected empty, got %d", got) } } From 900690c253a147c5f988d5cf5a336eac1747d843 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Thu, 23 Feb 2023 11:24:42 -0500 Subject: [PATCH 34/40] fix typos --- core/state/journal.go | 4 ++-- core/state/statedb.go | 22 +++++++++++----------- core/state/statedb_test.go | 16 ++++++++-------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/core/state/journal.go b/core/state/journal.go index 4e15f9da2b9e..1722fb4c02e1 100644 --- a/core/state/journal.go +++ b/core/state/journal.go @@ -266,7 +266,7 @@ func (ch accessListAddAccountChange) revert(s *StateDB) { (addr) at this point, since no storage adds can remain when come upon a single (addr) change. */ - s.AccessList.DeleteAddress(*ch.address) + s.accessList.DeleteAddress(*ch.address) } func (ch accessListAddAccountChange) dirtied() *common.Address { @@ -274,7 +274,7 @@ func (ch accessListAddAccountChange) dirtied() *common.Address { } func (ch accessListAddSlotChange) revert(s *StateDB) { - s.AccessList.DeleteSlot(*ch.address, *ch.slot) + s.accessList.DeleteSlot(*ch.address, *ch.slot) } func (ch accessListAddSlotChange) dirtied() *common.Address { diff --git a/core/state/statedb.go b/core/state/statedb.go index f6facd712a04..c9e124a30fca 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -145,7 +145,7 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) logs: make(map[common.Hash][]*types.Log), preimages: make(map[common.Hash][]byte), journal: newJournal(), - accessList: NewaccessList(), + accessList: NewAccessList(), transientStorage: newTransientStorage(), hasher: crypto.NewKeccakState(), } @@ -1093,10 +1093,10 @@ func (s *StateDB) Commit(deleteEmptyObjects bool) (common.Hash, error) { // - Reset access list (Berlin) // - Add coinbase to access list (EIP-3651) // - Reset transient storage (EIP-1153) -func (s *StateDB) Prepare(rules params.Rules, sender, coinbase common.Address, dst *common.Address, precompiles []common.Address, list types.accessList) { +func (s *StateDB) Prepare(rules params.Rules, sender, coinbase common.Address, dst *common.Address, precompiles []common.Address, list types.AccessList) { if rules.IsBerlin { // Clear out any leftover from previous executions - al := NewaccessList() + al := NewAccessList() s.accessList = al al.AddAddress(sender) @@ -1121,15 +1121,15 @@ func (s *StateDB) Prepare(rules params.Rules, sender, coinbase common.Address, d s.transientStorage = newTransientStorage() } -// AddAddressToaccessList adds the given address to the access list -func (s *StateDB) AddAddressToaccessList(addr common.Address) { +// AddAddressToAccessList adds the given address to the access list +func (s *StateDB) 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) { +// AddSlotToAccessList adds the given (address, slot)-tuple to the access list +func (s *StateDB) 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 @@ -1146,13 +1146,13 @@ 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 { +// AddressInAccessList returns true if the given address is in the access list. +func (s *StateDB) 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) { +// 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) { return s.accessList.Contains(addr, slot) } diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go index eaf2c4dc9912..f8fc4ac20a22 100644 --- a/core/state/statedb_test.go +++ b/core/state/statedb_test.go @@ -763,7 +763,7 @@ func TestStateDBAccessList(t *testing.T) { memDb := rawdb.NewMemoryDatabase() db := NewDatabase(memDb) state, _ := New(common.Hash{}, db, nil) - state.AccessList = NewAccessList() + state.accessList = NewAccessList() verifyAddrs := func(astrings ...string) { t.Helper() @@ -782,7 +782,7 @@ func TestStateDBAccessList(t *testing.T) { } } // Check that only the expected addresses are present in the access list - for address := range state.AccessList.addresses { + for address := range state.accessList.addresses { if _, exist := addressMap[address]; !exist { t.Fatalf("extra address %x in access list", address) } @@ -808,9 +808,9 @@ func TestStateDBAccessList(t *testing.T) { } } // Check that no extra elements are in the access list - index := state.AccessList.addresses[address] + index := state.accessList.addresses[address] if index >= 0 { - stateSlots := state.AccessList.slots[index] + stateSlots := state.accessList.slots[index] for s := range stateSlots { if _, slotPresent := slotMap[s]; !slotPresent { t.Fatalf("scope has extra slot %v (address %v)", s, addrString) @@ -906,10 +906,10 @@ func TestStateDBAccessList(t *testing.T) { if state.AddressInAccessList(addr("aa")) { t.Fatalf("addr present, expected missing") } - if got, exp := len(state.AccessList.addresses), 0; got != exp { + if got, exp := len(state.accessList.addresses), 0; got != exp { t.Fatalf("expected empty, got %d", got) } - if got, exp := len(state.AccessList.slots), 0; got != exp { + if got, exp := len(state.accessList.slots), 0; got != exp { t.Fatalf("expected empty, got %d", got) } // Check the copy @@ -917,10 +917,10 @@ func TestStateDBAccessList(t *testing.T) { state = stateCopy1 verifyAddrs("aa", "bb") verifySlots("bb", "01", "02") - if got, exp := len(state.AccessList.addresses), 2; got != exp { + if got, exp := len(state.accessList.addresses), 2; got != exp { t.Fatalf("expected empty, got %d", got) } - if got, exp := len(state.AccessList.slots), 1; got != exp { + if got, exp := len(state.accessList.slots), 1; got != exp { t.Fatalf("expected empty, got %d", got) } } From 86a96c543ecff8c3ebf0f1714076bc0aeff9da95 Mon Sep 17 00:00:00 2001 From: Devon Bear Date: Thu, 23 Feb 2023 14:08:04 -0500 Subject: [PATCH 35/40] ethpub --- core/types/transaction_signing.go | 81 +++++++++++++++++++++++++++++-- ethclient/signer.go | 5 ++ 2 files changed, 81 insertions(+), 5 deletions(-) diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go index 87f0390a6f9c..3e232fd84a66 100644 --- a/core/types/transaction_signing.go +++ b/core/types/transaction_signing.go @@ -157,6 +157,9 @@ type Signer interface { // Sender returns the sender address of the transaction. Sender(tx *Transaction) (common.Address, error) + // PubKey returns the public key of the sender. + PubKey(tx *Transaction) ([]byte, error) + // SignatureValues returns the raw R, S, V values corresponding to the // given signature. SignatureValues(tx *Transaction, sig []byte) (r, s, v *big.Int, err error) @@ -195,6 +198,20 @@ func (s londonSigner) Sender(tx *Transaction) (common.Address, error) { return recoverPlain(s.Hash(tx), R, S, V, true) } +func (s londonSigner) PubKey(tx *Transaction) ([]byte, error) { + if tx.Type() != DynamicFeeTxType { + return s.eip2930Signer.PubKey(tx) + } + V, R, S := tx.RawSignatureValues() + // DynamicFee txs are defined to use 0 and 1 as their recovery + // id, add 27 to become equivalent to unprotected Homestead signatures. + V = new(big.Int).Add(V, big.NewInt(27)) + if tx.ChainId().Cmp(s.chainId) != 0 { + return nil, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, tx.ChainId(), s.chainId) + } + return recoverPub(s.Hash(tx), R, S, V, true) +} + func (s londonSigner) Equal(s2 Signer) bool { x, ok := s2.(londonSigner) return ok && x.chainId.Cmp(s.chainId) == 0 @@ -275,6 +292,28 @@ func (s eip2930Signer) Sender(tx *Transaction) (common.Address, error) { return recoverPlain(s.Hash(tx), R, S, V, true) } +func (s eip2930Signer) PubKey(tx *Transaction) ([]byte, error) { + V, R, S := tx.RawSignatureValues() + switch tx.Type() { + case LegacyTxType: + if !tx.Protected() { + return HomesteadSigner{}.PubKey(tx) + } + V = new(big.Int).Sub(V, s.chainIdMul) + V.Sub(V, big8) + case AccessListTxType: + // AL txs are defined to use 0 and 1 as their recovery + // id, add 27 to become equivalent to unprotected Homestead signatures. + V = new(big.Int).Add(V, big.NewInt(27)) + default: + return nil, ErrTxTypeNotSupported + } + if tx.ChainId().Cmp(s.chainId) != 0 { + return nil, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, tx.ChainId(), s.chainId) + } + return recoverPub(s.Hash(tx), R, S, V, true) +} + func (s eip2930Signer) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big.Int, err error) { switch txdata := tx.inner.(type) { case *LegacyTx: @@ -372,6 +411,22 @@ func (s EIP155Signer) Sender(tx *Transaction) (common.Address, error) { return recoverPlain(s.Hash(tx), R, S, V, true) } +func (s EIP155Signer) PubKey(tx *Transaction) ([]byte, error) { + if tx.Type() != LegacyTxType { + return nil, ErrTxTypeNotSupported + } + if !tx.Protected() { + return HomesteadSigner{}.PubKey(tx) + } + if tx.ChainId().Cmp(s.chainId) != 0 { + return nil, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, tx.ChainId(), s.chainId) + } + V, R, S := tx.RawSignatureValues() + V = new(big.Int).Sub(V, s.chainIdMul) + V.Sub(V, big8) + return recoverPub(s.Hash(tx), R, S, V, true) +} + // SignatureValues returns signature values. This signature // needs to be in the [R || S || V] format where V is 0 or 1. func (s EIP155Signer) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big.Int, err error) { @@ -448,6 +503,14 @@ func (fs FrontierSigner) Sender(tx *Transaction) (common.Address, error) { return recoverPlain(fs.Hash(tx), r, s, v, false) } +func (fs FrontierSigner) PubKey(tx *Transaction) ([]byte, error) { + if tx.Type() != LegacyTxType { + return nil, ErrTxTypeNotSupported + } + v, r, s := tx.RawSignatureValues() + return recoverPub(fs.Hash(tx), r, s, v, false) +} + // SignatureValues returns signature values. This signature // needs to be in the [R || S || V] format where V is 0 or 1. func (fs FrontierSigner) SignatureValues(tx *Transaction, sig []byte) (r, s, v *big.Int, err error) { @@ -481,13 +544,13 @@ func decodeSignature(sig []byte) (r, s, v *big.Int) { return r, s, v } -func recoverPlain(sighash common.Hash, R, S, Vb *big.Int, homestead bool) (common.Address, error) { +func recoverPub(sighash common.Hash, R, S, Vb *big.Int, homestead bool) ([]byte, error) { if Vb.BitLen() > 8 { - return common.Address{}, ErrInvalidSig + return nil, ErrInvalidSig } V := byte(Vb.Uint64() - 27) if !crypto.ValidateSignatureValues(V, R, S, homestead) { - return common.Address{}, ErrInvalidSig + return nil, ErrInvalidSig } // encode the signature in uncompressed format r, s := R.Bytes(), S.Bytes() @@ -498,10 +561,18 @@ func recoverPlain(sighash common.Hash, R, S, Vb *big.Int, homestead bool) (commo // recover the public key from the signature pub, err := crypto.Ecrecover(sighash[:], sig) if err != nil { - return common.Address{}, err + return nil, err } if len(pub) == 0 || pub[0] != 4 { - return common.Address{}, errors.New("invalid public key") + return nil, errors.New("invalid public key") + } + return pub, nil +} + +func recoverPlain(sighash common.Hash, R, S, Vb *big.Int, homestead bool) (common.Address, error) { + pub, err := recoverPub(sighash, R, S, Vb, homestead) + if err != nil { + return common.Address{}, err } var addr common.Address copy(addr[:], crypto.Keccak256(pub[1:])[12:]) diff --git a/ethclient/signer.go b/ethclient/signer.go index f827d4eb56f4..8df14a5755de 100644 --- a/ethclient/signer.go +++ b/ethclient/signer.go @@ -51,6 +51,11 @@ func (s *senderFromServer) Sender(tx *types.Transaction) (common.Address, error) return s.addr, nil } +func (s *senderFromServer) PubKey(tx *types.Transaction) ([]byte, error) { + // not implemented + return nil, nil +} + func (s *senderFromServer) ChainID() *big.Int { panic("can't sign with senderFromServer") } From 9fdaf4f0091aeb42e4079f26d017c6feeac707cf Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Thu, 23 Feb 2023 16:48:05 -0500 Subject: [PATCH 36/40] use the StateDB interface in the API --- core/state/interface.go | 93 +++++++++++++++++++++++++++++++++ core/state/statedb.go | 2 +- core/state/statedb_test.go | 10 ++-- core/vm/interface.go | 58 +------------------- eth/tracers/api.go | 6 +-- ethapi/api.go | 3 +- ethapi/backend.go | 7 ++- ethapi/transaction_args_test.go | 6 +-- 8 files changed, 111 insertions(+), 74 deletions(-) create mode 100644 core/state/interface.go diff --git a/core/state/interface.go b/core/state/interface.go new file mode 100644 index 000000000000..2b04a2f747e6 --- /dev/null +++ b/core/state/interface.go @@ -0,0 +1,93 @@ +// Copyright 2014 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 state provides a caching layer atop the Ethereum state trie. + +package state + +import ( + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" +) + +// StateDBI is an EVM database for full state querying. +type StateDBI interface { + CreateAccount(common.Address) + + SubBalance(common.Address, *big.Int) + AddBalance(common.Address, *big.Int) + GetBalance(common.Address) *big.Int + + GetNonce(common.Address) uint64 + SetNonce(common.Address, uint64) + + GetCodeHash(common.Address) common.Hash + GetCode(common.Address) []byte + SetCode(common.Address, []byte) + GetCodeSize(common.Address) int + + AddRefund(uint64) + SubRefund(uint64) + GetRefund() uint64 + + GetCommittedState(common.Address, common.Hash) common.Hash + GetState(common.Address, common.Hash) common.Hash + SetState(common.Address, common.Hash, common.Hash) + + GetTransientState(addr common.Address, key common.Hash) common.Hash + SetTransientState(addr common.Address, key, value common.Hash) + + Suicide(common.Address) bool + HasSuicided(common.Address) bool + + // Exist reports whether the given account exists in state. + // Notably this should also return true for suicided accounts. + Exist(common.Address) bool + // Empty returns whether the given account is empty. Empty + // is defined according to EIP161 (balance = nonce = code = 0). + Empty(common.Address) bool + + AddressInAccessList(addr common.Address) bool + SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool) + // AddAddressToAccessList adds the given address to the access list. This operation is safe to perform + // even if the feature/fork is not active yet + AddAddressToAccessList(addr common.Address) + // AddSlotToAccessList adds the given (address,slot) to the access list. This operation is safe to perform + // even if the feature/fork is not active yet + AddSlotToAccessList(addr common.Address, slot common.Hash) + Prepare(rules params.Rules, sender, coinbase common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList) + + RevertToSnapshot(int) + Snapshot() int + + AddLog(*types.Log) + AddPreimage(common.Hash, []byte) + + ForEachStorage(common.Address, func(common.Hash, common.Hash) bool) error + + StorageTrie(addr common.Address) (Trie, error) + Error() error + GetStorageProof(a common.Address, key common.Hash) ([][]byte, error) + GetProof(addr common.Address) ([][]byte, error) + SetBalance(addr common.Address, amount *big.Int) + SetStorage(addr common.Address, storage map[common.Hash]common.Hash) + Finalise(deleteEmptyObjects bool) + Copy() StateDBI + SetTxContext(thash common.Hash, ti int) +} diff --git a/core/state/statedb.go b/core/state/statedb.go index c9e124a30fca..2c7d767a7b46 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -694,7 +694,7 @@ 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 *StateDB) Copy() StateDBI { // Copy all the basic fields, initialize the memory ones state := &StateDB{ db: s.db, diff --git a/core/state/statedb_test.go b/core/state/statedb_test.go index f8fc4ac20a22..b25976815a22 100644 --- a/core/state/statedb_test.go +++ b/core/state/statedb_test.go @@ -159,10 +159,10 @@ func TestCopy(t *testing.T) { orig.Finalise(false) // Copy the state - copy := orig.Copy() + copy := orig.Copy().(*StateDB) // Copy the copy state - ccopy := copy.Copy() + ccopy := copy.Copy().(*StateDB) // modify all in memory for i := byte(0); i < 255; i++ { @@ -542,7 +542,7 @@ func TestCopyCommitCopy(t *testing.T) { t.Fatalf("initial committed storage slot mismatch: have %x, want %x", val, common.Hash{}) } // Copy the non-committed state database and check pre/post commit balance - copyOne := state.Copy() + copyOne := state.Copy().(*StateDB) if balance := copyOne.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { t.Fatalf("first copy pre-commit balance mismatch: have %v, want %v", balance, 42) } @@ -628,7 +628,7 @@ func TestCopyCopyCommitCopy(t *testing.T) { t.Fatalf("first copy committed storage slot mismatch: have %x, want %x", val, common.Hash{}) } // Copy the copy and check the balance once more - copyTwo := copyOne.Copy() + copyTwo := copyOne.Copy().(*StateDB) if balance := copyTwo.GetBalance(addr); balance.Cmp(big.NewInt(42)) != 0 { t.Fatalf("second copy pre-commit balance mismatch: have %v, want %v", balance, 42) } @@ -914,7 +914,7 @@ func TestStateDBAccessList(t *testing.T) { } // Check the copy // Make a copy - state = stateCopy1 + state = stateCopy1.(*StateDB) verifyAddrs("aa", "bb") verifySlots("bb", "01", "02") if got, exp := len(state.accessList.addresses), 2; got != exp { diff --git a/core/vm/interface.go b/core/vm/interface.go index 0ee32b1dd510..24ee2c04ffbd 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -20,65 +20,11 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/core/state" ) // StateDB is an EVM database for full state querying. -type StateDB interface { - CreateAccount(common.Address) - - SubBalance(common.Address, *big.Int) - AddBalance(common.Address, *big.Int) - GetBalance(common.Address) *big.Int - - GetNonce(common.Address) uint64 - SetNonce(common.Address, uint64) - - GetCodeHash(common.Address) common.Hash - GetCode(common.Address) []byte - SetCode(common.Address, []byte) - GetCodeSize(common.Address) int - - AddRefund(uint64) - SubRefund(uint64) - GetRefund() uint64 - - GetCommittedState(common.Address, common.Hash) common.Hash - GetState(common.Address, common.Hash) common.Hash - SetState(common.Address, common.Hash, common.Hash) - - GetTransientState(addr common.Address, key common.Hash) common.Hash - SetTransientState(addr common.Address, key, value common.Hash) - - Suicide(common.Address) bool - HasSuicided(common.Address) bool - - // Exist reports whether the given account exists in state. - // Notably this should also return true for suicided accounts. - Exist(common.Address) bool - // Empty returns whether the given account is empty. Empty - // is defined according to EIP161 (balance = nonce = code = 0). - Empty(common.Address) bool - - AddressInAccessList(addr common.Address) bool - SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool) - // AddAddressToAccessList adds the given address to the access list. This operation is safe to perform - // even if the feature/fork is not active yet - AddAddressToAccessList(addr common.Address) - // AddSlotToAccessList adds the given (address,slot) to the access list. This operation is safe to perform - // even if the feature/fork is not active yet - AddSlotToAccessList(addr common.Address, slot common.Hash) - Prepare(rules params.Rules, sender, coinbase common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList) - - RevertToSnapshot(int) - Snapshot() int - - AddLog(*types.Log) - AddPreimage(common.Hash, []byte) - - ForEachStorage(common.Address, func(common.Hash, common.Hash) bool) error -} +type StateDB = state.StateDBI // CallContext provides a basic interface for the EVM calling conventions. The EVM // depends on this context being implemented for doing subcalls and initialising new EVM contracts. diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 6dca581ed74c..4814b0066663 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -207,7 +207,7 @@ type txTraceResult struct { // blockTraceTask represents a single block trace task when an entire chain is // being traced. type blockTraceTask struct { - statedb *state.StateDB // Intermediate state prepped for tracing + statedb state.StateDBI // Intermediate state prepped for tracing block *types.Block // Block to trace the transactions from release StateReleaseFunc // The function to release the held resource for this task results []*txTraceResult // Trace results produced by the task @@ -224,7 +224,7 @@ type blockTraceResult struct { // txTraceTask represents a single transaction trace task when an entire block // is being traced. type txTraceTask struct { - statedb *state.StateDB // Intermediate state prepped for tracing + statedb state.StateDBI // Intermediate state prepped for tracing index int // Transaction offset in the block } @@ -943,7 +943,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc // traceTx configures a new tracer according to the provided configuration, and // executes the given message in the provided environment. The return value will // be tracer dependent. -func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) { +func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Context, vmctx vm.BlockContext, statedb state.StateDBI, config *TraceConfig) (interface{}, error) { var ( tracer Tracer err error diff --git a/ethapi/api.go b/ethapi/api.go index 58f65f86d794..904f776393b5 100644 --- a/ethapi/api.go +++ b/ethapi/api.go @@ -36,7 +36,6 @@ import ( "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" @@ -878,7 +877,7 @@ type OverrideAccount struct { type StateOverride map[common.Address]OverrideAccount // Apply overrides the fields of specified accounts into the given state. -func (diff *StateOverride) Apply(state *state.StateDB) error { +func (diff *StateOverride) Apply(state vm.StateDB) error { if diff == nil { return nil } diff --git a/ethapi/backend.go b/ethapi/backend.go index 0c1763472f2d..d7e4f7e48a03 100644 --- a/ethapi/backend.go +++ b/ethapi/backend.go @@ -28,7 +28,6 @@ import ( "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/bloombits" - "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/ethdb" @@ -63,12 +62,12 @@ type Backend interface { BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) - StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) - StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) + StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (vm.StateDB, *types.Header, error) + StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (vm.StateDB, *types.Header, error) PendingBlockAndReceipts() (*types.Block, types.Receipts) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) GetTd(ctx context.Context, hash common.Hash) *big.Int - GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) + GetEVM(ctx context.Context, msg core.Message, state vm.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription diff --git a/ethapi/transaction_args_test.go b/ethapi/transaction_args_test.go index a8f2d5214889..773b0377bde0 100644 --- a/ethapi/transaction_args_test.go +++ b/ethapi/transaction_args_test.go @@ -291,10 +291,10 @@ func (b *backendMock) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc func (b *backendMock) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) { return nil, nil } -func (b *backendMock) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { +func (b *backendMock) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (state.StateDBI, *types.Header, error) { return nil, nil, nil } -func (b *backendMock) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { +func (b *backendMock) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (state.StateDBI, *types.Header, error) { return nil, nil, nil } func (b *backendMock) PendingBlockAndReceipts() (*types.Block, types.Receipts) { return nil, nil } @@ -305,7 +305,7 @@ func (b *backendMock) GetLogs(ctx context.Context, blockHash common.Hash, number return nil, nil } func (b *backendMock) GetTd(ctx context.Context, hash common.Hash) *big.Int { return nil } -func (b *backendMock) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { +func (b *backendMock) GetEVM(ctx context.Context, msg core.Message, state state.StateDBI, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { return nil, nil, nil } func (b *backendMock) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { return nil } From 991a1772ebf7835dbaa109500e2bb521164fd531 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Fri, 24 Feb 2023 12:00:58 -0500 Subject: [PATCH 37/40] make compatible --- accounts/abi/bind/backends/simulated.go | 6 +- cmd/evm/internal/t8ntool/execution.go | 4 +- cmd/evm/runner.go | 2 +- consensus/beacon/consensus.go | 4 +- consensus/clique/clique.go | 4 +- consensus/consensus.go | 4 +- consensus/ethash/consensus.go | 6 +- consensus/misc/dao.go | 2 +- core/block_validator.go | 2 +- core/blockchain.go | 10 +- core/blockchain_reader.go | 4 +- core/chain_makers.go | 6 +- core/state/interface.go | 15 +++ core/state/journal.go | 2 +- core/state/state_object.go | 90 ++++++------- core/state/state_test.go | 2 +- core/state/statedb.go | 134 ++++++++++---------- core/state_prefetcher.go | 4 +- core/state_processor.go | 6 +- core/txpool/noncer.go | 4 +- core/txpool/txpool.go | 4 +- core/txpool/txpool_test.go | 6 +- core/types.go | 6 +- core/vm/instructions_test.go | 2 +- core/vm/runtime/runtime.go | 4 +- eth/api.go | 2 +- eth/api_backend.go | 10 +- eth/api_test.go | 2 +- eth/state_accessor.go | 4 +- eth/tracers/api.go | 8 +- eth/tracers/api_test.go | 4 +- graphql/graphql.go | 2 +- les/api_backend.go | 10 +- les/odr_test.go | 2 +- les/state_accessor.go | 4 +- light/odr_test.go | 4 +- light/trie.go | 2 +- light/txpool.go | 2 +- miner/miner.go | 2 +- miner/miner_test.go | 6 +- miner/worker.go | 8 +- miner/worker_test.go | 2 +- tests/block_test_util.go | 2 +- tests/fuzzers/bls12381/precompile_fuzzer.go | 3 +- tests/state_test_util.go | 6 +- 45 files changed, 217 insertions(+), 201 deletions(-) diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 008c71feaa7a..91709100c412 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -65,7 +65,7 @@ type SimulatedBackend struct { mu sync.Mutex pendingBlock *types.Block // Currently pending block that will be imported on request - pendingState *state.StateDB // Currently pending state that will be the active on request + pendingState state.StateDBI // Currently pending state that will be the active on request pendingReceipts types.Receipts // Currently receipts for the pending block events *filters.EventSystem // for filtering log events live @@ -173,7 +173,7 @@ func (b *SimulatedBackend) Fork(ctx context.Context, parent common.Hash) error { } // stateByBlockNumber retrieves a state by a given blocknumber. -func (b *SimulatedBackend) stateByBlockNumber(ctx context.Context, blockNumber *big.Int) (*state.StateDB, error) { +func (b *SimulatedBackend) stateByBlockNumber(ctx context.Context, blockNumber *big.Int) (state.StateDBI, error) { if blockNumber == nil || blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) == 0 { return b.blockchain.State() } @@ -599,7 +599,7 @@ func (b *SimulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMs // callContract implements common code between normal and pending contract calls. // state is modified during execution, make sure to copy it if necessary. -func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Block, stateDB *state.StateDB) (*core.ExecutionResult, error) { +func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallMsg, block *types.Block, stateDB state.StateDBI) (*core.ExecutionResult, error) { // Gas prices post 1559 need to be initialized if call.GasPrice != nil && (call.GasFeeCap != nil || call.GasTipCap != nil) { return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified") diff --git a/cmd/evm/internal/t8ntool/execution.go b/cmd/evm/internal/t8ntool/execution.go index 2c68659945eb..66dc65c566bf 100644 --- a/cmd/evm/internal/t8ntool/execution.go +++ b/cmd/evm/internal/t8ntool/execution.go @@ -108,7 +108,7 @@ type rejectedTx struct { // Apply applies a set of transactions to a pre-state func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, txs types.Transactions, miningReward int64, - getTracerFn func(txIndex int, txHash common.Hash) (tracer vm.EVMLogger, err error)) (*state.StateDB, *ExecutionResult, error) { + getTracerFn func(txIndex int, txHash common.Hash) (tracer vm.EVMLogger, err error)) (state.StateDBI, *ExecutionResult, error) { // Capture errors for BLOCKHASH operation, if we haven't been supplied the // required blockhashes var hashError error @@ -287,7 +287,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig, return statedb, execRs, nil } -func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) *state.StateDB { +func MakePreState(db ethdb.Database, accounts core.GenesisAlloc) state.StateDBI { sdb := state.NewDatabaseWithConfig(db, &trie.Config{Preimages: true}) statedb, _ := state.New(common.Hash{}, sdb, nil) for addr, a := range accounts { diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go index 3a010da9f2dc..ce84f0cc28de 100644 --- a/cmd/evm/runner.go +++ b/cmd/evm/runner.go @@ -120,7 +120,7 @@ func runCmd(ctx *cli.Context) error { var ( tracer vm.EVMLogger debugLogger *logger.StructLogger - statedb *state.StateDB + statedb state.StateDBI chainConfig *params.ChainConfig sender = common.BytesToAddress([]byte("sender")) receiver = common.BytesToAddress([]byte("receiver")) diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index eb5aa58ca887..0a59c296dd8a 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -327,7 +327,7 @@ func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.H } // Finalize implements consensus.Engine, setting the final state on the header -func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { +func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state state.StateDBI, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { // Finalize is different with Prepare, it can be used in both block generation // and verification. So determine the consensus rules by header type. if !beacon.IsPoSHeader(header) { @@ -348,7 +348,7 @@ func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types. // FinalizeAndAssemble implements consensus.Engine, setting the final state and // assembling the block. -func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { +func (beacon *Beacon) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state state.StateDBI, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { // FinalizeAndAssemble is different with Prepare, it can be used in both block // generation and verification. So determine the consensus rules by header type. if !beacon.IsPoSHeader(header) { diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 4706bbac1ca9..e25fa2d869c4 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -567,7 +567,7 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header // Finalize implements consensus.Engine, ensuring no uncles are set, nor block // rewards given. -func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { +func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state state.StateDBI, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { // No block rewards in PoA, so the state remains as is and uncles are dropped header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) header.UncleHash = types.CalcUncleHash(nil) @@ -575,7 +575,7 @@ func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Heade // FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, // nor block rewards given, and returns the final block. -func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { +func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state state.StateDBI, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { if len(withdrawals) > 0 { return nil, errors.New("clique does not support withdrawals") } diff --git a/consensus/consensus.go b/consensus/consensus.go index 190d5ae12c8a..31cf037aaf36 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -89,7 +89,7 @@ type Engine interface { // // Note: The block header and state database might be updated to reflect any // consensus rules that happen at finalization (e.g. block rewards). - Finalize(chain ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, + Finalize(chain ChainHeaderReader, header *types.Header, state state.StateDBI, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) // FinalizeAndAssemble runs any post-transaction state modifications (e.g. block @@ -97,7 +97,7 @@ type Engine interface { // // Note: The block header and state database might be updated to reflect any // consensus rules that happen at finalization (e.g. block rewards). - FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, + FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state state.StateDBI, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) // Seal generates a new sealing request for the given input block and pushes diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index da29e16597b6..705756a9f617 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -600,7 +600,7 @@ func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.H // Finalize implements consensus.Engine, accumulating the block and uncle rewards, // setting the final state on the header -func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { +func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state state.StateDBI, txs []*types.Transaction, uncles []*types.Header, withdrawals []*types.Withdrawal) { // Accumulate any block and uncle rewards and commit the final state root accumulateRewards(chain.Config(), state, header, uncles) header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) @@ -608,7 +608,7 @@ func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types. // FinalizeAndAssemble implements consensus.Engine, accumulating the block and // uncle rewards, setting the final state and assembling the block. -func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { +func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state state.StateDBI, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, withdrawals []*types.Withdrawal) (*types.Block, error) { if len(withdrawals) > 0 { return nil, errors.New("ethash does not support withdrawals") } @@ -658,7 +658,7 @@ var ( // AccumulateRewards credits the coinbase of the given block with the mining // reward. The total reward consists of the static block reward and rewards for // included uncles. The coinbase of each uncle block is also rewarded. -func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) { +func accumulateRewards(config *params.ChainConfig, state state.StateDBI, header *types.Header, uncles []*types.Header) { // Select the correct block reward based on chain progression blockReward := FrontierBlockReward if config.IsByzantium(header.Number) { diff --git a/consensus/misc/dao.go b/consensus/misc/dao.go index 96995616de56..d436303c983e 100644 --- a/consensus/misc/dao.go +++ b/consensus/misc/dao.go @@ -72,7 +72,7 @@ func VerifyDAOHeaderExtraData(config *params.ChainConfig, header *types.Header) // ApplyDAOHardFork modifies the state database according to the DAO hard-fork // rules, transferring all balances of a set of DAO accounts to a single refund // contract. -func ApplyDAOHardFork(statedb *state.StateDB) { +func ApplyDAOHardFork(statedb state.StateDBI) { // Retrieve the contract to refund balances into if !statedb.Exist(params.DAORefundContract) { statedb.CreateAccount(params.DAORefundContract) diff --git a/core/block_validator.go b/core/block_validator.go index db7ea3568723..a79d1db978cf 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -94,7 +94,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { // transition, such as amount of used gas, the receipt roots and the state root // itself. ValidateState returns a database batch if the validation was a success // otherwise nil and an error is returned. -func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error { +func (v *BlockValidator) ValidateState(block *types.Block, statedb state.StateDBI, receipts types.Receipts, usedGas uint64) error { header := block.Header() if block.GasUsed() != usedGas { return fmt.Errorf("invalid gas used (remote: %d local: %d)", block.GasUsed(), usedGas) diff --git a/core/blockchain.go b/core/blockchain.go index 38a129d4eec5..f9ae9bd5499e 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1315,7 +1315,7 @@ func (bc *BlockChain) writeKnownBlock(block *types.Block) error { // writeBlockWithState writes block, metadata and corresponding state data to the // database. -func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.Receipt, state *state.StateDB) error { +func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.Receipt, state state.StateDBI) error { // Calculate the total difficulty of the block ptd := bc.GetTd(block.ParentHash(), block.NumberU64()-1) if ptd == nil { @@ -1398,7 +1398,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. // WriteBlockAndSetHead writes the given block and all associated state to the database, // and applies the block as the new chain head. -func (bc *BlockChain) WriteBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) { +func (bc *BlockChain) WriteBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state state.StateDBI, emitHeadEvent bool) (status WriteStatus, err error) { if !bc.chainmu.TryLock() { return NonStatTy, errChainStopped } @@ -1409,7 +1409,7 @@ func (bc *BlockChain) WriteBlockAndSetHead(block *types.Block, receipts []*types // writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead. // This function expects the chain mutex to be held. -func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, emitHeadEvent bool) (status WriteStatus, err error) { +func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state state.StateDBI, emitHeadEvent bool) (status WriteStatus, err error) { if err := bc.writeBlockWithState(block, receipts, state); err != nil { return NonStatTy, err } @@ -1638,7 +1638,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool) return it.index, err } // No validation errors for the first block (or chain prefix skipped) - var activeState *state.StateDB + var activeState state.StateDBI defer func() { // The chain importer is starting and stopping trie prefetchers. If a bad // block or other error is hit however, an early return may not properly @@ -1722,7 +1722,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool) if followup, err := it.peek(); followup != nil && err == nil { throwaway, _ := state.New(parent.Root, bc.stateCache, bc.snaps) - go func(start time.Time, followup *types.Block, throwaway *state.StateDB, interrupt *uint32) { + go func(start time.Time, followup *types.Block, throwaway state.StateDBI, interrupt *uint32) { bc.prefetcher.Prefetch(followup, throwaway, bc.vmConfig, &followupInterrupt) blockPrefetchExecuteTimer.Update(time.Since(start)) diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index e8a5d952a240..0d8000ac125a 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -314,12 +314,12 @@ func (bc *BlockChain) ContractCodeWithPrefix(hash common.Hash) ([]byte, error) { } // State returns a new mutable state based on the current HEAD block. -func (bc *BlockChain) State() (*state.StateDB, error) { +func (bc *BlockChain) State() (state.StateDBI, error) { return bc.StateAt(bc.CurrentBlock().Root()) } // StateAt returns a new mutable state based on a particular point in time. -func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) { +func (bc *BlockChain) StateAt(root common.Hash) (state.StateDBI, error) { return state.New(root, bc.stateCache, bc.snaps) } diff --git a/core/chain_makers.go b/core/chain_makers.go index 3518929f8e71..5e71b28111d9 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -39,7 +39,7 @@ type BlockGen struct { parent *types.Block chain []*types.Block header *types.Header - statedb *state.StateDB + statedb state.StateDBI gasPool *GasPool txs []*types.Transaction @@ -269,7 +269,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse } blocks, receipts := make(types.Blocks, n), make([]types.Receipts, n) chainreader := &fakeChainReader{config: config} - genblock := func(i int, parent *types.Block, statedb *state.StateDB) (*types.Block, types.Receipts) { + genblock := func(i int, parent *types.Block, statedb state.StateDBI) (*types.Block, types.Receipts) { b := &BlockGen{i: i, chain: blocks, parent: parent, statedb: statedb, config: config, engine: engine} b.header = makeHeader(chainreader, parent, statedb, b.engine) @@ -345,7 +345,7 @@ func GenerateChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, return db, blocks, receipts } -func makeHeader(chain consensus.ChainReader, parent *types.Block, state *state.StateDB, engine consensus.Engine) *types.Header { +func makeHeader(chain consensus.ChainReader, parent *types.Block, state state.StateDBI, engine consensus.Engine) *types.Header { var time uint64 if parent.Time() == 0 { time = 10 diff --git a/core/state/interface.go b/core/state/interface.go index 2b04a2f747e6..0f8b797344d2 100644 --- a/core/state/interface.go +++ b/core/state/interface.go @@ -77,10 +77,21 @@ type StateDBI interface { Snapshot() int AddLog(*types.Log) + Logs() []*types.Log + GetLogs(hash common.Hash, blockNumber uint64, blockHash common.Hash) []*types.Log + TxIndex() int AddPreimage(common.Hash, []byte) + Preimages() map[common.Hash][]byte ForEachStorage(common.Address, func(common.Hash, common.Hash) bool) error + GetOrNewStateObject(addr common.Address) *StateObject + + DumpToCollector(c DumpCollector, conf *DumpConfig) (nextKey []byte) + Dump(opts *DumpConfig) []byte + RawDump(opts *DumpConfig) Dump + IteratorDump(opts *DumpConfig) IteratorDump + Database() Database StorageTrie(addr common.Address) (Trie, error) Error() error GetStorageProof(a common.Address, key common.Hash) ([][]byte, error) @@ -88,6 +99,10 @@ type StateDBI interface { SetBalance(addr common.Address, amount *big.Int) SetStorage(addr common.Address, storage map[common.Hash]common.Hash) Finalise(deleteEmptyObjects bool) + Commit(deleteEmptyObjects bool) (common.Hash, error) Copy() StateDBI SetTxContext(thash common.Hash, ti int) + StopPrefetcher() + StartPrefetcher(namespace string) + IntermediateRoot(deleteEmptyObjects bool) common.Hash } diff --git a/core/state/journal.go b/core/state/journal.go index 1722fb4c02e1..5feb6bb05c61 100644 --- a/core/state/journal.go +++ b/core/state/journal.go @@ -90,7 +90,7 @@ type ( account *common.Address } resetObjectChange struct { - prev *stateObject + prev *StateObject prevdestruct bool } suicideChange struct { diff --git a/core/state/state_object.go b/core/state/state_object.go index 5dfd3c1b648a..71e5ec509e81 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -56,13 +56,13 @@ func (s Storage) Copy() Storage { return cpy } -// stateObject represents an Ethereum account which is being modified. +// StateObject represents an Ethereum account which is being modified. // // The usage pattern is as follows: // First you need to obtain a state object. // Account values can be accessed and modified through the object. // Finally, call commitTrie to write the modified storage trie into a database. -type stateObject struct { +type StateObject struct { address common.Address addrHash common.Hash // hash of ethereum address of the account data types.StateAccount @@ -97,7 +97,7 @@ func (s *stateObject) empty() bool { } // newObject creates a state object. -func newObject(db *StateDB, address common.Address, data types.StateAccount) *stateObject { +func newObject(db *StateDB, address common.Address, data types.StateAccount) *StateObject { if data.Balance == nil { data.Balance = new(big.Int) } @@ -107,7 +107,7 @@ func newObject(db *StateDB, address common.Address, data types.StateAccount) *st if data.Root == (common.Hash{}) { data.Root = types.EmptyRootHash } - return &stateObject{ + return &StateObject{ db: db, address: address, addrHash: crypto.Keccak256Hash(address[:]), @@ -119,22 +119,22 @@ func newObject(db *StateDB, address common.Address, data types.StateAccount) *st } // EncodeRLP implements rlp.Encoder. -func (s *stateObject) EncodeRLP(w io.Writer) error { +func (s *StateObject) EncodeRLP(w io.Writer) error { return rlp.Encode(w, &s.data) } // setError remembers the first non-nil error it is called with. -func (s *stateObject) setError(err error) { +func (s *StateObject) setError(err error) { if s.dbErr == nil { s.dbErr = err } } -func (s *stateObject) markSuicided() { +func (s *StateObject) markSuicided() { s.suicided = true } -func (s *stateObject) touch() { +func (s *StateObject) touch() { s.db.journal.append(touchChange{ account: &s.address, }) @@ -148,7 +148,7 @@ func (s *stateObject) touch() { // getTrie returns the associated storage trie. The trie will be opened // if it's not loaded previously. An error will be returned if trie can't // be loaded. -func (s *stateObject) getTrie(db Database) (Trie, error) { +func (s *StateObject) getTrie(db Database) (Trie, error) { if s.trie == nil { // Try fetching from prefetcher first // We don't prefetch empty tries @@ -169,7 +169,7 @@ func (s *stateObject) getTrie(db Database) (Trie, error) { } // GetState retrieves a value from the account storage trie. -func (s *stateObject) GetState(db Database, key common.Hash) common.Hash { +func (s *StateObject) GetState(db Database, key common.Hash) common.Hash { // If we have a dirty value for this state entry, return it value, dirty := s.dirtyStorage[key] if dirty { @@ -180,7 +180,7 @@ func (s *stateObject) GetState(db Database, key common.Hash) common.Hash { } // GetCommittedState retrieves a value from the committed account storage trie. -func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Hash { +func (s *StateObject) GetCommittedState(db Database, key common.Hash) common.Hash { // If we have a pending write or clean cached, return that if value, pending := s.pendingStorage[key]; pending { return value @@ -239,7 +239,7 @@ func (s *stateObject) GetCommittedState(db Database, key common.Hash) common.Has } // SetState updates a value in account storage. -func (s *stateObject) SetState(db Database, key, value common.Hash) { +func (s *StateObject) SetState(db Database, key, value common.Hash) { // If the new value is the same as old, don't set prev := s.GetState(db, key) if prev == value { @@ -254,13 +254,13 @@ func (s *stateObject) SetState(db Database, key, value common.Hash) { s.setState(key, value) } -func (s *stateObject) setState(key, value common.Hash) { +func (s *StateObject) setState(key, value common.Hash) { s.dirtyStorage[key] = value } // finalise moves all dirty storage slots into the pending area to be hashed or // committed later. It is invoked at the end of every transaction. -func (s *stateObject) finalise(prefetch bool) { +func (s *StateObject) finalise(prefetch bool) { slotsToPrefetch := make([][]byte, 0, len(s.dirtyStorage)) for key, value := range s.dirtyStorage { s.pendingStorage[key] = value @@ -279,7 +279,7 @@ func (s *stateObject) finalise(prefetch bool) { // updateTrie writes cached storage modifications into the object's storage trie. // It will return nil if the trie has not been loaded and no changes have been // made. An error will be returned if the trie can't be loaded/updated correctly. -func (s *stateObject) updateTrie(db Database) (Trie, error) { +func (s *StateObject) updateTrie(db Database) (Trie, error) { // Make sure all dirty slots are finalized into the pending storage area s.finalise(false) // Don't prefetch anymore, pull directly if need be if len(s.pendingStorage) == 0 { @@ -348,7 +348,7 @@ func (s *stateObject) updateTrie(db Database) (Trie, error) { // UpdateRoot sets the trie root to the current root hash of. An error // will be returned if trie root hash is not computed correctly. -func (s *stateObject) updateRoot(db Database) { +func (s *StateObject) updateRoot(db Database) { tr, err := s.updateTrie(db) if err != nil { s.setError(fmt.Errorf("updateRoot (%x) error: %w", s.address, err)) @@ -367,7 +367,7 @@ func (s *stateObject) updateRoot(db Database) { // commitTrie submits the storage changes into the storage trie and re-computes // the root. Besides, all trie changes will be collected in a nodeset and returned. -func (s *stateObject) commitTrie(db Database) (*trie.NodeSet, error) { +func (s *StateObject) commitTrie(db Database) (*trie.NodeSet, error) { tr, err := s.updateTrie(db) if err != nil { return nil, err @@ -390,7 +390,7 @@ func (s *stateObject) commitTrie(db Database) (*trie.NodeSet, error) { // AddBalance adds amount to s's balance. // It is used to add funds to the destination account of a transfer. -func (s *stateObject) AddBalance(amount *big.Int) { +func (s *StateObject) AddBalance(amount *big.Int) { // EIP161: We must check emptiness for the objects such that the account // clearing (0,0,0 objects) can take effect. if amount.Sign() == 0 { @@ -404,14 +404,14 @@ func (s *stateObject) AddBalance(amount *big.Int) { // SubBalance removes amount from s's balance. // It is used to remove funds from the origin account of a transfer. -func (s *stateObject) SubBalance(amount *big.Int) { +func (s *StateObject) SubBalance(amount *big.Int) { if amount.Sign() == 0 { return } s.SetBalance(new(big.Int).Sub(s.Balance(), amount)) } -func (s *stateObject) SetBalance(amount *big.Int) { +func (s *StateObject) SetBalance(amount *big.Int) { s.db.journal.append(balanceChange{ account: &s.address, prev: new(big.Int).Set(s.data.Balance), @@ -419,23 +419,23 @@ func (s *stateObject) SetBalance(amount *big.Int) { s.setBalance(amount) } -func (s *stateObject) setBalance(amount *big.Int) { +func (s *StateObject) setBalance(amount *big.Int) { s.data.Balance = amount } -func (s *stateObject) deepCopy(db *StateDB) *stateObject { - stateObject := newObject(db, s.address, s.data) +func (s *StateObject) deepCopy(db *StateDB) *StateObject { + StateObject := newObject(db, s.address, s.data) if s.trie != nil { - stateObject.trie = db.db.CopyTrie(s.trie) + StateObject.trie = db.db.CopyTrie(s.trie) } - stateObject.code = s.code - stateObject.dirtyStorage = s.dirtyStorage.Copy() - stateObject.originStorage = s.originStorage.Copy() - stateObject.pendingStorage = s.pendingStorage.Copy() - stateObject.suicided = s.suicided - stateObject.dirtyCode = s.dirtyCode - stateObject.deleted = s.deleted - return stateObject + StateObject.code = s.code + StateObject.dirtyStorage = s.dirtyStorage.Copy() + StateObject.originStorage = s.originStorage.Copy() + StateObject.pendingStorage = s.pendingStorage.Copy() + StateObject.suicided = s.suicided + StateObject.dirtyCode = s.dirtyCode + StateObject.deleted = s.deleted + return StateObject } // @@ -443,12 +443,12 @@ func (s *stateObject) deepCopy(db *StateDB) *stateObject { // // Address returns the address of the contract/account -func (s *stateObject) Address() common.Address { +func (s *StateObject) Address() common.Address { return s.address } // Code returns the contract code associated with this object, if any. -func (s *stateObject) Code(db Database) []byte { +func (s *StateObject) Code(db Database) []byte { if s.code != nil { return s.code } @@ -466,7 +466,7 @@ func (s *stateObject) Code(db Database) []byte { // CodeSize returns the size of the contract code associated with this object, // or zero if none. This method is an almost mirror of Code, but uses a cache // inside the database to avoid loading codes seen recently. -func (s *stateObject) CodeSize(db Database) int { +func (s *StateObject) CodeSize(db Database) int { if s.code != nil { return len(s.code) } @@ -480,7 +480,7 @@ func (s *stateObject) CodeSize(db Database) int { return size } -func (s *stateObject) SetCode(codeHash common.Hash, code []byte) { +func (s *StateObject) SetCode(codeHash common.Hash, code []byte) { prevcode := s.Code(s.db.db) s.db.journal.append(codeChange{ account: &s.address, @@ -490,13 +490,13 @@ func (s *stateObject) SetCode(codeHash common.Hash, code []byte) { s.setCode(codeHash, code) } -func (s *stateObject) setCode(codeHash common.Hash, code []byte) { +func (s *StateObject) setCode(codeHash common.Hash, code []byte) { s.code = code s.data.CodeHash = codeHash[:] s.dirtyCode = true } -func (s *stateObject) SetNonce(nonce uint64) { +func (s *StateObject) SetNonce(nonce uint64) { s.db.journal.append(nonceChange{ account: &s.address, prev: s.data.Nonce, @@ -504,25 +504,25 @@ func (s *stateObject) SetNonce(nonce uint64) { s.setNonce(nonce) } -func (s *stateObject) setNonce(nonce uint64) { +func (s *StateObject) setNonce(nonce uint64) { s.data.Nonce = nonce } -func (s *stateObject) CodeHash() []byte { +func (s *StateObject) CodeHash() []byte { return s.data.CodeHash } -func (s *stateObject) Balance() *big.Int { +func (s *StateObject) Balance() *big.Int { return s.data.Balance } -func (s *stateObject) Nonce() uint64 { +func (s *StateObject) Nonce() uint64 { return s.data.Nonce } -// Value is never called, but must be present to allow stateObject to be used +// Value is never called, but must be present to allow StateObject to be used // as a vm.Account interface that also satisfies the vm.ContractRef // interface. Interfaces are awesome. -func (s *stateObject) Value() *big.Int { - panic("Value on stateObject should never be called") +func (s *StateObject) Value() *big.Int { + panic("Value on StateObject should never be called") } diff --git a/core/state/state_test.go b/core/state/state_test.go index b6b46e446fba..3f48fdd13fd5 100644 --- a/core/state/state_test.go +++ b/core/state/state_test.go @@ -205,7 +205,7 @@ func TestSnapshot2(t *testing.T) { } } -func compareStateObjects(so0, so1 *stateObject, t *testing.T) { +func compareStateObjects(so0, so1 *StateObject, t *testing.T) { if so0.Address() != so1.Address() { t.Fatalf("Address mismatch: have %v, want %v", so0.address, so1.address) } diff --git a/core/state/statedb.go b/core/state/statedb.go index 2c7d767a7b46..b92ad1035f02 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -73,7 +73,7 @@ type StateDB struct { snapStorage map[common.Hash]map[common.Hash][]byte // This map holds 'live' objects, which will get modified while processing a state transition. - stateObjects map[common.Address]*stateObject + stateObjects map[common.Address]*StateObject stateObjectsPending map[common.Address]struct{} // State objects finalized but not yet written to the trie stateObjectsDirty map[common.Address]struct{} // State objects modified in the current execution stateObjectsDestruct map[common.Address]struct{} // State objects destructed in the block @@ -138,7 +138,7 @@ func New(root common.Hash, db Database, snaps *snapshot.Tree) (*StateDB, error) trie: tr, originalRoot: root, snaps: snaps, - stateObjects: make(map[common.Address]*stateObject), + stateObjects: make(map[common.Address]*StateObject), stateObjectsPending: make(map[common.Address]struct{}), stateObjectsDirty: make(map[common.Address]struct{}), stateObjectsDestruct: make(map[common.Address]struct{}), @@ -266,17 +266,17 @@ func (s *StateDB) Empty(addr common.Address) bool { // GetBalance retrieves the balance from the given address or 0 if object not found func (s *StateDB) GetBalance(addr common.Address) *big.Int { - stateObject := s.getStateObject(addr) - if stateObject != nil { - return stateObject.Balance() + StateObject := s.getStateObject(addr) + if StateObject != nil { + return StateObject.Balance() } return common.Big0 } func (s *StateDB) GetNonce(addr common.Address) uint64 { - stateObject := s.getStateObject(addr) - if stateObject != nil { - return stateObject.Nonce() + StateObject := s.getStateObject(addr) + if StateObject != nil { + return StateObject.Nonce() } return 0 @@ -288,34 +288,34 @@ func (s *StateDB) TxIndex() int { } func (s *StateDB) GetCode(addr common.Address) []byte { - stateObject := s.getStateObject(addr) - if stateObject != nil { - return stateObject.Code(s.db) + StateObject := s.getStateObject(addr) + if StateObject != nil { + return StateObject.Code(s.db) } return nil } func (s *StateDB) GetCodeSize(addr common.Address) int { - stateObject := s.getStateObject(addr) - if stateObject != nil { - return stateObject.CodeSize(s.db) + StateObject := s.getStateObject(addr) + if StateObject != nil { + return StateObject.CodeSize(s.db) } return 0 } func (s *StateDB) GetCodeHash(addr common.Address) common.Hash { - stateObject := s.getStateObject(addr) - if stateObject == nil { + StateObject := s.getStateObject(addr) + if StateObject == nil { return common.Hash{} } - return common.BytesToHash(stateObject.CodeHash()) + return common.BytesToHash(StateObject.CodeHash()) } // GetState retrieves a value from the given account's storage trie. func (s *StateDB) GetState(addr common.Address, hash common.Hash) common.Hash { - stateObject := s.getStateObject(addr) - if stateObject != nil { - return stateObject.GetState(s.db, hash) + StateObject := s.getStateObject(addr) + if StateObject != nil { + return StateObject.GetState(s.db, hash) } return common.Hash{} } @@ -351,9 +351,9 @@ 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 { - stateObject := s.getStateObject(addr) - if stateObject != nil { - return stateObject.GetCommittedState(s.db, hash) + StateObject := s.getStateObject(addr) + if StateObject != nil { + return StateObject.GetCommittedState(s.db, hash) } return common.Hash{} } @@ -367,11 +367,11 @@ func (s *StateDB) Database() Database { // and is nil for non-existent accounts. An error will be returned if storage trie // is existent but can't be loaded correctly. func (s *StateDB) StorageTrie(addr common.Address) (Trie, error) { - stateObject := s.getStateObject(addr) - if stateObject == nil { + StateObject := s.getStateObject(addr) + if StateObject == nil { return nil, nil } - cpy := stateObject.deepCopy(s) + cpy := StateObject.deepCopy(s) if _, err := cpy.updateTrie(s.db); err != nil { return nil, err } @@ -379,9 +379,9 @@ func (s *StateDB) StorageTrie(addr common.Address) (Trie, error) { } func (s *StateDB) HasSuicided(addr common.Address) bool { - stateObject := s.getStateObject(addr) - if stateObject != nil { - return stateObject.suicided + StateObject := s.getStateObject(addr) + if StateObject != nil { + return StateObject.suicided } return false } @@ -392,45 +392,45 @@ 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) { - stateObject := s.GetOrNewStateObject(addr) - if stateObject != nil { - stateObject.AddBalance(amount) + StateObject := s.GetOrNewStateObject(addr) + if StateObject != nil { + StateObject.AddBalance(amount) } } // SubBalance subtracts amount from the account associated with addr. func (s *StateDB) SubBalance(addr common.Address, amount *big.Int) { - stateObject := s.GetOrNewStateObject(addr) - if stateObject != nil { - stateObject.SubBalance(amount) + StateObject := s.GetOrNewStateObject(addr) + if StateObject != nil { + StateObject.SubBalance(amount) } } func (s *StateDB) SetBalance(addr common.Address, amount *big.Int) { - stateObject := s.GetOrNewStateObject(addr) - if stateObject != nil { - stateObject.SetBalance(amount) + StateObject := s.GetOrNewStateObject(addr) + if StateObject != nil { + StateObject.SetBalance(amount) } } func (s *StateDB) SetNonce(addr common.Address, nonce uint64) { - stateObject := s.GetOrNewStateObject(addr) - if stateObject != nil { - stateObject.SetNonce(nonce) + StateObject := s.GetOrNewStateObject(addr) + if StateObject != nil { + StateObject.SetNonce(nonce) } } func (s *StateDB) SetCode(addr common.Address, code []byte) { - stateObject := s.GetOrNewStateObject(addr) - if stateObject != nil { - stateObject.SetCode(crypto.Keccak256Hash(code), code) + StateObject := s.GetOrNewStateObject(addr) + if StateObject != nil { + StateObject.SetCode(crypto.Keccak256Hash(code), code) } } func (s *StateDB) SetState(addr common.Address, key, value common.Hash) { - stateObject := s.GetOrNewStateObject(addr) - if stateObject != nil { - stateObject.SetState(s.db, key, value) + StateObject := s.GetOrNewStateObject(addr) + if StateObject != nil { + StateObject.SetState(s.db, key, value) } } @@ -443,9 +443,9 @@ func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common // will not hit disk, since it is assumed that the disk-data is belonging // to a previous incarnation of the object. s.stateObjectsDestruct[addr] = struct{}{} - stateObject := s.GetOrNewStateObject(addr) + StateObject := s.GetOrNewStateObject(addr) for k, v := range storage { - stateObject.SetState(s.db, k, v) + StateObject.SetState(s.db, k, v) } } @@ -455,17 +455,17 @@ 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 { - stateObject := s.getStateObject(addr) - if stateObject == nil { + StateObject := s.getStateObject(addr) + if StateObject == nil { return false } s.journal.append(suicideChange{ account: &addr, - prev: stateObject.suicided, - prevbalance: new(big.Int).Set(stateObject.Balance()), + prev: StateObject.suicided, + prevbalance: new(big.Int).Set(StateObject.Balance()), }) - stateObject.markSuicided() - stateObject.data.Balance = new(big.Int) + StateObject.markSuicided() + StateObject.data.Balance = new(big.Int) return true } @@ -504,7 +504,7 @@ func (s *StateDB) GetTransientState(addr common.Address, key common.Hash) common // // updateStateObject writes the given object to the trie. -func (s *StateDB) updateStateObject(obj *stateObject) { +func (s *StateDB) 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()) @@ -525,7 +525,7 @@ func (s *StateDB) updateStateObject(obj *stateObject) { } // deleteStateObject removes the given object from the state trie. -func (s *StateDB) deleteStateObject(obj *stateObject) { +func (s *StateDB) 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()) @@ -540,7 +540,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 *StateDB) getStateObject(addr common.Address) *StateObject { if obj := s.getDeletedStateObject(addr); obj != nil && !obj.deleted { return obj } @@ -551,7 +551,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 *StateDB) getDeletedStateObject(addr common.Address) *StateObject { // Prefer live objects if any is available if obj := s.stateObjects[addr]; obj != nil { return obj @@ -604,22 +604,22 @@ func (s *StateDB) getDeletedStateObject(addr common.Address) *stateObject { return obj } -func (s *StateDB) setStateObject(object *stateObject) { +func (s *StateDB) 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 { - stateObject := s.getStateObject(addr) - if stateObject == nil { - stateObject, _ = s.createObject(addr) +func (s *StateDB) GetOrNewStateObject(addr common.Address) *StateObject { + StateObject := s.getStateObject(addr) + if StateObject == nil { + StateObject, _ = s.createObject(addr) } - return stateObject + return 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 *StateDB) createObject(addr common.Address) (newobj, prev *StateObject) { prev = s.getDeletedStateObject(addr) // Note, prev might have been deleted, we need that! var prevdestruct bool @@ -700,7 +700,7 @@ func (s *StateDB) Copy() StateDBI { db: s.db, trie: s.db.CopyTrie(s.trie), originalRoot: s.originalRoot, - stateObjects: make(map[common.Address]*stateObject, len(s.journal.dirties)), + stateObjects: make(map[common.Address]*StateObject, len(s.journal.dirties)), stateObjectsPending: make(map[common.Address]struct{}, len(s.stateObjectsPending)), stateObjectsDirty: make(map[common.Address]struct{}, len(s.journal.dirties)), stateObjectsDestruct: make(map[common.Address]struct{}, len(s.stateObjectsDestruct)), diff --git a/core/state_prefetcher.go b/core/state_prefetcher.go index 867b47db5319..3a9e388739d8 100644 --- a/core/state_prefetcher.go +++ b/core/state_prefetcher.go @@ -47,7 +47,7 @@ func newStatePrefetcher(config *params.ChainConfig, bc *BlockChain, engine conse // Prefetch processes the state changes according to the Ethereum rules by running // the transaction messages using the statedb, but any changes are discarded. The // only goal is to pre-cache transaction signatures and state trie nodes. -func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, cfg vm.Config, interrupt *uint32) { +func (p *statePrefetcher) Prefetch(block *types.Block, statedb state.StateDBI, cfg vm.Config, interrupt *uint32) { var ( header = block.Header() gaspool = new(GasPool).AddGas(block.GasLimit()) @@ -85,7 +85,7 @@ func (p *statePrefetcher) Prefetch(block *types.Block, statedb *state.StateDB, c // precacheTransaction attempts to apply a transaction to the given state database // and uses the input parameters for its environment. The goal is not to execute // the transaction successfully, rather to warm up touched data slots. -func precacheTransaction(msg types.Message, config *params.ChainConfig, gaspool *GasPool, statedb *state.StateDB, header *types.Header, evm *vm.EVM) error { +func precacheTransaction(msg types.Message, config *params.ChainConfig, gaspool *GasPool, statedb state.StateDBI, header *types.Header, evm *vm.EVM) error { // Update the evm with the new transaction context. evm.Reset(NewEVMTxContext(msg), statedb) // Add addresses to access list if applicable diff --git a/core/state_processor.go b/core/state_processor.go index 163ea0a0200a..952c434eba68 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -56,7 +56,7 @@ func NewStateProcessor(config *params.ChainConfig, bc *BlockChain, engine consen // Process returns the receipts and logs accumulated during the process and // returns the amount of gas that was used in the process. If any of the // transactions failed to execute due to insufficient gas it will return an error. -func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) { +func (p *StateProcessor) Process(block *types.Block, statedb state.StateDBI, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) { var ( receipts types.Receipts usedGas = new(uint64) @@ -97,7 +97,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg return receipts, allLogs, *usedGas, nil } -func applyTransaction(msg types.Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) { +func applyTransaction(msg types.Message, config *params.ChainConfig, gp *GasPool, statedb state.StateDBI, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) { // Create a new context to be used in the EVM environment. txContext := NewEVMTxContext(msg) evm.Reset(txContext, statedb) @@ -146,7 +146,7 @@ func applyTransaction(msg types.Message, config *params.ChainConfig, gp *GasPool // and uses the input parameters for its environment. It returns the receipt // for the transaction, gas used and an error if the transaction failed, // indicating the block was invalid. -func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, error) { +func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb state.StateDBI, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, error) { msg, err := tx.AsMessage(types.MakeSigner(config, header.Number), header.BaseFee) if err != nil { return nil, err diff --git a/core/txpool/noncer.go b/core/txpool/noncer.go index ba7fbedad568..a355d1f82c21 100644 --- a/core/txpool/noncer.go +++ b/core/txpool/noncer.go @@ -27,13 +27,13 @@ import ( // accounts in the pool, falling back to reading from a real state database if // an account is unknown. type noncer struct { - fallback *state.StateDB + fallback state.StateDBI nonces map[common.Address]uint64 lock sync.Mutex } // newNoncer creates a new virtual state database to track the pool nonces. -func newNoncer(statedb *state.StateDB) *noncer { +func newNoncer(statedb state.StateDBI) *noncer { return &noncer{ fallback: statedb.Copy(), nonces: make(map[common.Address]uint64), diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go index c80520186627..8d941dd5db09 100644 --- a/core/txpool/txpool.go +++ b/core/txpool/txpool.go @@ -147,7 +147,7 @@ const ( type blockChain interface { CurrentBlock() *types.Block GetBlock(hash common.Hash, number uint64) *types.Block - StateAt(root common.Hash) (*state.StateDB, error) + StateAt(root common.Hash) (state.StateDBI, error) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription } @@ -248,7 +248,7 @@ type TxPool struct { eip1559 bool // Fork indicator whether we are using EIP-1559 type transactions. shanghai bool // Fork indicator whether we are in the Shanghai stage. - currentState *state.StateDB // Current state in the blockchain head + currentState state.StateDBI // Current state in the blockchain head pendingNonces *noncer // Pending state tracking virtual nonces currentMaxGas uint64 // Current gas limit for transaction caps diff --git a/core/txpool/txpool_test.go b/core/txpool/txpool_test.go index bd82622f8de6..46bb08b3e14c 100644 --- a/core/txpool/txpool_test.go +++ b/core/txpool/txpool_test.go @@ -60,7 +60,7 @@ func init() { type testBlockChain struct { gasLimit uint64 // must be first field for 64 bit alignment (atomic access) - statedb *state.StateDB + statedb state.StateDBI chainHeadFeed *event.Feed } @@ -74,7 +74,7 @@ func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block return bc.CurrentBlock() } -func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { +func (bc *testBlockChain) StateAt(common.Hash) (state.StateDBI, error) { return bc.statedb, nil } @@ -202,7 +202,7 @@ type testChain struct { // testChain.State() is used multiple times to reset the pending state. // when simulate is true it will create a state that indicates // that tx0 and tx1 are included in the chain. -func (c *testChain) State() (*state.StateDB, error) { +func (c *testChain) State() (state.StateDBI, error) { // delay "state change" by one. The tx pool fetches the // state multiple times and by delaying it a bit we simulate // a state change between those fetches. diff --git a/core/types.go b/core/types.go index 4c5b74a49865..0a8fa9da2f61 100644 --- a/core/types.go +++ b/core/types.go @@ -31,7 +31,7 @@ type Validator interface { // ValidateState validates the given statedb and optionally the receipts and // gas used. - ValidateState(block *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error + ValidateState(block *types.Block, state state.StateDBI, receipts types.Receipts, usedGas uint64) error } // Prefetcher is an interface for pre-caching transaction signatures and state. @@ -39,7 +39,7 @@ type Prefetcher interface { // Prefetch processes the state changes according to the Ethereum rules by running // the transaction messages using the statedb, but any changes are discarded. The // only goal is to pre-cache transaction signatures and state trie nodes. - Prefetch(block *types.Block, statedb *state.StateDB, cfg vm.Config, interrupt *uint32) + Prefetch(block *types.Block, statedb state.StateDBI, cfg vm.Config, interrupt *uint32) } // Processor is an interface for processing blocks using a given initial state. @@ -47,5 +47,5 @@ type Processor interface { // Process processes the state changes according to the Ethereum rules by running // the transaction messages using the statedb and applying any rewards to both // the processor (coinbase) and any included uncles. - Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) + Process(block *types.Block, statedb state.StateDBI, cfg vm.Config) (types.Receipts, []*types.Log, uint64, error) } diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go index 61f001a692c3..1554a603ff0c 100644 --- a/core/vm/instructions_test.go +++ b/core/vm/instructions_test.go @@ -592,7 +592,7 @@ func TestOpTstore(t *testing.T) { value = common.Hex2Bytes("abcdef00000000000000abba000000000deaf000000c0de00100000000133700") ) - // Add a stateObject for the caller and the contract being called + // Add a StateObject for the caller and the contract being called statedb.CreateAccount(caller) statedb.CreateAccount(to) diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index 56ff5eeabe33..18ae0f697ef8 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -44,7 +44,7 @@ type Config struct { EVMConfig vm.Config BaseFee *big.Int - State *state.StateDB + State state.StateDBI GetHashFn func(n uint64) common.Hash } @@ -100,7 +100,7 @@ func setDefaults(cfg *Config) { // // Execute sets up an in-memory, temporary, environment for the execution of // the given code. It makes sure that it's restored to its original state afterwards. -func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) { +func Execute(code, input []byte, cfg *Config) ([]byte, state.StateDBI, error) { if cfg == nil { cfg = new(Config) } diff --git a/eth/api.go b/eth/api.go index c1f73037d7d8..42b413a246f9 100644 --- a/eth/api.go +++ b/eth/api.go @@ -337,7 +337,7 @@ const AccountRangeMaxResults = 256 // AccountRange enumerates all accounts in the given block and start point in paging request func (api *DebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, start hexutil.Bytes, maxResults int, nocode, nostorage, incompletes bool) (state.IteratorDump, error) { - var stateDb *state.StateDB + var stateDb state.StateDBI var err error if number, ok := blockNrOrHash.Number(); ok { diff --git a/eth/api_backend.go b/eth/api_backend.go index 8fd3e43300d3..4a6e9b05122d 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -171,7 +171,7 @@ func (b *EthAPIBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) return b.eth.miner.PendingBlockAndReceipts() } -func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { +func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (vm.StateDB, *types.Header, error) { // Pending state is only known by the miner if number == rpc.PendingBlockNumber { block, state := b.eth.miner.Pending() @@ -189,7 +189,7 @@ func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B return stateDb, header, err } -func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { +func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (vm.StateDB, *types.Header, error) { if blockNr, ok := blockNrOrHash.Number(); ok { return b.StateAndHeaderByNumber(ctx, blockNr) } @@ -225,7 +225,7 @@ func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int { return nil } -func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { +func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state vm.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { if vmConfig == nil { vmConfig = b.eth.blockchain.GetVMConfig() } @@ -375,10 +375,10 @@ func (b *EthAPIBackend) StartMining(threads int) error { return b.eth.StartMining(threads) } -func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, tracers.StateReleaseFunc, error) { +func (b *EthAPIBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base state.StateDBI, readOnly bool, preferDisk bool) (state.StateDBI, tracers.StateReleaseFunc, error) { return b.eth.StateAtBlock(ctx, block, reexec, base, readOnly, preferDisk) } -func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { +func (b *EthAPIBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, state.StateDBI, tracers.StateReleaseFunc, error) { return b.eth.stateAtTransaction(ctx, block, txIndex, reexec) } diff --git a/eth/api_test.go b/eth/api_test.go index fca17f12171b..465dfcc6c27d 100644 --- a/eth/api_test.go +++ b/eth/api_test.go @@ -34,7 +34,7 @@ import ( var dumper = spew.ConfigState{Indent: " "} -func accountRangeTest(t *testing.T, trie *state.Trie, statedb *state.StateDB, start common.Hash, requestedNum int, expectedNum int) state.IteratorDump { +func accountRangeTest(t *testing.T, trie *state.Trie, statedb state.StateDBI, start common.Hash, requestedNum int, expectedNum int) state.IteratorDump { result := statedb.IteratorDump(&state.DumpConfig{ SkipCode: true, SkipStorage: true, diff --git a/eth/state_accessor.go b/eth/state_accessor.go index 3bb1464952a0..d892b5e8ef8f 100644 --- a/eth/state_accessor.go +++ b/eth/state_accessor.go @@ -57,7 +57,7 @@ var noopReleaser = tracers.StateReleaseFunc(func() {}) // - preferDisk: this arg can be used by the caller to signal that even though the 'base' is // provided, it would be preferable to start from a fresh state, if we have it // on disk. -func (eth *Ethereum) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (statedb *state.StateDB, release tracers.StateReleaseFunc, err error) { +func (eth *Ethereum) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base state.StateDBI, readOnly bool, preferDisk bool) (statedb state.StateDBI, release tracers.StateReleaseFunc, err error) { var ( current *types.Block database state.Database @@ -189,7 +189,7 @@ func (eth *Ethereum) StateAtBlock(ctx context.Context, block *types.Block, reexe } // stateAtTransaction returns the execution environment of a certain transaction. -func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { +func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, state.StateDBI, tracers.StateReleaseFunc, error) { // Short circuit if it's genesis block. if block.NumberU64() == 0 { return nil, vm.BlockContext{}, nil, nil, errors.New("no transaction in genesis") diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 4814b0066663..5ea408832ff9 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -86,8 +86,8 @@ type Backend interface { ChainConfig() *params.ChainConfig Engine() consensus.Engine ChainDb() ethdb.Database - StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, StateReleaseFunc, error) - StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) + StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base state.StateDBI, readOnly bool, preferDisk bool) (state.StateDBI, StateReleaseFunc, error) + StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, state.StateDBI, StateReleaseFunc, error) } // API is the collection of tracing APIs exposed over the private debugging endpoint. @@ -331,7 +331,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed number uint64 traced uint64 failed error - statedb *state.StateDB + statedb state.StateDBI release StateReleaseFunc ) // Ensure everything is properly cleaned up on any exit path @@ -648,7 +648,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac // traceBlockParallel is for tracers that have a high overhead (read JS tracers). One thread // runs along and executes txes without tracing enabled to generate their prestate. // Worker threads take the tasks and the prestate and trace them. -func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, statedb *state.StateDB, config *TraceConfig) ([]*txTraceResult, error) { +func (api *API) traceBlockParallel(ctx context.Context, block *types.Block, statedb state.StateDBI, config *TraceConfig) ([]*txTraceResult, error) { // Execute all the transaction contained within the block concurrently var ( txs = block.Transactions() diff --git a/eth/tracers/api_test.go b/eth/tracers/api_test.go index bbcb00a5e763..46593be31445 100644 --- a/eth/tracers/api_test.go +++ b/eth/tracers/api_test.go @@ -140,7 +140,7 @@ func (b *testBackend) teardown() { b.chain.Stop() } -func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, StateReleaseFunc, error) { +func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base state.StateDBI, readOnly bool, preferDisk bool) (state.StateDBI, StateReleaseFunc, error) { statedb, err := b.chain.StateAt(block.Root()) if err != nil { return nil, nil, errStateNotFound @@ -156,7 +156,7 @@ func (b *testBackend) StateAtBlock(ctx context.Context, block *types.Block, reex return statedb, release, nil } -func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, StateReleaseFunc, error) { +func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, state.StateDBI, StateReleaseFunc, error) { parent := b.chain.GetBlock(block.ParentHash(), block.NumberU64()-1) if parent == nil { return nil, vm.BlockContext{}, nil, nil, errBlockNotFound diff --git a/graphql/graphql.go b/graphql/graphql.go index 637778e9d0f7..04445e35abc2 100644 --- a/graphql/graphql.go +++ b/graphql/graphql.go @@ -83,7 +83,7 @@ type Account struct { } // getState fetches the StateDB object for an account. -func (a *Account) getState(ctx context.Context) (*state.StateDB, error) { +func (a *Account) getState(ctx context.Context) (state.StateDBI, error) { state, _, err := a.r.backend.StateAndHeaderByNumberOrHash(ctx, a.blockNrOrHash) return state, err } diff --git a/les/api_backend.go b/les/api_backend.go index 422ac74b8668..3f9f44765184 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -138,7 +138,7 @@ func (b *LesApiBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) return nil, nil } -func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) { +func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (state.StateDBI, *types.Header, error) { header, err := b.HeaderByNumber(ctx, number) if err != nil { return nil, nil, err @@ -149,7 +149,7 @@ func (b *LesApiBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B return light.NewState(ctx, header, b.eth.odr), header, nil } -func (b *LesApiBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) { +func (b *LesApiBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (state.StateDBI, *types.Header, error) { if blockNr, ok := blockNrOrHash.Number(); ok { return b.StateAndHeaderByNumber(ctx, blockNr) } @@ -184,7 +184,7 @@ func (b *LesApiBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int { return nil } -func (b *LesApiBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { +func (b *LesApiBackend) GetEVM(ctx context.Context, msg core.Message, state state.StateDBI, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { if vmConfig == nil { vmConfig = new(vm.Config) } @@ -326,10 +326,10 @@ func (b *LesApiBackend) CurrentHeader() *types.Header { return b.eth.blockchain.CurrentHeader() } -func (b *LesApiBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, readOnly bool, preferDisk bool) (*state.StateDB, tracers.StateReleaseFunc, error) { +func (b *LesApiBackend) StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base state.StateDBI, readOnly bool, preferDisk bool) (state.StateDBI, tracers.StateReleaseFunc, error) { return b.eth.stateAtBlock(ctx, block, reexec) } -func (b *LesApiBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { +func (b *LesApiBackend) StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, state.StateDBI, tracers.StateReleaseFunc, error) { return b.eth.stateAtTransaction(ctx, block, txIndex, reexec) } diff --git a/les/odr_test.go b/les/odr_test.go index e028d35e639c..d7886423dda0 100644 --- a/les/odr_test.go +++ b/les/odr_test.go @@ -92,7 +92,7 @@ func odrAccounts(ctx context.Context, db ethdb.Database, config *params.ChainCon var ( res []byte - st *state.StateDB + st state.StateDBI err error ) for _, addr := range acc { diff --git a/les/state_accessor.go b/les/state_accessor.go index 091ec8871eee..9ba8f9c8d2b1 100644 --- a/les/state_accessor.go +++ b/les/state_accessor.go @@ -34,12 +34,12 @@ import ( var noopReleaser = tracers.StateReleaseFunc(func() {}) // stateAtBlock retrieves the state database associated with a certain block. -func (leth *LightEthereum) stateAtBlock(ctx context.Context, block *types.Block, reexec uint64) (*state.StateDB, tracers.StateReleaseFunc, error) { +func (leth *LightEthereum) stateAtBlock(ctx context.Context, block *types.Block, reexec uint64) (state.StateDBI, tracers.StateReleaseFunc, error) { return light.NewState(ctx, block.Header(), leth.odr), noopReleaser, nil } // stateAtTransaction returns the execution environment of a certain transaction. -func (leth *LightEthereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, tracers.StateReleaseFunc, error) { +func (leth *LightEthereum) stateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, state.StateDBI, tracers.StateReleaseFunc, error) { // Short circuit if it's genesis block. if block.NumberU64() == 0 { return nil, vm.BlockContext{}, nil, nil, errors.New("no transaction in genesis") diff --git a/light/odr_test.go b/light/odr_test.go index 903c7f6f90a6..99e396862067 100644 --- a/light/odr_test.go +++ b/light/odr_test.go @@ -154,7 +154,7 @@ func odrAccounts(ctx context.Context, db ethdb.Database, bc *core.BlockChain, lc dummyAddr := common.HexToAddress("1234567812345678123456781234567812345678") acc := []common.Address{testBankAddress, acc1Addr, acc2Addr, dummyAddr} - var st *state.StateDB + var st state.StateDBI if bc == nil { header := lc.GetHeaderByHash(bhash) st = NewState(ctx, header, lc.Odr()) @@ -189,7 +189,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain data[35] = byte(i) var ( - st *state.StateDB + st state.StateDBI header *types.Header chain core.ChainContext ) diff --git a/light/trie.go b/light/trie.go index 0ccab1588d3d..137b98654ba0 100644 --- a/light/trie.go +++ b/light/trie.go @@ -35,7 +35,7 @@ var ( sha3Nil = crypto.Keccak256Hash(nil) ) -func NewState(ctx context.Context, head *types.Header, odr OdrBackend) *state.StateDB { +func NewState(ctx context.Context, head *types.Header, odr OdrBackend) state.StateDBI { state, _ := state.New(head.Root, NewStateDatabase(ctx, head, odr), nil) return state } diff --git a/light/txpool.go b/light/txpool.go index e59dc3e77434..79f4dab391fe 100644 --- a/light/txpool.go +++ b/light/txpool.go @@ -114,7 +114,7 @@ func NewTxPool(config *params.ChainConfig, chain *LightChain, relay TxRelayBacke } // currentState returns the light state of the current head header -func (pool *TxPool) currentState(ctx context.Context) *state.StateDB { +func (pool *TxPool) currentState(ctx context.Context) state.StateDBI { return NewState(ctx, pool.chain.CurrentHeader(), pool.odr) } diff --git a/miner/miner.go b/miner/miner.go index c969aec73546..3b95b6620ef0 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -200,7 +200,7 @@ func (miner *Miner) SetRecommitInterval(interval time.Duration) { } // Pending returns the currently pending block and associated state. -func (miner *Miner) Pending() (*types.Block, *state.StateDB) { +func (miner *Miner) Pending() (*types.Block, state.StateDBI) { return miner.worker.pending() } diff --git a/miner/miner_test.go b/miner/miner_test.go index 2e7682acd331..163ff38b8ff2 100644 --- a/miner/miner_test.go +++ b/miner/miner_test.go @@ -55,12 +55,12 @@ func (m *mockBackend) TxPool() *txpool.TxPool { return m.txPool } -func (m *mockBackend) StateAtBlock(block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (statedb *state.StateDB, err error) { +func (m *mockBackend) StateAtBlock(block *types.Block, reexec uint64, base state.StateDBI, checkLive bool, preferDisk bool) (statedb state.StateDBI, err error) { return nil, errors.New("not supported") } type testBlockChain struct { - statedb *state.StateDB + statedb state.StateDBI gasLimit uint64 chainHeadFeed *event.Feed } @@ -75,7 +75,7 @@ func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block return bc.CurrentBlock() } -func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { +func (bc *testBlockChain) StateAt(common.Hash) (state.StateDBI, error) { return bc.statedb, nil } diff --git a/miner/worker.go b/miner/worker.go index 49204f71a076..c9685c701e40 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -88,7 +88,7 @@ var ( type environment struct { signer types.Signer - state *state.StateDB // apply state changes here + state state.StateDBI // apply state changes here ancestors mapset.Set[common.Hash] // ancestor set (used for checking uncle parent validity) family mapset.Set[common.Hash] // family set (used for checking uncle invalidity) tcount int // tx count in cycle @@ -150,7 +150,7 @@ func (env *environment) discard() { // task contains all information for consensus engine sealing and result submitting. type task struct { receipts []*types.Receipt - state *state.StateDB + state state.StateDBI block *types.Block createdAt time.Time } @@ -236,7 +236,7 @@ type worker struct { snapshotMu sync.RWMutex // The lock used to protect the snapshots below snapshotBlock *types.Block snapshotReceipts types.Receipts - snapshotState *state.StateDB + snapshotState state.StateDBI // atomic status counters running int32 // The indicator whether the consensus engine is running or not. @@ -381,7 +381,7 @@ func (w *worker) enablePreseal() { } // pending returns the pending state and corresponding block. -func (w *worker) pending() (*types.Block, *state.StateDB) { +func (w *worker) pending() (*types.Block, state.StateDBI) { // return a snapshot to avoid contention on currentMu mutex w.snapshotMu.RLock() defer w.snapshotMu.RUnlock() diff --git a/miner/worker_test.go b/miner/worker_test.go index ba929d293d8a..40045a42d26e 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -169,7 +169,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine func (b *testWorkerBackend) BlockChain() *core.BlockChain { return b.chain } func (b *testWorkerBackend) TxPool() *txpool.TxPool { return b.txPool } -func (b *testWorkerBackend) StateAtBlock(block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (statedb *state.StateDB, err error) { +func (b *testWorkerBackend) StateAtBlock(block *types.Block, reexec uint64, base state.StateDBI, checkLive bool, preferDisk bool) (statedb state.StateDBI, err error) { return nil, errors.New("not supported") } diff --git a/tests/block_test_util.go b/tests/block_test_util.go index 8da95a640a10..ea7eea2b74ee 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -286,7 +286,7 @@ func validateHeader(h *btHeader, h2 *types.Header) error { return nil } -func (t *BlockTest) validatePostState(statedb *state.StateDB) error { +func (t *BlockTest) validatePostState(statedb state.StateDBI) error { // validate post state accounts in test file against what we have in state db for addr, acct := range t.json.Post { // address is indirectly verified by the other fields, as it's the db key diff --git a/tests/fuzzers/bls12381/precompile_fuzzer.go b/tests/fuzzers/bls12381/precompile_fuzzer.go index cab2bcba3863..ccdc60156850 100644 --- a/tests/fuzzers/bls12381/precompile_fuzzer.go +++ b/tests/fuzzers/bls12381/precompile_fuzzer.go @@ -18,6 +18,7 @@ package bls import ( "bytes" + "context" "fmt" "github.com/ethereum/go-ethereum/common" @@ -92,7 +93,7 @@ func fuzz(id byte, data []byte) int { } cpy := make([]byte, len(data)) copy(cpy, data) - _, err := precompile.Run(cpy) + _, err := precompile.Run(context.Background(), cpy, common.Address{}, nil, true) if !bytes.Equal(cpy, data) { panic(fmt.Sprintf("input data modified, precompile %d: %x %x", id, data, cpy)) } diff --git a/tests/state_test_util.go b/tests/state_test_util.go index b2e87fb004b9..26adc0c791d7 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -182,7 +182,7 @@ func (t *StateTest) checkError(subtest StateSubtest, err error) error { } // Run executes a specific subtest and verifies the post-state and logs -func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bool) (*snapshot.Tree, *state.StateDB, error) { +func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bool) (*snapshot.Tree, state.StateDBI, error) { snaps, statedb, root, err := t.RunNoVerify(subtest, vmconfig, snapshotter) if checkedErr := t.checkError(subtest, err); checkedErr != nil { return snaps, statedb, checkedErr @@ -206,7 +206,7 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config, snapshotter bo } // RunNoVerify runs a specific subtest and returns the statedb and post-state root -func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapshotter bool) (*snapshot.Tree, *state.StateDB, common.Hash, error) { +func (t *StateTest) RunNoVerify(subtest StateSubtest, vmconfig vm.Config, snapshotter bool) (*snapshot.Tree, state.StateDBI, common.Hash, error) { config, eips, err := GetChainConfig(subtest.Fork) if err != nil { return nil, nil, common.Hash{}, UnsupportedForkError{subtest.Fork} @@ -283,7 +283,7 @@ func (t *StateTest) gasLimit(subtest StateSubtest) uint64 { return t.json.Tx.GasLimit[t.json.Post[subtest.Fork][subtest.Index].Indexes.Gas] } -func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter bool) (*snapshot.Tree, *state.StateDB) { +func MakePreState(db ethdb.Database, accounts core.GenesisAlloc, snapshotter bool) (*snapshot.Tree, state.StateDBI) { sdb := state.NewDatabase(db) statedb, _ := state.New(common.Hash{}, sdb, nil) for addr, a := range accounts { From d8cad9251ff66e2026fb6d8c474e3df7db3b5c91 Mon Sep 17 00:00:00 2001 From: t12s Date: Tue, 28 Feb 2023 11:57:46 -0500 Subject: [PATCH 38/40] fixed merge conflicts --- core/state/state_object.go | 2 +- core/vm/evm.go | 2 +- eth/filters/filter_system_test.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/state/state_object.go b/core/state/state_object.go index 71e5ec509e81..6c0023b25612 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -92,7 +92,7 @@ type StateObject struct { } // empty returns whether the account is considered empty. -func (s *stateObject) empty() bool { +func (s *StateObject) empty() bool { return s.data.Nonce == 0 && s.data.Balance.Sign() == 0 && bytes.Equal(s.data.CodeHash, types.EmptyCodeHash.Bytes()) } diff --git a/core/vm/evm.go b/core/vm/evm.go index a5b106b63b28..9f3790f5e505 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -132,7 +132,7 @@ func NewEVM(blockCtx BlockContext, txCtx TxContext, statedb StateDB, chainConfig StateDB: statedb, Config: config, chainConfig: chainConfig, - chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil), + chainRules: chainConfig.Rules(blockCtx.BlockNumber, blockCtx.Random != nil, blockCtx.Time), } evm.interpreter = NewEVMInterpreter(evm) return evm diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go index b70b0158ad00..242eec7383ef 100644 --- a/eth/filters/filter_system_test.go +++ b/eth/filters/filter_system_test.go @@ -35,9 +35,9 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethapi" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" - "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" ) From f629cbbcfd2089c9c2d3e727f845c24924c021d9 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Tue, 28 Feb 2023 12:38:34 -0500 Subject: [PATCH 39/40] remove unecessary vm imports --- eth/api_backend.go | 6 +++--- ethapi/api.go | 3 ++- ethapi/backend.go | 7 ++++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/eth/api_backend.go b/eth/api_backend.go index 4a6e9b05122d..5402a85a0117 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -171,7 +171,7 @@ func (b *EthAPIBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) return b.eth.miner.PendingBlockAndReceipts() } -func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (vm.StateDB, *types.Header, error) { +func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (state.StateDBI, *types.Header, error) { // Pending state is only known by the miner if number == rpc.PendingBlockNumber { block, state := b.eth.miner.Pending() @@ -189,7 +189,7 @@ func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.B return stateDb, header, err } -func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (vm.StateDB, *types.Header, error) { +func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (state.StateDBI, *types.Header, error) { if blockNr, ok := blockNrOrHash.Number(); ok { return b.StateAndHeaderByNumber(ctx, blockNr) } @@ -225,7 +225,7 @@ func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int { return nil } -func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state vm.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { +func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state state.StateDBI, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) { if vmConfig == nil { vmConfig = b.eth.blockchain.GetVMConfig() } diff --git a/ethapi/api.go b/ethapi/api.go index 904f776393b5..73323b33c642 100644 --- a/ethapi/api.go +++ b/ethapi/api.go @@ -36,6 +36,7 @@ import ( "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" @@ -877,7 +878,7 @@ type OverrideAccount struct { type StateOverride map[common.Address]OverrideAccount // Apply overrides the fields of specified accounts into the given state. -func (diff *StateOverride) Apply(state vm.StateDB) error { +func (diff *StateOverride) Apply(state state.StateDBI) error { if diff == nil { return nil } diff --git a/ethapi/backend.go b/ethapi/backend.go index d7e4f7e48a03..e1824adbcf8d 100644 --- a/ethapi/backend.go +++ b/ethapi/backend.go @@ -28,6 +28,7 @@ import ( "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/bloombits" + "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/ethdb" @@ -62,12 +63,12 @@ type Backend interface { BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) - StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (vm.StateDB, *types.Header, error) - StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (vm.StateDB, *types.Header, error) + StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (state.StateDBI, *types.Header, error) + StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (state.StateDBI, *types.Header, error) PendingBlockAndReceipts() (*types.Block, types.Receipts) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) GetTd(ctx context.Context, hash common.Hash) *big.Int - GetEVM(ctx context.Context, msg core.Message, state vm.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) + GetEVM(ctx context.Context, msg core.Message, state state.StateDBI, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription From 364e922bfe8d8c2d4859c8867bf022db6bca3bd4 Mon Sep 17 00:00:00 2001 From: Cal Bera Date: Mon, 6 Mar 2023 15:58:32 -0500 Subject: [PATCH 40/40] add signature to signer interface --- core/types/transaction_signing.go | 82 ++++++++++++++++++++++++++++++- ethclient/signer.go | 5 ++ 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go index 3e232fd84a66..5d9dcf1d3995 100644 --- a/core/types/transaction_signing.go +++ b/core/types/transaction_signing.go @@ -160,9 +160,13 @@ type Signer interface { // PubKey returns the public key of the sender. PubKey(tx *Transaction) ([]byte, error) + // Signature returns the raw signature of the transaction. + Signature(tx *Transaction) ([]byte, error) + // SignatureValues returns the raw R, S, V values corresponding to the // given signature. SignatureValues(tx *Transaction, sig []byte) (r, s, v *big.Int, err error) + ChainID() *big.Int // Hash returns 'signature hash', i.e. the transaction hash that is signed by the @@ -212,6 +216,20 @@ func (s londonSigner) PubKey(tx *Transaction) ([]byte, error) { return recoverPub(s.Hash(tx), R, S, V, true) } +func (s londonSigner) Signature(tx *Transaction) ([]byte, error) { + if tx.Type() != DynamicFeeTxType { + return s.eip2930Signer.PubKey(tx) + } + V, R, S := tx.RawSignatureValues() + // DynamicFee txs are defined to use 0 and 1 as their recovery + // id, add 27 to become equivalent to unprotected Homestead signatures. + V = new(big.Int).Add(V, big.NewInt(27)) + if tx.ChainId().Cmp(s.chainId) != 0 { + return nil, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, tx.ChainId(), s.chainId) + } + return recoverSig(s.Hash(tx), R, S, V, true) +} + func (s londonSigner) Equal(s2 Signer) bool { x, ok := s2.(londonSigner) return ok && x.chainId.Cmp(s.chainId) == 0 @@ -314,6 +332,28 @@ func (s eip2930Signer) PubKey(tx *Transaction) ([]byte, error) { return recoverPub(s.Hash(tx), R, S, V, true) } +func (s eip2930Signer) Signature(tx *Transaction) ([]byte, error) { + V, R, S := tx.RawSignatureValues() + switch tx.Type() { + case LegacyTxType: + if !tx.Protected() { + return HomesteadSigner{}.PubKey(tx) + } + V = new(big.Int).Sub(V, s.chainIdMul) + V.Sub(V, big8) + case AccessListTxType: + // AL txs are defined to use 0 and 1 as their recovery + // id, add 27 to become equivalent to unprotected Homestead signatures. + V = new(big.Int).Add(V, big.NewInt(27)) + default: + return nil, ErrTxTypeNotSupported + } + if tx.ChainId().Cmp(s.chainId) != 0 { + return nil, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, tx.ChainId(), s.chainId) + } + return recoverSig(s.Hash(tx), R, S, V, true) +} + func (s eip2930Signer) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big.Int, err error) { switch txdata := tx.inner.(type) { case *LegacyTx: @@ -427,6 +467,22 @@ func (s EIP155Signer) PubKey(tx *Transaction) ([]byte, error) { return recoverPub(s.Hash(tx), R, S, V, true) } +func (s EIP155Signer) Signature(tx *Transaction) ([]byte, error) { + if tx.Type() != LegacyTxType { + return nil, ErrTxTypeNotSupported + } + if !tx.Protected() { + return HomesteadSigner{}.Signature(tx) + } + if tx.ChainId().Cmp(s.chainId) != 0 { + return nil, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, tx.ChainId(), s.chainId) + } + V, R, S := tx.RawSignatureValues() + V = new(big.Int).Sub(V, s.chainIdMul) + V.Sub(V, big8) + return recoverSig(s.Hash(tx), R, S, V, true) +} + // SignatureValues returns signature values. This signature // needs to be in the [R || S || V] format where V is 0 or 1. func (s EIP155Signer) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big.Int, err error) { @@ -482,6 +538,14 @@ func (hs HomesteadSigner) Sender(tx *Transaction) (common.Address, error) { return recoverPlain(hs.Hash(tx), r, s, v, true) } +func (hs HomesteadSigner) Signature(tx *Transaction) ([]byte, error) { + if tx.Type() != LegacyTxType { + return nil, ErrTxTypeNotSupported + } + v, r, s := tx.RawSignatureValues() + return recoverSig(hs.Hash(tx), r, s, v, true) +} + // FrontierSigner implements Signer interface using the // frontier rules. type FrontierSigner struct{} @@ -511,6 +575,14 @@ func (fs FrontierSigner) PubKey(tx *Transaction) ([]byte, error) { return recoverPub(fs.Hash(tx), r, s, v, false) } +func (fs FrontierSigner) Signature(tx *Transaction) ([]byte, error) { + if tx.Type() != LegacyTxType { + return nil, ErrTxTypeNotSupported + } + v, r, s := tx.RawSignatureValues() + return recoverSig(fs.Hash(tx), r, s, v, false) +} + // SignatureValues returns signature values. This signature // needs to be in the [R || S || V] format where V is 0 or 1. func (fs FrontierSigner) SignatureValues(tx *Transaction, sig []byte) (r, s, v *big.Int, err error) { @@ -544,7 +616,7 @@ func decodeSignature(sig []byte) (r, s, v *big.Int) { return r, s, v } -func recoverPub(sighash common.Hash, R, S, Vb *big.Int, homestead bool) ([]byte, error) { +func recoverSig(sighash common.Hash, R, S, Vb *big.Int, homestead bool) ([]byte, error) { if Vb.BitLen() > 8 { return nil, ErrInvalidSig } @@ -558,7 +630,15 @@ func recoverPub(sighash common.Hash, R, S, Vb *big.Int, homestead bool) ([]byte, copy(sig[32-len(r):32], r) copy(sig[64-len(s):64], s) sig[64] = V + return sig, nil +} + +func recoverPub(sighash common.Hash, R, S, Vb *big.Int, homestead bool) ([]byte, error) { // recover the public key from the signature + sig, err := recoverSig(sighash, R, S, Vb, homestead) + if err != nil { + return nil, err + } pub, err := crypto.Ecrecover(sighash[:], sig) if err != nil { return nil, err diff --git a/ethclient/signer.go b/ethclient/signer.go index 8df14a5755de..9f1c247632eb 100644 --- a/ethclient/signer.go +++ b/ethclient/signer.go @@ -56,6 +56,11 @@ func (s *senderFromServer) PubKey(tx *types.Transaction) ([]byte, error) { return nil, nil } +func (s *senderFromServer) Signature(tx *types.Transaction) ([]byte, error) { + // not implemented + return nil, nil +} + func (s *senderFromServer) ChainID() *big.Int { panic("can't sign with senderFromServer") }