diff --git a/consensus/ethash/consensus.go b/consensus/ethash/consensus.go index dd9c81fd41b1..01d97a470e5f 100644 --- a/consensus/ethash/consensus.go +++ b/consensus/ethash/consensus.go @@ -287,8 +287,10 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent * // given the parent block's time and difficulty. // TODO (karalabe): Move the chain maker into this package and make this private! func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Header) *big.Int { - next := new(big.Int).Add(parent.Number, common.Big1) + next := new(big.Int).Add(parent.Number, big1) switch { + case config.IsMetropolis(next): + return calcDifficultyMetropolis(time, parent) case config.IsHomestead(next): return calcDifficultyHomestead(time, parent) default: @@ -299,10 +301,65 @@ func CalcDifficulty(config *params.ChainConfig, time uint64, parent *types.Heade // Some weird constants to avoid constant memory allocs for them. var ( expDiffPeriod = big.NewInt(100000) + big1 = big.NewInt(1) + big2 = big.NewInt(2) + big9 = big.NewInt(9) big10 = big.NewInt(10) bigMinus99 = big.NewInt(-99) ) +// calcDifficultyMetropolis is the difficulty adjustment algorithm. It returns +// the difficulty that a new block should have when created at time given the +// parent block's time and difficulty. The calculation uses the Metropolis rules. +func calcDifficultyMetropolis(time uint64, parent *types.Header) *big.Int { + // https://github.com/ethereum/EIPs/issues/100. + // algorithm: + // diff = (parent_diff + + // (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)) + // ) + 2^(periodCount - 2) + + bigTime := new(big.Int).SetUint64(time) + bigParentTime := new(big.Int).Set(parent.Time) + + // holds intermediate values to make the algo easier to read & audit + x := new(big.Int) + y := new(big.Int) + + // (2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // 9 + x.Sub(bigTime, bigParentTime) + x.Div(x, big9) + if parent.UncleHash == types.EmptyUncleHash { + x.Sub(big1, x) + } else { + x.Sub(big2, x) + } + // max((2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // 9, -99) + if x.Cmp(bigMinus99) < 0 { + x.Set(bigMinus99) + } + // (parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99)) + y.Div(parent.Difficulty, params.DifficultyBoundDivisor) + x.Mul(y, x) + x.Add(parent.Difficulty, x) + + // minimum difficulty can ever be (before exponential factor) + if x.Cmp(params.MinimumDifficulty) < 0 { + x.Set(params.MinimumDifficulty) + } + // for the exponential factor + periodCount := new(big.Int).Add(parent.Number, big1) + periodCount.Div(periodCount, expDiffPeriod) + + // the exponential factor, commonly referred to as "the bomb" + // diff = diff + 2^(periodCount - 2) + if periodCount.Cmp(big1) > 0 { + y.Sub(periodCount, big2) + y.Exp(big2, y, nil) + x.Add(x, y) + } + return x +} + // calcDifficultyHomestead is the difficulty adjustment algorithm. It returns // the difficulty that a new block should have when created at time given the // parent block's time and difficulty. The calculation uses the Homestead rules. @@ -320,12 +377,12 @@ func calcDifficultyHomestead(time uint64, parent *types.Header) *big.Int { x := new(big.Int) y := new(big.Int) - // 1 - (block_timestamp -parent_timestamp) // 10 + // 1 - (block_timestamp - parent_timestamp) // 10 x.Sub(bigTime, bigParentTime) x.Div(x, big10) - x.Sub(common.Big1, x) + x.Sub(big1, x) - // max(1 - (block_timestamp - parent_timestamp) // 10, -99))) + // max(1 - (block_timestamp - parent_timestamp) // 10, -99) if x.Cmp(bigMinus99) < 0 { x.Set(bigMinus99) } @@ -339,14 +396,14 @@ func calcDifficultyHomestead(time uint64, parent *types.Header) *big.Int { x.Set(params.MinimumDifficulty) } // for the exponential factor - periodCount := new(big.Int).Add(parent.Number, common.Big1) + periodCount := new(big.Int).Add(parent.Number, big1) periodCount.Div(periodCount, expDiffPeriod) // the exponential factor, commonly referred to as "the bomb" // diff = diff + 2^(periodCount - 2) - if periodCount.Cmp(common.Big1) > 0 { - y.Sub(periodCount, common.Big2) - y.Exp(common.Big2, y, nil) + if periodCount.Cmp(big1) > 0 { + y.Sub(periodCount, big2) + y.Exp(big2, y, nil) x.Add(x, y) } return x @@ -373,12 +430,12 @@ func calcDifficultyFrontier(time uint64, parent *types.Header) *big.Int { diff.Set(params.MinimumDifficulty) } - periodCount := new(big.Int).Add(parent.Number, common.Big1) + periodCount := new(big.Int).Add(parent.Number, big1) periodCount.Div(periodCount, expDiffPeriod) - if periodCount.Cmp(common.Big1) > 0 { + if periodCount.Cmp(big1) > 0 { // diff = diff + 2^(periodCount - 2) - expDiff := periodCount.Sub(periodCount, common.Big2) - expDiff.Exp(common.Big2, expDiff, nil) + expDiff := periodCount.Sub(periodCount, big2) + expDiff.Exp(big2, expDiff, nil) diff.Add(diff, expDiff) diff = math.BigMax(diff, params.MinimumDifficulty) } diff --git a/core/chain_makers.go b/core/chain_makers.go index 38a69d42a9bf..976a8114d3af 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -218,6 +218,7 @@ func makeHeader(config *params.ChainConfig, parent *types.Block, state *state.St Number: parent.Number(), Time: new(big.Int).Sub(time, big.NewInt(10)), Difficulty: parent.Difficulty(), + UncleHash: parent.UncleHash(), }), GasLimit: CalcGasLimit(parent), GasUsed: new(big.Int), diff --git a/core/state_processor.go b/core/state_processor.go index 90f5a4f60c90..158a9fa2dfba 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -105,10 +105,15 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common // Update the state with pending changes usedGas.Add(usedGas, gas) + var root []byte + if config.IsMetropolis(header.Number) { + statedb.Finalise() + } else { + root = statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes() + } // Create a new receipt for the transaction, storing the intermediate root and gas used by the tx // based on the eip phase, we're passing wether the root touch-delete accounts. - root := statedb.IntermediateRoot(config.IsEIP158(header.Number)) - receipt := types.NewReceipt(root.Bytes(), usedGas) + receipt := types.NewReceipt(root, usedGas) receipt.TxHash = tx.Hash() receipt.GasUsed = new(big.Int).Set(gas) // if the transaction created a contract, store the creation address in the receipt. diff --git a/core/state_transition.go b/core/state_transition.go index 0ae9d7fcbf8c..c6d7a5b68aa4 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -236,7 +236,8 @@ func (st *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *big vmerr error ) if contractCreation { - ret, _, st.gas, vmerr = evm.Create(sender, st.data, st.gas, st.value) + createAddressFn := vm.CreateAddressFn(st.evm.ChainConfig(), st.evm.BlockNumber, sender.Address(), st.state.GetNonce(sender.Address()), st.data) + ret, _, st.gas, vmerr = evm.Create(sender, createAddressFn, st.data, st.gas, st.value) } else { // Increment the nonce for the next transaction st.state.SetNonce(sender.Address(), st.state.GetNonce(sender.Address())+1) diff --git a/core/types/gen_receipt_json.go b/core/types/gen_receipt_json.go index edbd64ba4e3e..eb2e5d42b421 100644 --- a/core/types/gen_receipt_json.go +++ b/core/types/gen_receipt_json.go @@ -13,7 +13,7 @@ import ( func (r Receipt) MarshalJSON() ([]byte, error) { type Receipt struct { - PostState hexutil.Bytes `json:"root" gencodec:"required"` + PostState hexutil.Bytes `json:"root"` CumulativeGasUsed *hexutil.Big `json:"cumulativeGasUsed" gencodec:"required"` Bloom Bloom `json:"logsBloom" gencodec:"required"` Logs []*Log `json:"logs" gencodec:"required"` @@ -34,7 +34,7 @@ func (r Receipt) MarshalJSON() ([]byte, error) { func (r *Receipt) UnmarshalJSON(input []byte) error { type Receipt struct { - PostState hexutil.Bytes `json:"root" gencodec:"required"` + PostState hexutil.Bytes `json:"root"` CumulativeGasUsed *hexutil.Big `json:"cumulativeGasUsed" gencodec:"required"` Bloom *Bloom `json:"logsBloom" gencodec:"required"` Logs []*Log `json:"logs" gencodec:"required"` @@ -46,10 +46,9 @@ func (r *Receipt) UnmarshalJSON(input []byte) error { if err := json.Unmarshal(input, &dec); err != nil { return err } - if dec.PostState == nil { - return errors.New("missing required field 'root' for Receipt") + if dec.PostState != nil { + r.PostState = dec.PostState } - r.PostState = dec.PostState if dec.CumulativeGasUsed == nil { return errors.New("missing required field 'cumulativeGasUsed' for Receipt") } diff --git a/core/types/receipt.go b/core/types/receipt.go index ef6f6a2bb228..46d2530bbcc2 100644 --- a/core/types/receipt.go +++ b/core/types/receipt.go @@ -31,7 +31,7 @@ import ( // Receipt represents the results of a transaction. type Receipt struct { // Consensus fields - PostState []byte `json:"root" gencodec:"required"` + PostState []byte `json:"root"` CumulativeGasUsed *big.Int `json:"cumulativeGasUsed" gencodec:"required"` Bloom Bloom `json:"logsBloom" gencodec:"required"` Logs []*Log `json:"logs" gencodec:"required"` @@ -48,6 +48,19 @@ type receiptMarshaling struct { GasUsed *hexutil.Big } +type homesteadReceiptRLP struct { + PostState []byte + CumulativeGasUsed *big.Int + Bloom Bloom + Logs []*Log +} + +type metropolisReceiptRLP struct { + CumulativeGasUsed *big.Int + Bloom Bloom + Logs []*Log +} + // NewReceipt creates a barebone transaction receipt, copying the init fields. func NewReceipt(root []byte, cumulativeGasUsed *big.Int) *Receipt { return &Receipt{PostState: common.CopyBytes(root), CumulativeGasUsed: new(big.Int).Set(cumulativeGasUsed)} @@ -56,23 +69,28 @@ func NewReceipt(root []byte, cumulativeGasUsed *big.Int) *Receipt { // EncodeRLP implements rlp.Encoder, and flattens the consensus fields of a receipt // into an RLP stream. func (r *Receipt) EncodeRLP(w io.Writer) error { - return rlp.Encode(w, []interface{}{r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs}) + if r.PostState == nil { + return rlp.Encode(w, &metropolisReceiptRLP{r.CumulativeGasUsed, r.Bloom, r.Logs}) + } else { + return rlp.Encode(w, &homesteadReceiptRLP{r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs}) + } } // DecodeRLP implements rlp.Decoder, and loads the consensus fields of a receipt // from an RLP stream. func (r *Receipt) DecodeRLP(s *rlp.Stream) error { - var receipt struct { - PostState []byte - CumulativeGasUsed *big.Int - Bloom Bloom - Logs []*Log - } - if err := s.Decode(&receipt); err != nil { + raw, err := s.Raw() + if err != nil { return err } - r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs = receipt.PostState, receipt.CumulativeGasUsed, receipt.Bloom, receipt.Logs - return nil + var hr homesteadReceiptRLP + var mr metropolisReceiptRLP + if err = rlp.DecodeBytes(raw, &mr); err == nil { + r.CumulativeGasUsed, r.Bloom, r.Logs = mr.CumulativeGasUsed, mr.Bloom, mr.Logs + } else if err = rlp.DecodeBytes(raw, &hr); err == nil { + r.PostState, r.CumulativeGasUsed, r.Bloom, r.Logs = hr.PostState[:], hr.CumulativeGasUsed, hr.Bloom, hr.Logs + } + return err } // String implements the Stringer interface. diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go index b0f3275b2a44..514b848a5af7 100644 --- a/core/types/transaction_signing.go +++ b/core/types/transaction_signing.go @@ -45,6 +45,8 @@ type sigCache struct { func MakeSigner(config *params.ChainConfig, blockNumber *big.Int) Signer { var signer Signer switch { + case config.IsMetropolis(blockNumber): + signer = NewEIP86Signer(config.ChainId) case config.IsEIP155(blockNumber): signer = NewEIP155Signer(config.ChainId) case config.IsHomestead(blockNumber): @@ -88,6 +90,10 @@ func Sender(signer Signer, tx *Transaction) (common.Address, error) { pubkey, err := signer.PublicKey(tx) if err != nil { + if err == errAbstractSigner { + return abstractSignerAddress, nil + } + return common.Address{}, err } var addr common.Address @@ -108,6 +114,37 @@ type Signer interface { Equal(Signer) bool } +// EIP86Signer implements the the abstract signing feature +type EIP86Signer struct { + EIP155Signer +} + +func NewEIP86Signer(chainId *big.Int) EIP86Signer { + return EIP86Signer{ + EIP155Signer: NewEIP155Signer(chainId), + } +} + +func (s EIP86Signer) Equal(s2 Signer) bool { + _, ok := s2.(EIP86Signer) + return ok && s.EIP155Signer.Equal(s2) +} + +// isAbstractSigner checks whether the transaction signature is that of +// the abstract signer. The abstract signer is determined by V being equal +// to the chain identifier and r and s being 0. +func isAbstractSigner(tx *Transaction, chainId *big.Int) bool { + v, r, s := tx.RawSignatureValues() + return v.Cmp(chainId) == 0 && r.BitLen() == 0 && s.BitLen() == 0 +} + +func (s EIP86Signer) PublicKey(tx *Transaction) ([]byte, error) { + if isAbstractSigner(tx, s.chainId) { + return nil, errAbstractSigner + } + return s.EIP155Signer.PublicKey(tx) +} + // EIP155Transaction implements TransactionInterface using the // EIP155 rules type EIP155Signer struct { diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 90b2f913e667..68891c2f78ae 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -22,7 +22,9 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/crypto/bn256" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "golang.org/x/crypto/ripemd160" @@ -46,6 +48,19 @@ var PrecompiledContracts = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{4}): &dataCopy{}, } +// PrecompiledContractsMetropolis contains the default set of ethereum contracts +// for metropolis hardfork +var PrecompiledContractsMetropolis = map[common.Address]PrecompiledContract{ + common.BytesToAddress([]byte{1}): &ecrecover{}, + common.BytesToAddress([]byte{2}): &sha256hash{}, + common.BytesToAddress([]byte{3}): &ripemd160hash{}, + common.BytesToAddress([]byte{4}): &dataCopy{}, + common.BytesToAddress([]byte{5}): &bigModexp{}, + common.BytesToAddress([]byte{6}): &bn256Add{}, + common.BytesToAddress([]byte{7}): &bn256ScalarMul{}, + common.BytesToAddress([]byte{8}): &pairing{}, +} + // RunPrecompile runs and evaluate the output of a precompiled contract defined in contracts.go func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error) { gas := p.RequiredGas(input) @@ -135,3 +150,190 @@ func (c *dataCopy) RequiredGas(input []byte) uint64 { func (c *dataCopy) Run(in []byte) ([]byte, error) { return in, nil } + +// bigModexp implements a native big integer exponential modular operation. +type bigModexp struct{} + +// 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 +// required for anything significant is so high it's impossible to pay for. +func (c *bigModexp) RequiredGas(input []byte) uint64 { + // TODO reword required gas to have error reporting and convert arithmetic + // to uint64. + if len(input) < 3*32 { + input = append(input, make([]byte, 3*32-len(input))...) + } + var ( + baseLen = new(big.Int).SetBytes(input[:31]) + expLen = math.BigMax(new(big.Int).SetBytes(input[32:64]), big.NewInt(1)) + modLen = new(big.Int).SetBytes(input[65:97]) + ) + x := new(big.Int).Set(math.BigMax(baseLen, modLen)) + x.Mul(x, x) + x.Mul(x, expLen) + x.Div(x, new(big.Int).SetUint64(params.QuadCoeffDiv)) + + return x.Uint64() +} + +func (c *bigModexp) Run(input []byte) ([]byte, error) { + if len(input) < 3*32 { + input = append(input, make([]byte, 3*32-len(input))...) + } + // why 32-byte? These values won't fit anyway + var ( + baseLen = new(big.Int).SetBytes(input[:32]).Uint64() + expLen = new(big.Int).SetBytes(input[32:64]).Uint64() + modLen = new(big.Int).SetBytes(input[64:96]).Uint64() + ) + + input = input[96:] + if uint64(len(input)) < baseLen { + input = append(input, make([]byte, baseLen-uint64(len(input)))...) + } + base := new(big.Int).SetBytes(input[:baseLen]) + + input = input[baseLen:] + if uint64(len(input)) < expLen { + input = append(input, make([]byte, expLen-uint64(len(input)))...) + } + exp := new(big.Int).SetBytes(input[:expLen]) + + input = input[expLen:] + if uint64(len(input)) < modLen { + input = append(input, make([]byte, modLen-uint64(len(input)))...) + } + mod := new(big.Int).SetBytes(input[:modLen]) + + return common.LeftPadBytes(base.Exp(base, exp, mod).Bytes(), len(input[:modLen])), nil +} + +type bn256Add struct{} + +// 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 +// required for anything significant is so high it's impossible to pay for. +func (c *bn256Add) RequiredGas(input []byte) uint64 { + return 0 // TODO +} + +func (c *bn256Add) Run(in []byte) ([]byte, error) { + in = common.RightPadBytes(in, 128) + + x, onCurve := new(bn256.G1).Unmarshal(in[:64]) + if !onCurve { + return nil, errNotOnCurve + } + gx, gy, _, _ := x.CurvePoints() + if gx.Cmp(bn256.P) >= 0 || gy.Cmp(bn256.P) >= 0 { + return nil, errInvalidCurvePoint + } + + y, onCurve := new(bn256.G1).Unmarshal(in[64:128]) + if !onCurve { + return nil, errNotOnCurve + } + gx, gy, _, _ = y.CurvePoints() + if gx.Cmp(bn256.P) >= 0 || gy.Cmp(bn256.P) >= 0 { + return nil, errInvalidCurvePoint + } + x.Add(x, y) + + return x.Marshal(), nil +} + +type bn256ScalarMul struct{} + +// 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 +// required for anything significant is so high it's impossible to pay for. +func (c *bn256ScalarMul) RequiredGas(input []byte) uint64 { + return 0 // TODO +} + +func (c *bn256ScalarMul) Run(in []byte) ([]byte, error) { + in = common.RightPadBytes(in, 96) + + g1, onCurve := new(bn256.G1).Unmarshal(in[:64]) + if !onCurve { + return nil, errNotOnCurve + } + x, y, _, _ := g1.CurvePoints() + if x.Cmp(bn256.P) >= 0 || y.Cmp(bn256.P) >= 0 { + return nil, errInvalidCurvePoint + } + g1.ScalarMult(g1, new(big.Int).SetBytes(in[64:96])) + + return g1.Marshal(), nil +} + +// pairing implements a pairing pre-compile for the bn256 curve +type pairing struct{} + +// 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 +// required for anything significant is so high it's impossible to pay for. +func (c *pairing) RequiredGas(input []byte) uint64 { + //return 0 // TODO + k := (len(input) + 191) / pairSize + return uint64(60000*k + 40000) +} + +const pairSize = 192 + +var ( + 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} + fals32Byte = make([]byte, 32) + errNotOnCurve = errors.New("point not on elliptic curve") + errInvalidCurvePoint = errors.New("invalid elliptic curve point") +) + +func (c *pairing) Run(in []byte) ([]byte, error) { + if len(in) == 0 { + return true32Byte, nil + } + + if len(in)%pairSize > 0 { + return nil, errBadPrecompileInput + } + + var ( + g1s []*bn256.G1 + g2s []*bn256.G2 + ) + for i := 0; i < len(in); i += pairSize { + g1, onCurve := new(bn256.G1).Unmarshal(in[i : i+64]) + if !onCurve { + return nil, errNotOnCurve + } + + x, y, _, _ := g1.CurvePoints() + if x.Cmp(bn256.P) >= 0 || y.Cmp(bn256.P) >= 0 { + return nil, errInvalidCurvePoint + } + + g2, onCurve := new(bn256.G2).Unmarshal(in[i+64 : i+192]) + if !onCurve { + return nil, errNotOnCurve + } + x2, y2, _, _ := g2.CurvePoints() + if x2.Real().Cmp(bn256.P) >= 0 || x2.Imag().Cmp(bn256.P) >= 0 || + y2.Real().Cmp(bn256.P) >= 0 || y2.Imag().Cmp(bn256.P) >= 0 { + return nil, errInvalidCurvePoint + } + + g1s = append(g1s, g1) + g2s = append(g2s, g2) + } + + isOne := bn256.PairingCheck(g1s, g2s) + if isOne { + return true32Byte, nil + } + + return fals32Byte, nil +} diff --git a/core/vm/contracts_test.go b/core/vm/contracts_test.go index 830a8f69d995..2b4070ede7e0 100644 --- a/core/vm/contracts_test.go +++ b/core/vm/contracts_test.go @@ -1 +1,35 @@ package vm + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" +) + +const input = "" + +func TestPairing(t *testing.T) { + pairing := &pairing{} + + for i, test := range []struct { + input string + valid int + }{ + {"1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", 1}, + {"2eca0c7238bf16e83e7a1e6c5d49540685ff51380f309842a98561558019fc0203d3260361bb8451de5ff5ecd17f010ff22f5c31cdf184e9020b06fa5997db841213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f06967a1237ebfeca9aaae0d6d0bab8e28c198c5a339ef8a2407e31cdac516db922160fa257a5fd5b280642ff47b65eca77e626cb685c84fa6d3b6882a283ddd1198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", 1}, + {"0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb314a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee245901b9e027bd5cfc2cb5db82d4dc9677ac795ec500ecd47deee3b5da006d6d049b811d7511c78158de484232fc68daf8a45cf217d1c2fae693ff5871e8752d73b21198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", 1}, + {"2f2ea0b3da1e8ef11914acf8b2e1b32d99df51f5f4f206fc6b947eae860eddb6068134ddb33dc888ef446b648d72338684d678d2eb2371c61a50734d78da4b7225f83c8b6ab9de74e7da488ef02645c5a16a6652c3c71a15dc37fe3a5dcb7cb122acdedd6308e3bb230d226d16a105295f523a8a02bfc5e8bd2da135ac4c245d065bbad92e7c4e31bf3757f1fe7362a63fbfee50e7dc68da116e67d600d9bf6806d302580dc0661002994e7cd3a7f224e7ddc27802777486bf80f40e4ca3cfdb186bac5188a98c45e6016873d107f5cd131f3a3e339d0375e58bd6219347b008122ae2b09e539e152ec5364e7e2204b03d11d3caa038bfc7cd499f8176aacbee1f39e4e4afc4bc74790a4a028aff2c3d2538731fb755edefd8cb48d6ea589b5e283f150794b6736f670d6a1033f9b46c6f5204f50813eb85c8dc4b59db1c5d39140d97ee4d2b36d99bc49974d18ecca3e7ad51011956051b464d9e27d46cc25e0764bb98575bd466d32db7b15f582b2d5c452b36aa394b789366e5e3ca5aabd415794ab061441e51d01e94640b7e3084a07e02c78cf3103c542bc5b298669f211b88da1679b0b64a63b7e0e7bfe52aae524f73a55be7fe70c7e9bfc94b4cf0da1213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f", 1}, + {"20a754d2071d4d53903e3b31a7e98ad6882d58aec240ef981fdf0a9d22c5926a29c853fcea789887315916bbeb89ca37edb355b4f980c9a12a94f30deeed30211213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f1abb4a25eb9379ae96c84fff9f0540abcfc0a0d11aeda02d4f37e4baf74cb0c11073b3ff2cdbb38755f8691ea59e9606696b3ff278acfc098fa8226470d03869217cee0a9ad79a4493b5253e2e4e3a39fc2df38419f230d341f60cb064a0ac290a3d76f140db8418ba512272381446eb73958670f00cf46f1d9e64cba057b53c26f64a8ec70387a13e41430ed3ee4a7db2059cc5fc13c067194bcc0cb49a98552fd72bd9edb657346127da132e5b82ab908f5816c826acb499e22f2412d1a2d70f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2198a1f162a73261f112401aa2db79c7dab1533c9935c77290a6ce3b191f2318d198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", 1}, + {"1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c103188585e2364128fe25c70558f1560f4f9350baf3959e603cc91486e110936198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", 0}, + } { + r, err := pairing.Run(common.FromHex(test.input)) + if err != nil { + t.Error(i, ":", err) + } + + if int(r[31]) != test.valid { + t.Error(i, "expected", test.valid, "but was", r[31]) + } + } + +} diff --git a/core/vm/evm.go b/core/vm/evm.go index 9296cc7cac28..38916cc95626 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -37,6 +37,10 @@ type ( func run(evm *EVM, snapshot int, contract *Contract, input []byte) ([]byte, error) { if contract.CodeAddr != nil { precompiledContracts := PrecompiledContracts + if evm.ChainConfig().IsMetropolis(evm.BlockNumber) { + precompiledContracts = PrecompiledContractsMetropolis + } + if p := precompiledContracts[*contract.CodeAddr]; p != nil { return RunPrecompiledContract(p, input, contract) } @@ -100,8 +104,8 @@ type EVM struct { abort int32 } -// NewEVM retutrns a new EVM evmironment. The returned EVM is not thread safe -// and should only ever be used *once*. +// NewEVM retutrns a new EVM . The returned EVM is not thread safe and should +// only ever be used *once*. func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM { evm := &EVM{ Context: ctx, @@ -121,6 +125,51 @@ func (evm *EVM) Cancel() { atomic.StoreInt32(&evm.abort, 1) } +func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { + if evm.vmConfig.NoRecursion && evm.depth > 0 { + return nil, gas, nil + } + + // Depth check execution. Fail if we're trying to execute above the + // limit. + if evm.depth > int(params.CallCreateDepth) { + return nil, gas, ErrDepth + } + + // make sure the readonly is only set if we aren't in readonly yet + // this makes also sure that the readonly flag isn't removed for + // child calls. + if !evm.interpreter.readonly { + evm.interpreter.readonly = true + defer func() { evm.interpreter.readonly = false }() + } + + var ( + to = AccountRef(addr) + snapshot = evm.StateDB.Snapshot() + ) + if !evm.StateDB.Exist(addr) { + return nil, gas, nil + } + + // initialise a new contract and set the code that is to be used by the + // EVM. The contract is a scoped evmironment for this execution context + // only. + contract := NewContract(caller, to, new(big.Int), gas) + contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) + + ret, err = evm.interpreter.Run(snapshot, contract, input) + // When an error was returned by the EVM or when setting the creation code + // above we revert to the snapshot and consume any gas remaining. Additionally + // when we're in homestead this also counts for code storage gas errors. + if err != nil { + contract.UseGas(contract.Gas) + + evm.StateDB.RevertToSnapshot(snapshot) + } + return ret, contract.Gas, err +} + // 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 execution error or failed value transfer. @@ -241,7 +290,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by } // Create creates a new contract using code as deployment code. -func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { +func (evm *EVM) Create(caller ContractRef, createAddress addressCreationFn, code []byte, gas uint64, value *big.Int) (ret []byte, _ common.Address, leftOverGas uint64, err error) { if evm.vmConfig.NoRecursion && evm.depth > 0 { return nil, common.Address{}, gas, nil } @@ -260,7 +309,9 @@ func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.I evm.StateDB.SetNonce(caller.Address(), nonce+1) snapshot := evm.StateDB.Snapshot() - contractAddr = crypto.CreateAddress(caller.Address(), nonce) + + contractAddr := createAddress() + evm.StateDB.CreateAccount(contractAddr) if evm.ChainConfig().IsEIP158(evm.BlockNumber) { evm.StateDB.SetNonce(contractAddr, 1) @@ -312,3 +363,5 @@ func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig } // Interpreter returns the EVM interpreter func (evm *EVM) Interpreter() *Interpreter { return evm.interpreter } + +type addressCreationFn func() common.Address diff --git a/core/vm/gas_table.go b/core/vm/gas_table.go index 761ca44507c9..5921e26631ef 100644 --- a/core/vm/gas_table.go +++ b/core/vm/gas_table.go @@ -91,6 +91,32 @@ func gasCalldataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *St return gas, nil } +func gasReturnDataCopy(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + gas, err := memoryGasCost(mem, memorySize) + if err != nil { + return 0, err + } + + var overflow bool + if gas, overflow = math.SafeAdd(gas, GasFastestStep); overflow { + return 0, errGasUintOverflow + } + + words, overflow := bigUint64(stack.Back(2)) + if overflow { + return 0, errGasUintOverflow + } + + if words, overflow = math.SafeMul(toWordSize(words), params.CopyGas); overflow { + return 0, errGasUintOverflow + } + + if gas, overflow = math.SafeAdd(gas, words); overflow { + return 0, errGasUintOverflow + } + return gas, nil +} + func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { var ( y, x = stack.Back(1), stack.Back(0) @@ -423,6 +449,35 @@ func gasDelegateCall(gt params.GasTable, evm *EVM, contract *Contract, stack *St return gas, nil } +func gasStaticCall(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { + panic("verify this one") + + gas, err := memoryGasCost(mem, memorySize) + if err != nil { + return 0, err + } + var overflow bool + if gas, overflow = math.SafeAdd(gas, gt.Calls); overflow { + return 0, errGasUintOverflow + } + + cg, err := callGas(gt, contract.Gas, gas, stack.Back(0)) + if err != nil { + return 0, err + } + // Replace the stack item with the new gas calculation. This means that + // either the original item is left on the stack or the item is replaced by: + // (availableGas - gas) * 63 / 64 + // We replace the stack item so that it's available when the opCall instruction is + // called. + stack.data[stack.len()-1] = new(big.Int).SetUint64(cg) + + if gas, overflow = math.SafeAdd(gas, cg); overflow { + return 0, errGasUintOverflow + } + return gas, nil +} + func gasPush(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) { return GasFastestStep, nil } diff --git a/core/vm/instructions.go b/core/vm/instructions.go index f5164fcdd43e..353632f13acd 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -17,6 +17,7 @@ package vm import ( + "errors" "fmt" "math/big" @@ -28,7 +29,9 @@ import ( ) var ( - bigZero = new(big.Int) + bigZero = new(big.Int) + errWriteProtection = errors.New("evm: write protection") + errReadOutOfBound = errors.New("evm: read out of bound") ) func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { @@ -539,6 +542,18 @@ func opGas(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac return nil, nil } +func CreateAddressFn(chainConfig *params.ChainConfig, blockNumber *big.Int, senderAddress common.Address, nonce uint64, input []byte) func() common.Address { + if chainConfig.IsMetropolis(blockNumber) { + return func() common.Address { + return common.BytesToAddress(crypto.Keccak256(senderAddress.Bytes(), crypto.Keccak256(input))[12:]) + } + } else { + return func() common.Address { + return crypto.CreateAddress(senderAddress, nonce) + } + } +} + func opCreate(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { var ( value = stack.pop() @@ -550,8 +565,10 @@ func opCreate(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S gas -= gas / 64 } + createAddressFn := CreateAddressFn(evm.ChainConfig(), evm.BlockNumber, contract.Address(), evm.StateDB.GetNonce(contract.Address()), input) + contract.UseGas(gas) - _, addr, returnGas, suberr := evm.Create(contract, input, gas, value) + _, addr, returnGas, suberr := evm.Create(contract, createAddressFn, input, gas, value) // Push item on the stack based on the returned error. If the ruleset is // homestead we must check for CodeStoreOutOfGasError (homestead only // rule) and treat as an error, if the ruleset is frontier we must @@ -570,6 +587,71 @@ func opCreate(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S return nil, nil } +func opCreate2(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { + var ( + value = stack.pop() + salt = stack.pop() + offset, size = stack.pop(), stack.pop() + input = memory.Get(offset.Int64(), size.Int64()) + gas = contract.Gas + ) + if evm.ChainConfig().IsEIP150(evm.BlockNumber) { + gas -= gas / 64 + } + + createAddress := func() common.Address { + return common.BytesToAddress(crypto.Keccak256(contract.Address().Bytes(), salt.Bytes(), crypto.Keccak256(input))[12:]) + } + + contract.UseGas(gas) + _, addr, returnGas, suberr := evm.Create(contract, createAddress, input, gas, value) + // Push item on the stack based on the returned error. If the ruleset is + // homestead we must check for CodeStoreOutOfGasError (homestead only + // rule) and treat as an error, if the ruleset is frontier we must + // ignore this error and pretend the operation was successful. + if evm.ChainConfig().IsHomestead(evm.BlockNumber) && suberr == ErrCodeStoreOutOfGas { + stack.push(new(big.Int)) + } else if suberr != nil && suberr != ErrCodeStoreOutOfGas { + stack.push(new(big.Int)) + } else { + stack.push(addr.Big()) + } + contract.Gas += returnGas + + evm.interpreter.intPool.put(value, offset, size) + + return nil, nil +} + +func opStaticCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { + // pop gas + gas := stack.pop().Uint64() + // pop address + addr := stack.pop() + // pop input size and offset + inOffset, inSize := stack.pop(), stack.pop() + // pop return size and offset + retOffset, retSize := stack.pop(), stack.pop() + + address := common.BigToAddress(addr) + + // Get the arguments from the memory + args := memory.Get(inOffset.Int64(), inSize.Int64()) + + ret, returnGas, err := evm.StaticCall(contract, address, args, gas) + if err != nil { + stack.push(new(big.Int)) + } else { + stack.push(big.NewInt(1)) + + memory.Set(retOffset.Uint64(), retSize.Uint64(), ret) + } + contract.Gas += returnGas + + evm.interpreter.intPool.put(addr, inOffset, inSize, retOffset, retSize) + return ret, nil +} + func opCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { gas := stack.pop().Uint64() // pop gas and value of the stack. @@ -665,6 +747,14 @@ func opReturn(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S return ret, nil } +func opRevert(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { + offset, size := stack.pop(), stack.pop() + ret := memory.GetPtr(offset.Int64(), size.Int64()) + + evm.interpreter.intPool.put(offset, size) + return ret, nil +} + func opStop(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { return nil, nil } @@ -678,6 +768,28 @@ func opSuicide(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack * return nil, nil } +func opReturnDataSize(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { + stack.push(evm.interpreter.intPool.get().SetUint64(uint64(len(evm.interpreter.returnData)))) + return nil, nil +} + +func opReturnDataCopy(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { + var ( + mOff = stack.pop() + cOff = stack.pop() + l = stack.pop() + ) + defer evm.interpreter.intPool.put(mOff, cOff, l) + + cEnd := new(big.Int).Add(cOff, l) + if cEnd.BitLen() > 64 || uint64(len(evm.interpreter.returnData)) < cEnd.Uint64() { + return nil, errReadOutOfBound + } + memory.Set(mOff.Uint64(), l.Uint64(), evm.interpreter.returnData[cOff.Uint64():cEnd.Uint64()]) + + return nil, nil +} + // following functions are used by the instruction jump table // make log instruction function diff --git a/core/vm/instructions_test.go b/core/vm/instructions_test.go index 03c42c561c83..0ba86e56eb0e 100644 --- a/core/vm/instructions_test.go +++ b/core/vm/instructions_test.go @@ -64,85 +64,278 @@ func opBenchmark(bench *testing.B, op func(pc *uint64, evm *EVM, contract *Contr } } -func precompiledBenchmark(addr, input, expected string, gas uint64, bench *testing.B) { +func precompiledBenchmark(addr string, test testCase, bench *testing.B) { + p := PrecompiledContractsMetropolis[common.HexToAddress(addr)] + in := common.Hex2Bytes(test.input) + reqGas := p.RequiredGas(in) contract := NewContract(AccountRef(common.HexToAddress("1337")), - nil, new(big.Int), gas) + nil, new(big.Int), reqGas) - p := PrecompiledContracts[common.HexToAddress(addr)] - in := common.Hex2Bytes(input) var ( - res []byte - err error + res []byte + err error + data = make([]byte, len(in)) ) - data := make([]byte, len(in)) - bench.ResetTimer() - for i := 0; i < bench.N; i++ { - contract.Gas = gas - copy(data, in) - res, err = RunPrecompiledContract(p, data, contract) - } - bench.StopTimer() - //Check if it is correct - if err != nil { - bench.Error(err) - return - } - if common.Bytes2Hex(res) != expected { - bench.Error(fmt.Sprintf("Expected %v, got %v", expected, common.Bytes2Hex(res))) - return - } + + bench.Run(fmt.Sprintf("%s-Gas=%d", test.name, contract.Gas), func(bench *testing.B) { + bench.ResetTimer() + for i := 0; i < bench.N; i++ { + contract.Gas = reqGas + copy(data, in) + res, err = RunPrecompiledContract(p, data, contract) + } + bench.StopTimer() + //Check if it is correct + if err != nil { + bench.Error(err) + return + } + if common.Bytes2Hex(res) != test.expected { + bench.Error(fmt.Sprintf("Expected %v, got %v", test.expected, common.Bytes2Hex(res))) + return + } + + }) +} + +func precompiledTest(addr string, test testCase, t *testing.T) { + + p := PrecompiledContractsMetropolis[common.HexToAddress(addr)] + in := common.Hex2Bytes(test.input) + contract := NewContract(AccountRef(common.HexToAddress("1337")), + nil, new(big.Int), p.RequiredGas(in)) + t.Run(fmt.Sprintf("%s-Gas=%d", test.name, contract.Gas), func(t *testing.T) { + if res, err := RunPrecompiledContract(p, in, contract); err != nil { + t.Error(err) + } else if common.Bytes2Hex(res) != test.expected { + t.Errorf("Expected %v, got %v", test.expected, common.Bytes2Hex(res)) + } + }) } func BenchmarkPrecompiledEcdsa(bench *testing.B) { - var ( - addr = "01" - inp = "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02" - exp = "000000000000000000000000ceaccac640adf55b2028469bd36ba501f28b699d" - gas = uint64(4000000) - ) - precompiledBenchmark(addr, inp, exp, gas, bench) + t := testCase{ + input: "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02", + expected: "000000000000000000000000ceaccac640adf55b2028469bd36ba501f28b699d", + name: "", + } + precompiledBenchmark("01", t, bench) } func BenchmarkPrecompiledSha256(bench *testing.B) { - var ( - addr = "02" - inp = "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02" - exp = "811c7003375852fabd0d362e40e68607a12bdabae61a7d068fe5fdd1dbbf2a5d" - gas = uint64(4000000) - ) - precompiledBenchmark(addr, inp, exp, gas, bench) + t := testCase{ + input: "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02", + expected: "811c7003375852fabd0d362e40e68607a12bdabae61a7d068fe5fdd1dbbf2a5d", + name: "128", + } + precompiledBenchmark("02", t, bench) } func BenchmarkPrecompiledRipeMD(bench *testing.B) { - var ( - addr = "03" - inp = "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02" - exp = "0000000000000000000000009215b8d9882ff46f0dfde6684d78e831467f65e6" - gas = uint64(4000000) - ) - precompiledBenchmark(addr, inp, exp, gas, bench) + t := testCase{ + input: "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02", + expected: "0000000000000000000000009215b8d9882ff46f0dfde6684d78e831467f65e6", + name: "128", + } + precompiledBenchmark("03", t, bench) } func BenchmarkPrecompiledIdentity(bench *testing.B) { - var ( - addr = "04" - inp = "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02" - exp = "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02" - gas = uint64(4000000) - ) - precompiledBenchmark(addr, inp, exp, gas, bench) + t := testCase{ + input: "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02", + expected: "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02", + name: "128", + } + precompiledBenchmark("04", t, bench) +} + +type testCase struct { + input, expected string + gas uint64 + name string +} + +var modexpTestcases = [...]testCase{ + {input: "0000000000000000000000000000000000000000000000000000000000000001" + + "0000000000000000000000000000000000000000000000000000000000000020" + + "0000000000000000000000000000000000000000000000000000000000000020" + + "03" + + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e" + + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + expected: "0000000000000000000000000000000000000000000000000000000000000001", + name: "eip_example1", + }, + {input: "0000000000000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000020" + + "0000000000000000000000000000000000000000000000000000000000000020" + + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e" + + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + expected: "0000000000000000000000000000000000000000000000000000000000000000", + name: "eip_example2", + }, +} +var pairingTestcases = []testCase{ + {input: "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + expected: "0000000000000000000000000000000000000000000000000000000000000001", + name: "jeff1"}, + {input: "2eca0c7238bf16e83e7a1e6c5d49540685ff51380f309842a98561558019fc0203d3260361bb8451de5ff5ecd17f010ff22f5c31cdf184e9020b06fa5997db841213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f06967a1237ebfeca9aaae0d6d0bab8e28c198c5a339ef8a2407e31cdac516db922160fa257a5fd5b280642ff47b65eca77e626cb685c84fa6d3b6882a283ddd1198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + expected: "0000000000000000000000000000000000000000000000000000000000000001", + name: "jeff2", + }, + {input: "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb314a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee245901b9e027bd5cfc2cb5db82d4dc9677ac795ec500ecd47deee3b5da006d6d049b811d7511c78158de484232fc68daf8a45cf217d1c2fae693ff5871e8752d73b21198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + expected: "0000000000000000000000000000000000000000000000000000000000000001", + name: "jeff3", + }, + {input: "2f2ea0b3da1e8ef11914acf8b2e1b32d99df51f5f4f206fc6b947eae860eddb6068134ddb33dc888ef446b648d72338684d678d2eb2371c61a50734d78da4b7225f83c8b6ab9de74e7da488ef02645c5a16a6652c3c71a15dc37fe3a5dcb7cb122acdedd6308e3bb230d226d16a105295f523a8a02bfc5e8bd2da135ac4c245d065bbad92e7c4e31bf3757f1fe7362a63fbfee50e7dc68da116e67d600d9bf6806d302580dc0661002994e7cd3a7f224e7ddc27802777486bf80f40e4ca3cfdb186bac5188a98c45e6016873d107f5cd131f3a3e339d0375e58bd6219347b008122ae2b09e539e152ec5364e7e2204b03d11d3caa038bfc7cd499f8176aacbee1f39e4e4afc4bc74790a4a028aff2c3d2538731fb755edefd8cb48d6ea589b5e283f150794b6736f670d6a1033f9b46c6f5204f50813eb85c8dc4b59db1c5d39140d97ee4d2b36d99bc49974d18ecca3e7ad51011956051b464d9e27d46cc25e0764bb98575bd466d32db7b15f582b2d5c452b36aa394b789366e5e3ca5aabd415794ab061441e51d01e94640b7e3084a07e02c78cf3103c542bc5b298669f211b88da1679b0b64a63b7e0e7bfe52aae524f73a55be7fe70c7e9bfc94b4cf0da1213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f", + expected: "0000000000000000000000000000000000000000000000000000000000000001", + name: "jeff4", + }, + {input: "20a754d2071d4d53903e3b31a7e98ad6882d58aec240ef981fdf0a9d22c5926a29c853fcea789887315916bbeb89ca37edb355b4f980c9a12a94f30deeed30211213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f1abb4a25eb9379ae96c84fff9f0540abcfc0a0d11aeda02d4f37e4baf74cb0c11073b3ff2cdbb38755f8691ea59e9606696b3ff278acfc098fa8226470d03869217cee0a9ad79a4493b5253e2e4e3a39fc2df38419f230d341f60cb064a0ac290a3d76f140db8418ba512272381446eb73958670f00cf46f1d9e64cba057b53c26f64a8ec70387a13e41430ed3ee4a7db2059cc5fc13c067194bcc0cb49a98552fd72bd9edb657346127da132e5b82ab908f5816c826acb499e22f2412d1a2d70f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2198a1f162a73261f112401aa2db79c7dab1533c9935c77290a6ce3b191f2318d198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + expected: "0000000000000000000000000000000000000000000000000000000000000001", + name: "jeff5", + }, + {input: "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c103188585e2364128fe25c70558f1560f4f9350baf3959e603cc91486e110936198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + expected: "0000000000000000000000000000000000000000000000000000000000000000", + name: "jeff6"}, + { // ecpairing_empty_data_insufficient_gas + input: "", + expected: "0000000000000000000000000000000000000000000000000000000000000001", + name: "empty_data"}, + { // ecpairing_one_point_insufficient_gas + input: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + expected: "0000000000000000000000000000000000000000000000000000000000000000", + name: "one_point"}, + { // ecpairing_two_point_match_2 + input: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d", + expected: "0000000000000000000000000000000000000000000000000000000000000001", + name: "two_point_match_2"}, + { // ecpairing_two_point_match_3 + input: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + expected: "0000000000000000000000000000000000000000000000000000000000000001", + name: "two_point_match_3"}, + { // ecpairing_two_point_match_4 + input: "105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c51bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e60071f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b4a106054688728c9972c8512e9789e9567aae23e302ccd75", + expected: "0000000000000000000000000000000000000000000000000000000000000001", + name: "two_point_match_4"}, + { + input: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d", + expected: "0000000000000000000000000000000000000000000000000000000000000001", + name: "ten_point_match_1"}, + { + input: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + expected: "0000000000000000000000000000000000000000000000000000000000000001", + name: "ten_point_match_2"}, + { // ecpairing_two_point_match_4 + input: "105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c51bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e60071f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b4a106054688728c9972c8512e9789e9567aae23e302ccd75", + expected: "0000000000000000000000000000000000000000000000000000000000000001", + name: "ten_point_match_3"}, +} + +var bn256AddTestcases = []testCase{ + {input: "18b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f3726607c2b7f58a84bd6145f00c9c2bc0bb1a187f20ff2c92963a88019e7c6a014eed06614e20c147e940f2d70da3f74c9a17df361706a4485c742bd6788478fa17d7", + expected: "2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c915", + name: "chfast1"}, + {input: "2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c91518b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f37266", + expected: "2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb721611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb204", + name: "chfast2"}, +} + +var bn256MulTestcases = []testCase{ + {input: "2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb721611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb20400000000000000000000000000000000000000000000000011138ce750fa15c2", + expected: "070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc", + name: "chfast1"}, + {input: "070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46", + expected: "025a6f4181d2b4ea8b724290ffb40156eb0adb514c688556eb79cdea0752c2bb2eff3f31dea215f1eb86023a133a996eb6300b44da664d64251d05381bb8a02e", + name: "chfast2"}, + {input: "025a6f4181d2b4ea8b724290ffb40156eb0adb514c688556eb79cdea0752c2bb2eff3f31dea215f1eb86023a133a996eb6300b44da664d64251d05381bb8a02e183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7ea3", + expected: "14789d0d4a730b354403b5fac948113739e276c23e0258d8596ee72f9cd9d3230af18a63153e0ec25ff9f2951dd3fa90ed0197bfef6e2a1a62b5095b9d2b4a27", + name: "chfast3"}, +} + +func BenchmarkPrecompiledModexp(bench *testing.B) { + for _, test := range modexpTestcases { + precompiledBenchmark("05", test, bench) + } +} + +func TestPrecompiledModexp(t *testing.T) { + for _, test := range modexpTestcases { + precompiledTest("05", test, t) + } } -func BenchmarkOpAdd(b *testing.B) { - x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" - y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" + +func BenchmarkPrecompiledBn256Add(bench *testing.B) { + for _, test := range bn256AddTestcases { + precompiledBenchmark("06", test, bench) + } +} + +func TestPrecompiledBn256Add(t *testing.T) { + for _, test := range bn256AddTestcases { + precompiledTest("06", test, t) + } +} + +func BenchmarkPrecompiledBn256ScalarMul(bench *testing.B) { + for _, test := range bn256MulTestcases { + precompiledBenchmark("07", test, bench) + } +} + +func TestPrecompiledBn256ScalarMul(t *testing.T) { + for _, test := range bn256MulTestcases { + precompiledTest("07", test, t) + } +} + +func BenchmarkPrecompiledPairing(bench *testing.B) { + for _, test := range pairingTestcases { + precompiledBenchmark("08", test, bench) + } +} + +func TestPrecompiledPairing(t *testing.T) { + for _, test := range pairingTestcases { + precompiledTest("08", test, t) + } +} + +func BenchmarkOpAdd64(b *testing.B) { + x := "ffffffff" + y := "fd37f3e2bba2c4f" opBenchmark(b, opAdd, x, y) } -func BenchmarkOpSub(b *testing.B) { - x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" - y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" +func BenchmarkOpAdd128(b *testing.B) { + x := "ffffffffffffffff" + y := "f5470b43c6549b016288e9a65629687" + + opBenchmark(b, opAdd, x, y) + +} +func BenchmarkOpAdd256(b *testing.B) { + x := "0802431afcbce1fc194c9eaa417b2fb67dc75a95db0bc7ec6b1c8af11df6a1da9" + y := "a1f5aac137876480252e5dcac62c354ec0d42b76b0642b6181ed099849ea1d57" + + opBenchmark(b, opAdd, x, y) + +} +func BenchmarkOpSub64(b *testing.B) { + x := "51022b6317003a9d" + y := "a20456c62e00753a" opBenchmark(b, opSub, x, y) +} +func BenchmarkOpSub128(b *testing.B) { + x := "4dde30faaacdc14d00327aac314e915d" + y := "9bbc61f5559b829a0064f558629d22ba" + + opBenchmark(b, opSub, x, y) +} +func BenchmarkOpSub256(b *testing.B) { + x := "4bfcd8bb2ac462735b48a17580690283980aa2d679f091c64364594df113ea37" + y := "97f9b1765588c4e6b69142eb00d20507301545acf3e1238c86c8b29be227d46e" + opBenchmark(b, opSub, x, y) } func BenchmarkOpMul(b *testing.B) { x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" @@ -151,16 +344,24 @@ func BenchmarkOpMul(b *testing.B) { opBenchmark(b, opMul, x, y) } -func BenchmarkOpDiv(b *testing.B) { - x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" - y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" - +func BenchmarkOpDiv256(b *testing.B) { + x := "ff3f9014f20db29ae04af2c2d265de17" + y := "fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611" + opBenchmark(b, opDiv, x, y) +} +func BenchmarkOpDiv128(b *testing.B) { + x := "fdedc7f10142ff97" + y := "fbdfda0e2ce356173d1993d5f70a2b11" + opBenchmark(b, opDiv, x, y) +} +func BenchmarkOpDiv64(b *testing.B) { + x := "fcb34eb3" + y := "f97180878e839129" opBenchmark(b, opDiv, x, y) - } func BenchmarkOpSdiv(b *testing.B) { - x := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" - y := "ABCDEF090807060504030201ffffffffffffffffffffffffffffffffffffffff" + x := "ff3f9014f20db29ae04af2c2d265de17" + y := "fe7fb0d1f59dfe9492ffbf73683fd1e870eec79504c60144cc7f5fc2bad1e611" opBenchmark(b, opSdiv, x, y) diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 545f7d6502bc..a64d1bab5a3f 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -51,10 +51,9 @@ type Config struct { JumpTable [256]operation } -// Interpreter is used to run Ethereum based contracts and will utilise the -// passed evmironment to query external sources for state information. -// The Interpreter will run the byte code VM or JIT VM based on the passed -// configuration. +// Interpreter is capable of interpreting Ethereum Byte code and uses the passed +// Ethereum Virtual Machine to query for auxiliary data such as state, block and +// caller information. type Interpreter struct { evm *EVM cfg Config @@ -62,6 +61,8 @@ type Interpreter struct { intPool *intPool readonly bool + // returnData contains the last call's return data + returnData []byte } // NewInterpreter returns a new instance of the Interpreter. @@ -71,6 +72,8 @@ func NewInterpreter(evm *EVM, cfg Config) *Interpreter { // we'll set the default jump table. if !cfg.JumpTable[STOP].valid { switch { + case evm.ChainConfig().IsMetropolis(evm.BlockNumber): + cfg.JumpTable = metropolisInstructionSet case evm.ChainConfig().IsHomestead(evm.BlockNumber): cfg.JumpTable = homesteadInstructionSet default: @@ -87,6 +90,19 @@ func NewInterpreter(evm *EVM, cfg Config) *Interpreter { } func (in *Interpreter) enforceRestrictions(op OpCode, operation operation, stack *Stack) error { + if in.evm.chainRules.IsMetropolis { + if in.readonly { + // if the interpreter is operating in readonly mode, make sure no + // state-modifying operation is performed. The 4th stack item + // for a call operation is the value. Transfering value from one + // account to the others means the state is modified and should also + // return with an error. + if operation.writes || + ((op == CALL || op == CALLCODE) && stack.Back(3).BitLen() > 0) { + return errWriteProtection + } + } + } return nil } @@ -97,8 +113,12 @@ func (in *Interpreter) enforceRestrictions(op OpCode, operation operation, stack // considered a revert-and-consume-all-gas operation. No error specific checks // should be handled to reduce complexity and errors further down the in. func (in *Interpreter) Run(snapshot int, contract *Contract, input []byte) (ret []byte, err error) { + // Increment the call depth which is restricted to 1024. in.evm.depth++ defer func() { in.evm.depth-- }() + // Reset the previous call's return data. It's unimportant to preserve the old buffer + // as every returning call will return new data anyway. + in.returnData = nil // Don't bother with the execution if there's no code. if len(contract.Code) == 0 { @@ -201,6 +221,11 @@ func (in *Interpreter) Run(snapshot int, contract *Contract, input []byte) (ret verifyIntegerPool(in.intPool) } + // checks whether the operation should revert state. + if operation.reverts { + in.evm.StateDB.RevertToSnapshot(snapshot) + } + switch { case err != nil: return nil, err @@ -209,10 +234,10 @@ func (in *Interpreter) Run(snapshot int, contract *Contract, input []byte) (ret case !operation.jumps: pc++ } - // if the operation returned a value make sure that is also set - // the last return data. - if res != nil { - mem.lastReturn = ret + // if the operation clears the return data (e.g. it has returning data) + // set the last return to the result of the operation. + if operation.clearsReturndata { + in.returnData = res } } return nil, nil diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index 0034eacb7dfd..14f604fe884c 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -53,13 +53,51 @@ type operation struct { valid bool // reverts determined whether the operation reverts state reverts bool + // clearsReturndata determines whether the opertions clears the return data + clearsReturndata bool } var ( - frontierInstructionSet = NewFrontierInstructionSet() - homesteadInstructionSet = NewHomesteadInstructionSet() + frontierInstructionSet = NewFrontierInstructionSet() + homesteadInstructionSet = NewHomesteadInstructionSet() + metropolisInstructionSet = NewMetropolisInstructionSet() ) +// NewMetropolisInstructionSet returns the frontier, homestead and +// metropolis instructions. +func NewMetropolisInstructionSet() [256]operation { + // instructions that can be executed during the homestead phase. + instructionSet := NewHomesteadInstructionSet() + instructionSet[STATIC_CALL] = operation{ + execute: opStaticCall, + gasCost: gasStaticCall, + validateStack: makeStackFunc(6, 1), + memorySize: memoryStaticCall, + valid: true, + } + instructionSet[REVERT] = operation{ + execute: opRevert, + gasCost: constGasFunc(GasFastestStep), + validateStack: makeStackFunc(2, 0), + valid: true, + reverts: true, + } + instructionSet[RETURNDATASIZE] = operation{ + execute: opReturnDataSize, + gasCost: constGasFunc(GasQuickStep), + validateStack: makeStackFunc(0, 1), + valid: true, + } + instructionSet[RETURNDATACOPY] = operation{ + execute: opReturnDataCopy, + gasCost: gasReturnDataCopy, + validateStack: makeStackFunc(3, 0), + memorySize: memoryReturnDataCopy, + valid: true, + } + return instructionSet +} + // NewHomesteadInstructionSet returns the frontier and homestead // instructions that can be executed during the homestead phase. func NewHomesteadInstructionSet() [256]operation { @@ -810,6 +848,7 @@ func NewFrontierInstructionSet() [256]operation { validateStack: makeStackFunc(2, 0), memorySize: memoryLog, valid: true, + writes: true, }, LOG1: { execute: makeLog(1), @@ -817,6 +856,7 @@ func NewFrontierInstructionSet() [256]operation { validateStack: makeStackFunc(3, 0), memorySize: memoryLog, valid: true, + writes: true, }, LOG2: { execute: makeLog(2), @@ -824,6 +864,7 @@ func NewFrontierInstructionSet() [256]operation { validateStack: makeStackFunc(4, 0), memorySize: memoryLog, valid: true, + writes: true, }, LOG3: { execute: makeLog(3), @@ -831,6 +872,7 @@ func NewFrontierInstructionSet() [256]operation { validateStack: makeStackFunc(5, 0), memorySize: memoryLog, valid: true, + writes: true, }, LOG4: { execute: makeLog(4), @@ -838,28 +880,41 @@ func NewFrontierInstructionSet() [256]operation { validateStack: makeStackFunc(6, 0), memorySize: memoryLog, valid: true, + writes: true, }, CREATE: { - execute: opCreate, - gasCost: gasCreate, - validateStack: makeStackFunc(3, 1), - memorySize: memoryCreate, - valid: true, - writes: true, + execute: opCreate, + gasCost: gasCreate, + validateStack: makeStackFunc(3, 1), + memorySize: memoryCreate, + valid: true, + writes: true, + clearsReturndata: true, + }, + CREATE2: { + execute: opCreate2, + gasCost: gasCreate, + validateStack: makeStackFunc(4, 1), + memorySize: memoryCreate2, + valid: true, + writes: true, + clearsReturndata: true, }, CALL: { - execute: opCall, - gasCost: gasCall, - validateStack: makeStackFunc(7, 1), - memorySize: memoryCall, - valid: true, + execute: opCall, + gasCost: gasCall, + validateStack: makeStackFunc(7, 1), + memorySize: memoryCall, + valid: true, + clearsReturndata: true, }, CALLCODE: { - execute: opCallCode, - gasCost: gasCallCode, - validateStack: makeStackFunc(7, 1), - memorySize: memoryCall, - valid: true, + execute: opCallCode, + gasCost: gasCallCode, + validateStack: makeStackFunc(7, 1), + memorySize: memoryCall, + valid: true, + clearsReturndata: true, }, RETURN: { execute: opReturn, diff --git a/core/vm/memory.go b/core/vm/memory.go index 6dbee94eff76..99a84d227158 100644 --- a/core/vm/memory.go +++ b/core/vm/memory.go @@ -22,7 +22,6 @@ import "fmt" type Memory struct { store []byte lastGasCost uint64 - lastReturn []byte } func NewMemory() *Memory { diff --git a/core/vm/memory_table.go b/core/vm/memory_table.go index 654137c70bc6..01e43fbc00e5 100644 --- a/core/vm/memory_table.go +++ b/core/vm/memory_table.go @@ -30,6 +30,10 @@ func memoryCalldataCopy(stack *Stack) *big.Int { return calcMemSize(stack.Back(0), stack.Back(2)) } +func memoryReturnDataCopy(stack *Stack) *big.Int { + return calcMemSize(stack.Back(0), stack.Back(2)) +} + func memoryCodeCopy(stack *Stack) *big.Int { return calcMemSize(stack.Back(0), stack.Back(2)) } @@ -54,6 +58,10 @@ func memoryCreate(stack *Stack) *big.Int { return calcMemSize(stack.Back(1), stack.Back(2)) } +func memoryCreate2(stack *Stack) *big.Int { + return calcMemSize(stack.Back(2), stack.Back(3)) +} + func memoryCall(stack *Stack) *big.Int { x := calcMemSize(stack.Back(5), stack.Back(6)) y := calcMemSize(stack.Back(3), stack.Back(4)) @@ -74,6 +82,13 @@ func memoryDelegateCall(stack *Stack) *big.Int { return math.BigMax(x, y) } +func memoryStaticCall(stack *Stack) *big.Int { + x := calcMemSize(stack.Back(4), stack.Back(5)) + y := calcMemSize(stack.Back(2), stack.Back(3)) + + return math.BigMax(x, y) +} + func memoryReturn(stack *Stack) *big.Int { return calcMemSize(stack.Back(0), stack.Back(1)) } diff --git a/core/vm/opcodes.go b/core/vm/opcodes.go index d4ba7f1563f5..49789a22dd5f 100644 --- a/core/vm/opcodes.go +++ b/core/vm/opcodes.go @@ -194,6 +194,11 @@ const ( SWAP ) +const ( + RETURNDATASIZE OpCode = 0xd0 + iota + RETURNDATACOPY +) + const ( // 0xf0 range - closures CREATE OpCode = 0xf0 + iota @@ -201,7 +206,11 @@ const ( CALLCODE RETURN DELEGATECALL + STATIC_CALL + + CREATE2 OpCode = 0xfb + REVERT = 0xfd SELFDESTRUCT = 0xff ) @@ -349,13 +358,17 @@ var opCodeToString = map[OpCode]string{ LOG3: "LOG3", LOG4: "LOG4", + RETURNDATASIZE: "RETURNDATASIZE", + RETURNDATACOPY: "RETURNDATACOPY", // 0xf0 range CREATE: "CREATE", CALL: "CALL", RETURN: "RETURN", + REVERT: "REVERT", CALLCODE: "CALLCODE", DELEGATECALL: "DELEGATECALL", SELFDESTRUCT: "SELFDESTRUCT", + STATIC_CALL: "STATIC_CALL", PUSH: "PUSH", DUP: "DUP", @@ -372,136 +385,140 @@ func (o OpCode) String() string { } var stringToOp = map[string]OpCode{ - "STOP": STOP, - "ADD": ADD, - "MUL": MUL, - "SUB": SUB, - "DIV": DIV, - "SDIV": SDIV, - "MOD": MOD, - "SMOD": SMOD, - "EXP": EXP, - "NOT": NOT, - "LT": LT, - "GT": GT, - "SLT": SLT, - "SGT": SGT, - "EQ": EQ, - "ISZERO": ISZERO, - "SIGNEXTEND": SIGNEXTEND, - "AND": AND, - "OR": OR, - "XOR": XOR, - "BYTE": BYTE, - "ADDMOD": ADDMOD, - "MULMOD": MULMOD, - "SHA3": SHA3, - "ADDRESS": ADDRESS, - "BALANCE": BALANCE, - "ORIGIN": ORIGIN, - "CALLER": CALLER, - "CALLVALUE": CALLVALUE, - "CALLDATALOAD": CALLDATALOAD, - "CALLDATASIZE": CALLDATASIZE, - "CALLDATACOPY": CALLDATACOPY, - "DELEGATECALL": DELEGATECALL, - "CODESIZE": CODESIZE, - "CODECOPY": CODECOPY, - "GASPRICE": GASPRICE, - "BLOCKHASH": BLOCKHASH, - "COINBASE": COINBASE, - "TIMESTAMP": TIMESTAMP, - "NUMBER": NUMBER, - "DIFFICULTY": DIFFICULTY, - "GASLIMIT": GASLIMIT, - "EXTCODESIZE": EXTCODESIZE, - "EXTCODECOPY": EXTCODECOPY, - "POP": POP, - "MLOAD": MLOAD, - "MSTORE": MSTORE, - "MSTORE8": MSTORE8, - "SLOAD": SLOAD, - "SSTORE": SSTORE, - "JUMP": JUMP, - "JUMPI": JUMPI, - "PC": PC, - "MSIZE": MSIZE, - "GAS": GAS, - "JUMPDEST": JUMPDEST, - "PUSH1": PUSH1, - "PUSH2": PUSH2, - "PUSH3": PUSH3, - "PUSH4": PUSH4, - "PUSH5": PUSH5, - "PUSH6": PUSH6, - "PUSH7": PUSH7, - "PUSH8": PUSH8, - "PUSH9": PUSH9, - "PUSH10": PUSH10, - "PUSH11": PUSH11, - "PUSH12": PUSH12, - "PUSH13": PUSH13, - "PUSH14": PUSH14, - "PUSH15": PUSH15, - "PUSH16": PUSH16, - "PUSH17": PUSH17, - "PUSH18": PUSH18, - "PUSH19": PUSH19, - "PUSH20": PUSH20, - "PUSH21": PUSH21, - "PUSH22": PUSH22, - "PUSH23": PUSH23, - "PUSH24": PUSH24, - "PUSH25": PUSH25, - "PUSH26": PUSH26, - "PUSH27": PUSH27, - "PUSH28": PUSH28, - "PUSH29": PUSH29, - "PUSH30": PUSH30, - "PUSH31": PUSH31, - "PUSH32": PUSH32, - "DUP1": DUP1, - "DUP2": DUP2, - "DUP3": DUP3, - "DUP4": DUP4, - "DUP5": DUP5, - "DUP6": DUP6, - "DUP7": DUP7, - "DUP8": DUP8, - "DUP9": DUP9, - "DUP10": DUP10, - "DUP11": DUP11, - "DUP12": DUP12, - "DUP13": DUP13, - "DUP14": DUP14, - "DUP15": DUP15, - "DUP16": DUP16, - "SWAP1": SWAP1, - "SWAP2": SWAP2, - "SWAP3": SWAP3, - "SWAP4": SWAP4, - "SWAP5": SWAP5, - "SWAP6": SWAP6, - "SWAP7": SWAP7, - "SWAP8": SWAP8, - "SWAP9": SWAP9, - "SWAP10": SWAP10, - "SWAP11": SWAP11, - "SWAP12": SWAP12, - "SWAP13": SWAP13, - "SWAP14": SWAP14, - "SWAP15": SWAP15, - "SWAP16": SWAP16, - "LOG0": LOG0, - "LOG1": LOG1, - "LOG2": LOG2, - "LOG3": LOG3, - "LOG4": LOG4, - "CREATE": CREATE, - "CALL": CALL, - "RETURN": RETURN, - "CALLCODE": CALLCODE, - "SELFDESTRUCT": SELFDESTRUCT, + "STOP": STOP, + "ADD": ADD, + "MUL": MUL, + "SUB": SUB, + "DIV": DIV, + "SDIV": SDIV, + "MOD": MOD, + "SMOD": SMOD, + "EXP": EXP, + "NOT": NOT, + "LT": LT, + "GT": GT, + "SLT": SLT, + "SGT": SGT, + "EQ": EQ, + "ISZERO": ISZERO, + "SIGNEXTEND": SIGNEXTEND, + "AND": AND, + "OR": OR, + "XOR": XOR, + "BYTE": BYTE, + "ADDMOD": ADDMOD, + "MULMOD": MULMOD, + "SHA3": SHA3, + "ADDRESS": ADDRESS, + "BALANCE": BALANCE, + "ORIGIN": ORIGIN, + "CALLER": CALLER, + "CALLVALUE": CALLVALUE, + "CALLDATALOAD": CALLDATALOAD, + "CALLDATASIZE": CALLDATASIZE, + "CALLDATACOPY": CALLDATACOPY, + "DELEGATECALL": DELEGATECALL, + "STATIC_CALL": STATIC_CALL, + "CODESIZE": CODESIZE, + "CODECOPY": CODECOPY, + "GASPRICE": GASPRICE, + "BLOCKHASH": BLOCKHASH, + "COINBASE": COINBASE, + "TIMESTAMP": TIMESTAMP, + "NUMBER": NUMBER, + "DIFFICULTY": DIFFICULTY, + "GASLIMIT": GASLIMIT, + "EXTCODESIZE": EXTCODESIZE, + "EXTCODECOPY": EXTCODECOPY, + "POP": POP, + "MLOAD": MLOAD, + "MSTORE": MSTORE, + "MSTORE8": MSTORE8, + "SLOAD": SLOAD, + "SSTORE": SSTORE, + "JUMP": JUMP, + "JUMPI": JUMPI, + "PC": PC, + "MSIZE": MSIZE, + "GAS": GAS, + "JUMPDEST": JUMPDEST, + "PUSH1": PUSH1, + "PUSH2": PUSH2, + "PUSH3": PUSH3, + "PUSH4": PUSH4, + "PUSH5": PUSH5, + "PUSH6": PUSH6, + "PUSH7": PUSH7, + "PUSH8": PUSH8, + "PUSH9": PUSH9, + "PUSH10": PUSH10, + "PUSH11": PUSH11, + "PUSH12": PUSH12, + "PUSH13": PUSH13, + "PUSH14": PUSH14, + "PUSH15": PUSH15, + "PUSH16": PUSH16, + "PUSH17": PUSH17, + "PUSH18": PUSH18, + "PUSH19": PUSH19, + "PUSH20": PUSH20, + "PUSH21": PUSH21, + "PUSH22": PUSH22, + "PUSH23": PUSH23, + "PUSH24": PUSH24, + "PUSH25": PUSH25, + "PUSH26": PUSH26, + "PUSH27": PUSH27, + "PUSH28": PUSH28, + "PUSH29": PUSH29, + "PUSH30": PUSH30, + "PUSH31": PUSH31, + "PUSH32": PUSH32, + "DUP1": DUP1, + "DUP2": DUP2, + "DUP3": DUP3, + "DUP4": DUP4, + "DUP5": DUP5, + "DUP6": DUP6, + "DUP7": DUP7, + "DUP8": DUP8, + "DUP9": DUP9, + "DUP10": DUP10, + "DUP11": DUP11, + "DUP12": DUP12, + "DUP13": DUP13, + "DUP14": DUP14, + "DUP15": DUP15, + "DUP16": DUP16, + "SWAP1": SWAP1, + "SWAP2": SWAP2, + "SWAP3": SWAP3, + "SWAP4": SWAP4, + "SWAP5": SWAP5, + "SWAP6": SWAP6, + "SWAP7": SWAP7, + "SWAP8": SWAP8, + "SWAP9": SWAP9, + "SWAP10": SWAP10, + "SWAP11": SWAP11, + "SWAP12": SWAP12, + "SWAP13": SWAP13, + "SWAP14": SWAP14, + "SWAP15": SWAP15, + "SWAP16": SWAP16, + "LOG0": LOG0, + "LOG1": LOG1, + "LOG2": LOG2, + "LOG3": LOG3, + "LOG4": LOG4, + "CREATE": CREATE, + "CALL": CALL, + "RETURN": RETURN, + "REVERT": REVERT, + "CALLCODE": CALLCODE, + "SELFDESTRUCT": SELFDESTRUCT, + "RETURNDATASIZE": RETURNDATASIZE, + "RETURNDATACOPY": RETURNDATACOPY, } func StringToOp(str string) OpCode { diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go index 44cde4f70a93..b2666909110a 100644 --- a/core/vm/runtime/runtime.go +++ b/core/vm/runtime/runtime.go @@ -141,8 +141,11 @@ func Create(input []byte, cfg *Config) ([]byte, common.Address, uint64, error) { ) // Call the code with the given configuration. + createAddressFn := vm.CreateAddressFn(vmenv.ChainConfig(), vmenv.BlockNumber, sender.Address(), vmenv.StateDB.GetNonce(sender.Address()), input) + code, address, leftOverGas, err := vmenv.Create( sender, + createAddressFn, input, cfg.GasLimit, cfg.Value, diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index 45bb87322527..02df03fff458 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -203,8 +203,6 @@ func (ec *Client) TransactionReceipt(ctx context.Context, txHash common.Hash) (* if err == nil { if r == nil { return nil, ethereum.NotFound - } else if len(r.PostState) == 0 { - return nil, fmt.Errorf("server returned receipt without post state") } } return r, err