github.com/zhiqiangxu/go-ethereum@v1.9.16-0.20210824055606-be91cfdebc48/core/vm/contracts_test.go (about)

     1  // Copyright 2017 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package vm
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/json"
    22  	"fmt"
    23  	"io/ioutil"
    24  	"math/big"
    25  	"testing"
    26  
    27  	"github.com/zhiqiangxu/go-ethereum/common"
    28  )
    29  
    30  // precompiledTest defines the input/output pairs for precompiled contract tests.
    31  type precompiledTest struct {
    32  	Input, Expected string
    33  	Name            string
    34  	NoBenchmark     bool // Benchmark primarily the worst-cases
    35  }
    36  
    37  // precompiledFailureTest defines the input/error pairs for precompiled
    38  // contract failure tests.
    39  type precompiledFailureTest struct {
    40  	Input         string
    41  	ExpectedError string
    42  	Name          string
    43  }
    44  
    45  var allPrecompiles = PrecompiledContractsYoloV1
    46  
    47  // EIP-152 test vectors
    48  var blake2FMalformedInputTests = []precompiledFailureTest{
    49  	{
    50  		Input:         "",
    51  		ExpectedError: errBlake2FInvalidInputLength.Error(),
    52  		Name:          "vector 0: empty input",
    53  	},
    54  	{
    55  		Input:         "00000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001",
    56  		ExpectedError: errBlake2FInvalidInputLength.Error(),
    57  		Name:          "vector 1: less than 213 bytes input",
    58  	},
    59  	{
    60  		Input:         "000000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001",
    61  		ExpectedError: errBlake2FInvalidInputLength.Error(),
    62  		Name:          "vector 2: more than 213 bytes input",
    63  	},
    64  	{
    65  		Input:         "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000002",
    66  		ExpectedError: errBlake2FInvalidFinalFlag.Error(),
    67  		Name:          "vector 3: malformed final block indicator flag",
    68  	},
    69  }
    70  
    71  func testPrecompiled(addr string, test precompiledTest, t *testing.T) {
    72  	p := allPrecompiles[common.HexToAddress(addr)]
    73  	in := common.Hex2Bytes(test.Input)
    74  	contract := NewContract(AccountRef(common.HexToAddress("1337")),
    75  		nil, new(big.Int), p.RequiredGas(in))
    76  	t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, contract.Gas), func(t *testing.T) {
    77  		if res, err := RunPrecompiledContract(p, in, contract); err != nil {
    78  			t.Error(err)
    79  		} else if common.Bytes2Hex(res) != test.Expected {
    80  			t.Errorf("Expected %v, got %v", test.Expected, common.Bytes2Hex(res))
    81  		}
    82  		// Verify that the precompile did not touch the input buffer
    83  		exp := common.Hex2Bytes(test.Input)
    84  		if !bytes.Equal(in, exp) {
    85  			t.Errorf("Precompiled %v modified input data", addr)
    86  		}
    87  	})
    88  }
    89  
    90  func testPrecompiledOOG(addr string, test precompiledTest, t *testing.T) {
    91  	p := allPrecompiles[common.HexToAddress(addr)]
    92  	in := common.Hex2Bytes(test.Input)
    93  	contract := NewContract(AccountRef(common.HexToAddress("1337")),
    94  		nil, new(big.Int), p.RequiredGas(in)-1)
    95  	t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, contract.Gas), func(t *testing.T) {
    96  		_, err := RunPrecompiledContract(p, in, contract)
    97  		if err.Error() != "out of gas" {
    98  			t.Errorf("Expected error [out of gas], got [%v]", err)
    99  		}
   100  		// Verify that the precompile did not touch the input buffer
   101  		exp := common.Hex2Bytes(test.Input)
   102  		if !bytes.Equal(in, exp) {
   103  			t.Errorf("Precompiled %v modified input data", addr)
   104  		}
   105  	})
   106  }
   107  
   108  func testPrecompiledFailure(addr string, test precompiledFailureTest, t *testing.T) {
   109  	p := allPrecompiles[common.HexToAddress(addr)]
   110  	in := common.Hex2Bytes(test.Input)
   111  	contract := NewContract(AccountRef(common.HexToAddress("31337")),
   112  		nil, new(big.Int), p.RequiredGas(in))
   113  
   114  	t.Run(test.Name, func(t *testing.T) {
   115  		_, err := RunPrecompiledContract(p, in, contract)
   116  		if err.Error() != test.ExpectedError {
   117  			t.Errorf("Expected error [%v], got [%v]", test.ExpectedError, err)
   118  		}
   119  		// Verify that the precompile did not touch the input buffer
   120  		exp := common.Hex2Bytes(test.Input)
   121  		if !bytes.Equal(in, exp) {
   122  			t.Errorf("Precompiled %v modified input data", addr)
   123  		}
   124  	})
   125  }
   126  
   127  func benchmarkPrecompiled(addr string, test precompiledTest, bench *testing.B) {
   128  	if test.NoBenchmark {
   129  		return
   130  	}
   131  	p := allPrecompiles[common.HexToAddress(addr)]
   132  	in := common.Hex2Bytes(test.Input)
   133  	reqGas := p.RequiredGas(in)
   134  	contract := NewContract(AccountRef(common.HexToAddress("1337")),
   135  		nil, new(big.Int), reqGas)
   136  
   137  	var (
   138  		res  []byte
   139  		err  error
   140  		data = make([]byte, len(in))
   141  	)
   142  
   143  	bench.Run(fmt.Sprintf("%s-Gas=%d", test.Name, contract.Gas), func(bench *testing.B) {
   144  		bench.ReportAllocs()
   145  		bench.ResetTimer()
   146  		for i := 0; i < bench.N; i++ {
   147  			contract.Gas = reqGas
   148  			copy(data, in)
   149  			res, err = RunPrecompiledContract(p, data, contract)
   150  		}
   151  		bench.StopTimer()
   152  		bench.ReportMetric(float64(reqGas), "gas/op")
   153  		//Check if it is correct
   154  		if err != nil {
   155  			bench.Error(err)
   156  			return
   157  		}
   158  		if common.Bytes2Hex(res) != test.Expected {
   159  			bench.Error(fmt.Sprintf("Expected %v, got %v", test.Expected, common.Bytes2Hex(res)))
   160  			return
   161  		}
   162  	})
   163  }
   164  
   165  // Benchmarks the sample inputs from the ECRECOVER precompile.
   166  func BenchmarkPrecompiledEcrecover(bench *testing.B) {
   167  	t := precompiledTest{
   168  		Input:    "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
   169  		Expected: "000000000000000000000000ceaccac640adf55b2028469bd36ba501f28b699d",
   170  		Name:     "",
   171  	}
   172  	benchmarkPrecompiled("01", t, bench)
   173  }
   174  
   175  // Benchmarks the sample inputs from the SHA256 precompile.
   176  func BenchmarkPrecompiledSha256(bench *testing.B) {
   177  	t := precompiledTest{
   178  		Input:    "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
   179  		Expected: "811c7003375852fabd0d362e40e68607a12bdabae61a7d068fe5fdd1dbbf2a5d",
   180  		Name:     "128",
   181  	}
   182  	benchmarkPrecompiled("02", t, bench)
   183  }
   184  
   185  // Benchmarks the sample inputs from the RIPEMD precompile.
   186  func BenchmarkPrecompiledRipeMD(bench *testing.B) {
   187  	t := precompiledTest{
   188  		Input:    "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
   189  		Expected: "0000000000000000000000009215b8d9882ff46f0dfde6684d78e831467f65e6",
   190  		Name:     "128",
   191  	}
   192  	benchmarkPrecompiled("03", t, bench)
   193  }
   194  
   195  // Benchmarks the sample inputs from the identiy precompile.
   196  func BenchmarkPrecompiledIdentity(bench *testing.B) {
   197  	t := precompiledTest{
   198  		Input:    "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
   199  		Expected: "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
   200  		Name:     "128",
   201  	}
   202  	benchmarkPrecompiled("04", t, bench)
   203  }
   204  
   205  // Tests the sample inputs from the ModExp EIP 198.
   206  func TestPrecompiledModExp(t *testing.T)      { testJson("modexp", "05", t) }
   207  func BenchmarkPrecompiledModExp(b *testing.B) { benchJson("modexp", "05", b) }
   208  
   209  // Tests the sample inputs from the elliptic curve addition EIP 213.
   210  func TestPrecompiledBn256Add(t *testing.T)      { testJson("bn256Add", "06", t) }
   211  func BenchmarkPrecompiledBn256Add(b *testing.B) { benchJson("bn256Add", "06", b) }
   212  
   213  // Tests OOG
   214  func TestPrecompiledModExpOOG(t *testing.T) {
   215  	modexpTests, err := loadJson("modexp")
   216  	if err != nil {
   217  		t.Fatal(err)
   218  	}
   219  	for _, test := range modexpTests {
   220  		testPrecompiledOOG("05", test, t)
   221  	}
   222  }
   223  
   224  // Tests the sample inputs from the elliptic curve scalar multiplication EIP 213.
   225  func TestPrecompiledBn256ScalarMul(t *testing.T)      { testJson("bn256ScalarMul", "07", t) }
   226  func BenchmarkPrecompiledBn256ScalarMul(b *testing.B) { benchJson("bn256ScalarMul", "07", b) }
   227  
   228  // Tests the sample inputs from the elliptic curve pairing check EIP 197.
   229  func TestPrecompiledBn256Pairing(t *testing.T)      { testJson("bn256Pairing", "08", t) }
   230  func BenchmarkPrecompiledBn256Pairing(b *testing.B) { benchJson("bn256Pairing", "08", b) }
   231  
   232  func TestPrecompiledBlake2F(t *testing.T)      { testJson("blake2F", "09", t) }
   233  func BenchmarkPrecompiledBlake2F(b *testing.B) { benchJson("blake2F", "09", b) }
   234  
   235  func TestPrecompileBlake2FMalformedInput(t *testing.T) {
   236  	for _, test := range blake2FMalformedInputTests {
   237  		testPrecompiledFailure("09", test, t)
   238  	}
   239  }
   240  
   241  func TestPrecompiledEcrecover(t *testing.T) { testJson("ecRecover", "01", t) }
   242  
   243  func testJson(name, addr string, t *testing.T) {
   244  	tests, err := loadJson(name)
   245  	if err != nil {
   246  		t.Fatal(err)
   247  	}
   248  	for _, test := range tests {
   249  		testPrecompiled(addr, test, t)
   250  	}
   251  }
   252  
   253  func testJsonFail(name, addr string, t *testing.T) {
   254  	tests, err := loadJsonFail(name)
   255  	if err != nil {
   256  		t.Fatal(err)
   257  	}
   258  	for _, test := range tests {
   259  		testPrecompiledFailure(addr, test, t)
   260  	}
   261  }
   262  
   263  func benchJson(name, addr string, b *testing.B) {
   264  	tests, err := loadJson(name)
   265  	if err != nil {
   266  		b.Fatal(err)
   267  	}
   268  	for _, test := range tests {
   269  		benchmarkPrecompiled(addr, test, b)
   270  	}
   271  }
   272  
   273  func TestPrecompiledBLS12381G1Add(t *testing.T)      { testJson("blsG1Add", "0a", t) }
   274  func TestPrecompiledBLS12381G1Mul(t *testing.T)      { testJson("blsG1Mul", "0b", t) }
   275  func TestPrecompiledBLS12381G1MultiExp(t *testing.T) { testJson("blsG1MultiExp", "0c", t) }
   276  func TestPrecompiledBLS12381G2Add(t *testing.T)      { testJson("blsG2Add", "0d", t) }
   277  func TestPrecompiledBLS12381G2Mul(t *testing.T)      { testJson("blsG2Mul", "0e", t) }
   278  func TestPrecompiledBLS12381G2MultiExp(t *testing.T) { testJson("blsG2MultiExp", "0f", t) }
   279  func TestPrecompiledBLS12381Pairing(t *testing.T)    { testJson("blsPairing", "10", t) }
   280  func TestPrecompiledBLS12381MapG1(t *testing.T)      { testJson("blsMapG1", "11", t) }
   281  func TestPrecompiledBLS12381MapG2(t *testing.T)      { testJson("blsMapG2", "12", t) }
   282  
   283  func BenchmarkPrecompiledBLS12381G1Add(b *testing.B)      { benchJson("blsG1Add", "0a", b) }
   284  func BenchmarkPrecompiledBLS12381G1Mul(b *testing.B)      { benchJson("blsG1Mul", "0b", b) }
   285  func BenchmarkPrecompiledBLS12381G1MultiExp(b *testing.B) { benchJson("blsG1MultiExp", "0c", b) }
   286  func BenchmarkPrecompiledBLS12381G2Add(b *testing.B)      { benchJson("blsG2Add", "0d", b) }
   287  func BenchmarkPrecompiledBLS12381G2Mul(b *testing.B)      { benchJson("blsG2Mul", "0e", b) }
   288  func BenchmarkPrecompiledBLS12381G2MultiExp(b *testing.B) { benchJson("blsG2MultiExp", "0f", b) }
   289  func BenchmarkPrecompiledBLS12381Pairing(b *testing.B)    { benchJson("blsPairing", "10", b) }
   290  func BenchmarkPrecompiledBLS12381MapG1(b *testing.B)      { benchJson("blsMapG1", "11", b) }
   291  func BenchmarkPrecompiledBLS12381MapG2(b *testing.B)      { benchJson("blsMapG2", "12", b) }
   292  
   293  // Failure tests
   294  func TestPrecompiledBLS12381G1AddFail(t *testing.T)      { testJsonFail("blsG1Add", "0a", t) }
   295  func TestPrecompiledBLS12381G1MulFail(t *testing.T)      { testJsonFail("blsG1Mul", "0b", t) }
   296  func TestPrecompiledBLS12381G1MultiExpFail(t *testing.T) { testJsonFail("blsG1MultiExp", "0c", t) }
   297  func TestPrecompiledBLS12381G2AddFail(t *testing.T)      { testJsonFail("blsG2Add", "0d", t) }
   298  func TestPrecompiledBLS12381G2MulFail(t *testing.T)      { testJsonFail("blsG2Mul", "0e", t) }
   299  func TestPrecompiledBLS12381G2MultiExpFail(t *testing.T) { testJsonFail("blsG2MultiExp", "0f", t) }
   300  func TestPrecompiledBLS12381PairingFail(t *testing.T)    { testJsonFail("blsPairing", "10", t) }
   301  func TestPrecompiledBLS12381MapG1Fail(t *testing.T)      { testJsonFail("blsMapG1", "11", t) }
   302  func TestPrecompiledBLS12381MapG2Fail(t *testing.T)      { testJsonFail("blsMapG2", "12", t) }
   303  
   304  func loadJson(name string) ([]precompiledTest, error) {
   305  	data, err := ioutil.ReadFile(fmt.Sprintf("testdata/precompiles/%v.json", name))
   306  	if err != nil {
   307  		return nil, err
   308  	}
   309  	var testcases []precompiledTest
   310  	err = json.Unmarshal(data, &testcases)
   311  	return testcases, err
   312  }
   313  
   314  func loadJsonFail(name string) ([]precompiledFailureTest, error) {
   315  	data, err := ioutil.ReadFile(fmt.Sprintf("testdata/precompiles/fail-%v.json", name))
   316  	if err != nil {
   317  		return nil, err
   318  	}
   319  	var testcases []precompiledFailureTest
   320  	err = json.Unmarshal(data, &testcases)
   321  	return testcases, err
   322  }