# Nimbus # Copyright (c) 2018-2024 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) # * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) # at your option. This file may not be copied, modified, or distributed except according to those terms. import std/[strformat, strutils, json, os, tables, macros], unittest2, stew/byteutils, eth/[keys, trie], ../nimbus/common/common, ../nimbus/[evm/computation, evm/state, evm/types, constants, evm/precompiles {.all.}, transaction, transaction/call_evm ], ./test_helpers, ./test_allowed_to_fail proc initAddress(i: byte): EthAddress = result[19] = i template doTest(fixture: JsonNode; vmState: BaseVMState; fork: EVMFork, address: PrecompileAddresses): untyped = for test in fixture: let expectedErr = test.hasKey("ExpectedError") expected = if test.hasKey("Expected"): hexToSeqByte(test["Expected"].getStr) else: @[] dataStr = test["Input"].getStr gasExpected = if test.hasKey("Gas"): Opt.some(GasInt test["Gas"].getInt) else: Opt.none(GasInt) let unsignedTx = Transaction( txType: TxLegacy, nonce: 0, gasPrice: 1.GasInt, gasLimit: 1_000_000_000.GasInt, to: Opt.some initAddress(address.byte), value: 0.u256, payload: if dataStr.len > 0: dataStr.hexToSeqByte else: @[] ) let tx = signTransaction(unsignedTx, privateKey, ChainId(1), false) let fixtureResult = testCallEvm(tx, tx.getSender, vmState, fork) if expectedErr: check fixtureResult.isError else: check not fixtureResult.isError let c = fixtureResult.output == expected if not c: echo "Output : " & fixtureResult.output.toHex & "\nExpected: " & expected.toHex check c if gasExpected.isSome: if fixtureResult.gasUsed != gasExpected.get: debugEcho "GAS: ", fixtureResult.gasUsed, " ", gasExpected.get check fixtureResult.gasUsed == gasExpected.get proc parseFork(x: string): EVMFork = let x = x.toLowerAscii for name, fork in nameToFork: if name.toLowerAscii == x: return fork doAssert(false, "unsupported fork name " & x) proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) = let label = fixtures["func"].getStr fork = parseFork(fixtures["fork"].getStr) data = fixtures["data"] privateKey = PrivateKey.fromHex("7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d")[] com = CommonRef.new(newCoreDbRef DefaultDbMemory, config = ChainConfig()) vmState = BaseVMState.new( BlockHeader(number: 1'u64, stateRoot: emptyRlpHash), BlockHeader(), com ) case toLowerAscii(label) of "ecrecover": data.doTest(vmState, fork, paEcRecover) of "sha256" : data.doTest(vmState, fork, paSha256) of "ripemd" : data.doTest(vmState, fork, paRipeMd160) of "identity" : data.doTest(vmState, fork, paIdentity) of "modexp" : data.doTest(vmState, fork, paModExp) of "bn256add" : data.doTest(vmState, fork, paEcAdd) of "bn256mul" : data.doTest(vmState, fork, paEcMul) of "ecpairing": data.doTest(vmState, fork, paPairing) of "blake2f" : data.doTest(vmState, fork, paBlake2bf) of "blsg1add" : data.doTest(vmState, fork, paBlsG1Add) of "blsg1mul" : data.doTest(vmState, fork, paBlsG1Mul) of "blsg1multiexp" : data.doTest(vmState, fork, paBlsG1MultiExp) of "blsg2add" : data.doTest(vmState, fork, paBlsG2Add) of "blsg2mul" : data.doTest(vmState, fork, paBlsG2Mul) # EIP 2537: disabled due to gas price changes/discprepancies #of "blsg2multiexp": data.doTest(vmState, fork, paBlsG2MultiExp) #of "blspairing": data.doTest(vmState, fork, paBlsPairing) #of "blsmapg1": data.doTest(vmState, fork, paBlsMapG1) #of "blsmapg2": data.doTest(vmState, fork, paBlsMapG2) else: echo "Unknown test vector '" & $label & "'" testStatusIMPL = SKIPPED proc precompilesMain*() = suite "Precompiles": jsonTest("PrecompileTests", testFixture, skipPrecompilesTests) when isMainModule: precompilesMain()