github.com/klaytn/klaytn@v1.12.1/blockchain/vm/evm_test.go (about)

     1  package vm
     2  
     3  import (
     4  	"errors"
     5  	"math"
     6  	"math/big"
     7  	"testing"
     8  
     9  	"github.com/klaytn/klaytn/blockchain/state"
    10  	"github.com/klaytn/klaytn/common"
    11  	"github.com/klaytn/klaytn/kerrors"
    12  	"github.com/klaytn/klaytn/params"
    13  	"github.com/klaytn/klaytn/storage/database"
    14  	"github.com/stretchr/testify/assert"
    15  )
    16  
    17  // Block data
    18  var (
    19  	Block4 = big.NewInt(4) // Block number before the istanbulHF
    20  	Block5 = big.NewInt(5) // Block number after the istanbulHF(also istanbulHF Block number)
    21  )
    22  
    23  type TestData struct {
    24  	addr  string
    25  	input []byte
    26  	// Test condition
    27  	isDeployedAfterIstanbulHF bool     // contract deployment time
    28  	block                     *big.Int // block when execution is done
    29  	// Expect field
    30  	expectGas uint64
    31  	expectRet string
    32  	expectErr error
    33  }
    34  
    35  func runPrecompiledContractTestWithHFCondition(t *testing.T, config *params.ChainConfig, testData []TestData) {
    36  	for _, tc := range testData {
    37  		// Make StateDB
    38  		callerAddr := common.BytesToAddress([]byte("contract"))
    39  		statedb, _ := state.New(common.Hash{}, state.NewDatabase(database.NewMemoryDBManager()), nil, nil)
    40  		statedb.CreateSmartContractAccount(callerAddr, params.CodeFormatEVM, params.Rules{IsIstanbul: tc.isDeployedAfterIstanbulHF})
    41  
    42  		// Make EVM environment
    43  		blockCtx := BlockContext{
    44  			CanTransfer: func(StateDB, common.Address, *big.Int) bool { return true },
    45  			Transfer:    func(StateDB, common.Address, common.Address, *big.Int) {},
    46  			BlockNumber: tc.block,
    47  		}
    48  		vmenv := NewEVM(blockCtx, TxContext{}, statedb, config, &Config{})
    49  
    50  		// run
    51  		ret, gas, err := vmenv.Call(AccountRef(callerAddr), common.HexToAddress(tc.addr), tc.input, math.MaxUint64, new(big.Int))
    52  
    53  		// compare with expected data
    54  		assert.Equal(t, tc.expectRet, common.Bytes2Hex(ret))
    55  		assert.Equal(t, tc.expectGas, math.MaxUint64-gas)
    56  		assert.Equal(t, tc.expectErr, err)
    57  	}
    58  }
    59  
    60  func TestPrecompiledContractAddressMapping(t *testing.T) {
    61  	var (
    62  		// Test Input
    63  		vmLogInput    = []byte("Hello")
    64  		feePayerInput = []byte("")
    65  		validateInput = common.Hex2Bytes("00000000000000000000000000000001234567890000000000000000000000000000000000000000000000000000000000000000db38e383310a432f1cec0bfbd765fe67c9932b02295b1f2062a785eec288b2f962d578d163a8b13c9cee127e0b24c01d1906979ac3bc6a763bf95c50999ca97c01")
    66  		// Expected Output
    67  		vmLogOutput    = ""
    68  		feePayerOutput = "000000000000000000000000636f6e7472616374"
    69  		validateOutput = "00"
    70  		// Test ChainConfig
    71  		config = &params.ChainConfig{IstanbulCompatibleBlock: Block5} // Set IstanbulCompatible block number as '5'
    72  	)
    73  
    74  	runPrecompiledContractTestWithHFCondition(t, config, []TestData{
    75  		// Expect Normal Behavior
    76  		// Condition 1. Caller Contract Deploy - before IstanbulCompatible, Call - before istanbulCompatible
    77  		{"0x009", vmLogInput, false, Block4, 200, vmLogOutput, nil},
    78  		{"0x00a", feePayerInput, false, Block4, 300, feePayerOutput, nil},
    79  		{"0x00b", validateInput, false, Block4, 5000, validateOutput, nil},
    80  		// Condition 2. Caller Contract Deploy - before IstanbulCompatible, Call - after istanbulCompatible
    81  		{"0x009", vmLogInput, false, Block5, 200, vmLogOutput, nil},
    82  		{"0x00a", feePayerInput, false, Block5, 300, feePayerOutput, nil},
    83  		{"0x00b", validateInput, false, Block5, 5000, validateOutput, nil},
    84  		// Condition 3. Caller Contract Deploy - after IstanbulCompatible, Call - after istanbulCompatible
    85  		{"0x3fd", vmLogInput, true, Block5, 200, vmLogOutput, nil},
    86  		{"0x3fe", feePayerInput, true, Block5, 300, feePayerOutput, nil},
    87  		{"0x3ff", validateInput, true, Block5, 5000, validateOutput, nil},
    88  
    89  		// Expect Error Behavior
    90  		// Condition 1. Caller Contract Deploy - before IstanbulCompatible, Call - before istanbulCompatible
    91  		{"0x3fd", vmLogInput, false, Block4, 0, "", kerrors.ErrPrecompiledContractAddress},
    92  		{"0x3fe", feePayerInput, false, Block4, 0, "", kerrors.ErrPrecompiledContractAddress},
    93  		{"0x3ff", validateInput, false, Block4, 0, "", kerrors.ErrPrecompiledContractAddress},
    94  		// Condition 2. Caller Contract Deploy - before IstanbulCompatible, Call - after istanbulCompatible
    95  		{"0x3fd", vmLogInput, false, Block5, 0, "", kerrors.ErrPrecompiledContractAddress},
    96  		{"0x3fe", feePayerInput, false, Block5, 0, "", kerrors.ErrPrecompiledContractAddress},
    97  		{"0x3ff", validateInput, false, Block5, 0, "", kerrors.ErrPrecompiledContractAddress},
    98  		// Condition 3. Caller Contract Deploy - after IstanbulCompatible, Call - after istanbulCompatible
    99  		{"0x009", vmLogInput, true, Block5, math.MaxUint64, "", errors.New("invalid input length")},
   100  		{"0x00a", feePayerInput, true, Block5, 0, "", kerrors.ErrPrecompiledContractAddress},
   101  		{"0x00b", validateInput, true, Block5, 0, "", kerrors.ErrPrecompiledContractAddress},
   102  	})
   103  }
   104  
   105  func TestBn256GasCost(t *testing.T) {
   106  	var (
   107  		// Test Input
   108  		bn256AddInput       = common.Hex2Bytes("18b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f3726607c2b7f58a84bd6145f00c9c2bc0bb1a187f20ff2c92963a88019e7c6a014eed06614e20c147e940f2d70da3f74c9a17df361706a4485c742bd6788478fa17d7")
   109  		bn256ScalarMulInput = common.Hex2Bytes("2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb721611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb20400000000000000000000000000000000000000000000000011138ce750fa15c2")
   110  		bn256PairingInput   = common.Hex2Bytes("1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa")
   111  		// Expected Output
   112  		bn256AddOutput       = "2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c915"
   113  		bn256ScalarMulOutput = "070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc"
   114  		bn256PairingOutput   = "0000000000000000000000000000000000000000000000000000000000000001"
   115  		// Test ChainConfig
   116  		config = &params.ChainConfig{IstanbulCompatibleBlock: Block5}
   117  	)
   118  
   119  	runPrecompiledContractTestWithHFCondition(t, config, []TestData{
   120  		// Test whether appropriate gas cost is returned
   121  		// Condition 1. Caller Contract Deploy - before IstanbulCompatible, Call - before istanbulCompatible
   122  		{"0x006", bn256AddInput, false, Block4, params.Bn256AddGasByzantium, bn256AddOutput, nil},
   123  		{"0x007", bn256ScalarMulInput, false, Block4, params.Bn256ScalarMulGasByzantium, bn256ScalarMulOutput, nil},
   124  		{"0x008", bn256PairingInput, false, Block4, params.Bn256PairingBaseGasByzantium + params.Bn256PairingPerPointGasByzantium*uint64(len(bn256PairingInput)/192), bn256PairingOutput, nil},
   125  		// Condition 2. Caller Contract Deploy - before IstanbulCompatible, Call - after istanbulCompatible
   126  		{"0x006", bn256AddInput, false, Block5, params.Bn256AddGasByzantium, bn256AddOutput, nil},
   127  		{"0x007", bn256ScalarMulInput, false, Block5, params.Bn256ScalarMulGasByzantium, bn256ScalarMulOutput, nil},
   128  		{"0x008", bn256PairingInput, false, Block5, params.Bn256PairingBaseGasByzantium + params.Bn256PairingPerPointGasByzantium*uint64(len(bn256PairingInput)/192), bn256PairingOutput, nil},
   129  		// Condition 3. Caller Contract Deploy - after IstanbulCompatible, Call - after istanbulCompatible
   130  		{"0x006", bn256AddInput, true, Block5, params.Bn256AddGasIstanbul, bn256AddOutput, nil},
   131  		{"0x007", bn256ScalarMulInput, true, Block5, params.Bn256ScalarMulGasIstanbul, bn256ScalarMulOutput, nil},
   132  		{"0x008", bn256PairingInput, true, Block5, params.Bn256PairingBaseGasIstanbul + params.Bn256PairingPerPointGasIstanbul*uint64(len(bn256PairingInput)/192), bn256PairingOutput, nil},
   133  	})
   134  }