github.com/iozhaq/go-ppcchain@v0.0.0-20200829190007-06fc4d127077/core/vm/contracts_test.go (about)

     1  // Copyright 2017 The go-ppcchain Authors
     2  // This file is part of the go-ppcchain library.
     3  //
     4  // The go-ppcchain 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-ppcchain 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-ppcchain 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  	"testing"
    25  	"time"
    26  
    27  	"github.com/iozhaq/go-ppcchain/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  	gas := p.RequiredGas(in)
    75  	t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) {
    76  		if res, _, err := RunPrecompiledContract(p, in, gas); err != nil {
    77  			t.Error(err)
    78  		} else if common.Bytes2Hex(res) != test.Expected {
    79  			t.Errorf("Expected %v, got %v", test.Expected, common.Bytes2Hex(res))
    80  		}
    81  		// Verify that the precompile did not touch the input buffer
    82  		exp := common.Hex2Bytes(test.Input)
    83  		if !bytes.Equal(in, exp) {
    84  			t.Errorf("Precompiled %v modified input data", addr)
    85  		}
    86  	})
    87  }
    88  
    89  func testPrecompiledOOG(addr string, test precompiledTest, t *testing.T) {
    90  	p := allPrecompiles[common.HexToAddress(addr)]
    91  	in := common.Hex2Bytes(test.Input)
    92  	gas := p.RequiredGas(in) - 1
    93  
    94  	t.Run(fmt.Sprintf("%s-Gas=%d", test.Name, gas), func(t *testing.T) {
    95  		_, _, err := RunPrecompiledContract(p, in, gas)
    96  		if err.Error() != "out of gas" {
    97  			t.Errorf("Expected error [out of gas], got [%v]", err)
    98  		}
    99  		// Verify that the precompile did not touch the input buffer
   100  		exp := common.Hex2Bytes(test.Input)
   101  		if !bytes.Equal(in, exp) {
   102  			t.Errorf("Precompiled %v modified input data", addr)
   103  		}
   104  	})
   105  }
   106  
   107  func testPrecompiledFailure(addr string, test precompiledFailureTest, t *testing.T) {
   108  	p := allPrecompiles[common.HexToAddress(addr)]
   109  	in := common.Hex2Bytes(test.Input)
   110  	gas := p.RequiredGas(in)
   111  	t.Run(test.Name, func(t *testing.T) {
   112  		_, _, err := RunPrecompiledContract(p, in, gas)
   113  		if err.Error() != test.ExpectedError {
   114  			t.Errorf("Expected error [%v], got [%v]", test.ExpectedError, err)
   115  		}
   116  		// Verify that the precompile did not touch the input buffer
   117  		exp := common.Hex2Bytes(test.Input)
   118  		if !bytes.Equal(in, exp) {
   119  			t.Errorf("Precompiled %v modified input data", addr)
   120  		}
   121  	})
   122  }
   123  
   124  func benchmarkPrecompiled(addr string, test precompiledTest, bench *testing.B) {
   125  	if test.NoBenchmark {
   126  		return
   127  	}
   128  	p := allPrecompiles[common.HexToAddress(addr)]
   129  	in := common.Hex2Bytes(test.Input)
   130  	reqGas := p.RequiredGas(in)
   131  
   132  	var (
   133  		res  []byte
   134  		err  error
   135  		data = make([]byte, len(in))
   136  	)
   137  
   138  	bench.Run(fmt.Sprintf("%s-Gas=%d", test.Name, reqGas), func(bench *testing.B) {
   139  		bench.ReportAllocs()
   140  		start := time.Now().Nanosecond()
   141  		bench.ResetTimer()
   142  		for i := 0; i < bench.N; i++ {
   143  			copy(data, in)
   144  			res, _, err = RunPrecompiledContract(p, data, reqGas)
   145  		}
   146  		bench.StopTimer()
   147  		elapsed := float64(time.Now().Nanosecond() - start)
   148  		if elapsed < 1 {
   149  			elapsed = 1
   150  		}
   151  		gasUsed := reqGas * uint64(bench.N)
   152  		bench.ReportMetric(float64(reqGas), "gas/op")
   153  		bench.ReportMetric(float64(gasUsed*1000)/elapsed, "mgas/s")
   154  		//Check if it is correct
   155  		if err != nil {
   156  			bench.Error(err)
   157  			return
   158  		}
   159  		if common.Bytes2Hex(res) != test.Expected {
   160  			bench.Error(fmt.Sprintf("Expected %v, got %v", test.Expected, common.Bytes2Hex(res)))
   161  			return
   162  		}
   163  	})
   164  }
   165  
   166  // Benchmarks the sample inputs from the ECRECOVER precompile.
   167  func BenchmarkPrecompiledEcrecover(bench *testing.B) {
   168  	t := precompiledTest{
   169  		Input:    "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
   170  		Expected: "000000000000000000000000ceaccac640adf55b2028469bd36ba501f28b699d",
   171  		Name:     "",
   172  	}
   173  	benchmarkPrecompiled("01", t, bench)
   174  }
   175  
   176  // Benchmarks the sample inputs from the SHA256 precompile.
   177  func BenchmarkPrecompiledSha256(bench *testing.B) {
   178  	t := precompiledTest{
   179  		Input:    "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
   180  		Expected: "811c7003375852fabd0d362e40e68607a12bdabae61a7d068fe5fdd1dbbf2a5d",
   181  		Name:     "128",
   182  	}
   183  	benchmarkPrecompiled("02", t, bench)
   184  }
   185  
   186  // Benchmarks the sample inputs from the RIPEMD precompile.
   187  func BenchmarkPrecompiledRipeMD(bench *testing.B) {
   188  	t := precompiledTest{
   189  		Input:    "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
   190  		Expected: "0000000000000000000000009215b8d9882ff46f0dfde6684d78e831467f65e6",
   191  		Name:     "128",
   192  	}
   193  	benchmarkPrecompiled("03", t, bench)
   194  }
   195  
   196  // Benchmarks the sample inputs from the identiy precompile.
   197  func BenchmarkPrecompiledIdentity(bench *testing.B) {
   198  	t := precompiledTest{
   199  		Input:    "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
   200  		Expected: "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02",
   201  		Name:     "128",
   202  	}
   203  	benchmarkPrecompiled("04", t, bench)
   204  }
   205  
   206  // Tests the sample inputs from the ModExp EIP 198.
   207  func TestPrecompiledModExp(t *testing.T)      { testJson("modexp", "05", t) }
   208  func BenchmarkPrecompiledModExp(b *testing.B) { benchJson("modexp", "05", b) }
   209  
   210  // Tests the sample inputs from the elliptic curve addition EIP 213.
   211  func TestPrecompiledBn256Add(t *testing.T)      { testJson("bn256Add", "06", t) }
   212  func BenchmarkPrecompiledBn256Add(b *testing.B) { benchJson("bn256Add", "06", b) }
   213  
   214  // Tests OOG
   215  func TestPrecompiledModExpOOG(t *testing.T) {
   216  	modexpTests, err := loadJson("modexp")
   217  	if err != nil {
   218  		t.Fatal(err)
   219  	}
   220  	for _, test := range modexpTests {
   221  		testPrecompiledOOG("05", test, t)
   222  	}
   223  }
   224  
   225  // Tests the sample inputs from the elliptic curve scalar multiplication EIP 213.
   226  func TestPrecompiledBn256ScalarMul(t *testing.T)      { testJson("bn256ScalarMul", "07", t) }
   227  func BenchmarkPrecompiledBn256ScalarMul(b *testing.B) { benchJson("bn256ScalarMul", "07", b) }
   228  
   229  // Tests the sample inputs from the elliptic curve pairing check EIP 197.
   230  func TestPrecompiledBn256Pairing(t *testing.T)      { testJson("bn256Pairing", "08", t) }
   231  func BenchmarkPrecompiledBn256Pairing(b *testing.B) { benchJson("bn256Pairing", "08", b) }
   232  
   233  func TestPrecompiledBlake2F(t *testing.T)      { testJson("blake2F", "09", t) }
   234  func BenchmarkPrecompiledBlake2F(b *testing.B) { benchJson("blake2F", "09", b) }
   235  
   236  func TestPrecompileBlake2FMalformedInput(t *testing.T) {
   237  	for _, test := range blake2FMalformedInputTests {
   238  		testPrecompiledFailure("09", test, t)
   239  	}
   240  }
   241  
   242  func TestPrecompiledEcrecover(t *testing.T) { testJson("ecRecover", "01", t) }
   243  
   244  func testJson(name, addr string, t *testing.T) {
   245  	tests, err := loadJson(name)
   246  	if err != nil {
   247  		t.Fatal(err)
   248  	}
   249  	for _, test := range tests {
   250  		testPrecompiled(addr, test, t)
   251  	}
   252  }
   253  
   254  func testJsonFail(name, addr string, t *testing.T) {
   255  	tests, err := loadJsonFail(name)
   256  	if err != nil {
   257  		t.Fatal(err)
   258  	}
   259  	for _, test := range tests {
   260  		testPrecompiledFailure(addr, test, t)
   261  	}
   262  }
   263  
   264  func benchJson(name, addr string, b *testing.B) {
   265  	tests, err := loadJson(name)
   266  	if err != nil {
   267  		b.Fatal(err)
   268  	}
   269  	for _, test := range tests {
   270  		benchmarkPrecompiled(addr, test, b)
   271  	}
   272  }
   273  
   274  func TestPrecompiledBLS12381G1Add(t *testing.T)      { testJson("blsG1Add", "0a", t) }
   275  func TestPrecompiledBLS12381G1Mul(t *testing.T)      { testJson("blsG1Mul", "0b", t) }
   276  func TestPrecompiledBLS12381G1MultiExp(t *testing.T) { testJson("blsG1MultiExp", "0c", t) }
   277  func TestPrecompiledBLS12381G2Add(t *testing.T)      { testJson("blsG2Add", "0d", t) }
   278  func TestPrecompiledBLS12381G2Mul(t *testing.T)      { testJson("blsG2Mul", "0e", t) }
   279  func TestPrecompiledBLS12381G2MultiExp(t *testing.T) { testJson("blsG2MultiExp", "0f", t) }
   280  func TestPrecompiledBLS12381Pairing(t *testing.T)    { testJson("blsPairing", "10", t) }
   281  func TestPrecompiledBLS12381MapG1(t *testing.T)      { testJson("blsMapG1", "11", t) }
   282  func TestPrecompiledBLS12381MapG2(t *testing.T)      { testJson("blsMapG2", "12", t) }
   283  
   284  func BenchmarkPrecompiledBLS12381G1Add(b *testing.B)      { benchJson("blsG1Add", "0a", b) }
   285  func BenchmarkPrecompiledBLS12381G1Mul(b *testing.B)      { benchJson("blsG1Mul", "0b", b) }
   286  func BenchmarkPrecompiledBLS12381G1MultiExp(b *testing.B) { benchJson("blsG1MultiExp", "0c", b) }
   287  func BenchmarkPrecompiledBLS12381G2Add(b *testing.B)      { benchJson("blsG2Add", "0d", b) }
   288  func BenchmarkPrecompiledBLS12381G2Mul(b *testing.B)      { benchJson("blsG2Mul", "0e", b) }
   289  func BenchmarkPrecompiledBLS12381G2MultiExp(b *testing.B) { benchJson("blsG2MultiExp", "0f", b) }
   290  func BenchmarkPrecompiledBLS12381Pairing(b *testing.B)    { benchJson("blsPairing", "10", b) }
   291  func BenchmarkPrecompiledBLS12381MapG1(b *testing.B)      { benchJson("blsMapG1", "11", b) }
   292  func BenchmarkPrecompiledBLS12381MapG2(b *testing.B)      { benchJson("blsMapG2", "12", b) }
   293  
   294  // Failure tests
   295  func TestPrecompiledBLS12381G1AddFail(t *testing.T)      { testJsonFail("blsG1Add", "0a", t) }
   296  func TestPrecompiledBLS12381G1MulFail(t *testing.T)      { testJsonFail("blsG1Mul", "0b", t) }
   297  func TestPrecompiledBLS12381G1MultiExpFail(t *testing.T) { testJsonFail("blsG1MultiExp", "0c", t) }
   298  func TestPrecompiledBLS12381G2AddFail(t *testing.T)      { testJsonFail("blsG2Add", "0d", t) }
   299  func TestPrecompiledBLS12381G2MulFail(t *testing.T)      { testJsonFail("blsG2Mul", "0e", t) }
   300  func TestPrecompiledBLS12381G2MultiExpFail(t *testing.T) { testJsonFail("blsG2MultiExp", "0f", t) }
   301  func TestPrecompiledBLS12381PairingFail(t *testing.T)    { testJsonFail("blsPairing", "10", t) }
   302  func TestPrecompiledBLS12381MapG1Fail(t *testing.T)      { testJsonFail("blsMapG1", "11", t) }
   303  func TestPrecompiledBLS12381MapG2Fail(t *testing.T)      { testJsonFail("blsMapG2", "12", t) }
   304  
   305  func loadJson(name string) ([]precompiledTest, error) {
   306  	data, err := ioutil.ReadFile(fmt.Sprintf("testdata/precompiles/%v.json", name))
   307  	if err != nil {
   308  		return nil, err
   309  	}
   310  	var testcases []precompiledTest
   311  	err = json.Unmarshal(data, &testcases)
   312  	return testcases, err
   313  }
   314  
   315  func loadJsonFail(name string) ([]precompiledFailureTest, error) {
   316  	data, err := ioutil.ReadFile(fmt.Sprintf("testdata/precompiles/fail-%v.json", name))
   317  	if err != nil {
   318  		return nil, err
   319  	}
   320  	var testcases []precompiledFailureTest
   321  	err = json.Unmarshal(data, &testcases)
   322  	return testcases, err
   323  }
   324  
   325  // BenchmarkPrecompiledBLS12381G1MultiExpWorstCase benchmarks the worst case we could find that still fits a gaslimit of 10MGas.
   326  func BenchmarkPrecompiledBLS12381G1MultiExpWorstCase(b *testing.B) {
   327  	task := "0000000000000000000000000000000008d8c4a16fb9d8800cce987c0eadbb6b3b005c213d44ecb5adeed713bae79d606041406df26169c35df63cf972c94be1" +
   328  		"0000000000000000000000000000000011bc8afe71676e6730702a46ef817060249cd06cd82e6981085012ff6d013aa4470ba3a2c71e13ef653e1e223d1ccfe9" +
   329  		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
   330  	input := task
   331  	for i := 0; i < 4787; i++ {
   332  		input = input + task
   333  	}
   334  	testcase := precompiledTest{
   335  		Input:       input,
   336  		Expected:    "0000000000000000000000000000000005a6310ea6f2a598023ae48819afc292b4dfcb40aabad24a0c2cb6c19769465691859eeb2a764342a810c5038d700f18000000000000000000000000000000001268ac944437d15923dc0aec00daa9250252e43e4b35ec7a19d01f0d6cd27f6e139d80dae16ba1c79cc7f57055a93ff5",
   337  		Name:        "WorstCaseG1",
   338  		NoBenchmark: false,
   339  	}
   340  	benchmarkPrecompiled("0c", testcase, b)
   341  }
   342  
   343  // BenchmarkPrecompiledBLS12381G2MultiExpWorstCase benchmarks the worst case we could find that still fits a gaslimit of 10MGas.
   344  func BenchmarkPrecompiledBLS12381G2MultiExpWorstCase(b *testing.B) {
   345  	task := "000000000000000000000000000000000d4f09acd5f362e0a516d4c13c5e2f504d9bd49fdfb6d8b7a7ab35a02c391c8112b03270d5d9eefe9b659dd27601d18f" +
   346  		"000000000000000000000000000000000fd489cb75945f3b5ebb1c0e326d59602934c8f78fe9294a8877e7aeb95de5addde0cb7ab53674df8b2cfbb036b30b99" +
   347  		"00000000000000000000000000000000055dbc4eca768714e098bbe9c71cf54b40f51c26e95808ee79225a87fb6fa1415178db47f02d856fea56a752d185f86b" +
   348  		"000000000000000000000000000000001239b7640f416eb6e921fe47f7501d504fadc190d9cf4e89ae2b717276739a2f4ee9f637c35e23c480df029fd8d247c7" +
   349  		"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
   350  	input := task
   351  	for i := 0; i < 1040; i++ {
   352  		input = input + task
   353  	}
   354  
   355  	testcase := precompiledTest{
   356  		Input:       input,
   357  		Expected:    "0000000000000000000000000000000018f5ea0c8b086095cfe23f6bb1d90d45de929292006dba8cdedd6d3203af3c6bbfd592e93ecb2b2c81004961fdcbb46c00000000000000000000000000000000076873199175664f1b6493a43c02234f49dc66f077d3007823e0343ad92e30bd7dc209013435ca9f197aca44d88e9dac000000000000000000000000000000000e6f07f4b23b511eac1e2682a0fc224c15d80e122a3e222d00a41fab15eba645a700b9ae84f331ae4ed873678e2e6c9b000000000000000000000000000000000bcb4849e460612aaed79617255fd30c03f51cf03d2ed4163ca810c13e1954b1e8663157b957a601829bb272a4e6c7b8",
   358  		Name:        "WorstCaseG2",
   359  		NoBenchmark: false,
   360  	}
   361  	benchmarkPrecompiled("0f", testcase, b)
   362  }