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 }