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 }