From 62968bf733bd188da10dda504380ea9efe4b9455 Mon Sep 17 00:00:00 2001 From: coffeepots Date: Tue, 2 Oct 2018 15:46:39 +0100 Subject: [PATCH 01/27] Initial support for precompiles with ecRecover --- nimbus/vm/precompiles.nim | 55 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 nimbus/vm/precompiles.nim diff --git a/nimbus/vm/precompiles.nim b/nimbus/vm/precompiles.nim new file mode 100644 index 000000000..58e7637cd --- /dev/null +++ b/nimbus/vm/precompiles.nim @@ -0,0 +1,55 @@ +import + ../vm_types, interpreter/[gas_meter, gas_costs], + ../errors, stint, eth_keys, eth_common, chronicles, tables, macros, + message + +type + PrecompileAddresses = enum + paEcRecover = 1, + paSha256, + paRipeMd160, + paIdentity, + # + paModExp, + paEcAdd, + paEcMul, + paPairing = 8 + +proc getSignature*(computation: BaseComputation): Signature = + var bytes: array[128, byte] + bytes[0..31] = computation.msg.data[32..63] # V + bytes[32..63] = computation.msg.data[64..95] # R + bytes[64..63] = computation.msg.data[96..128] # S + result = initSignature(bytes) # Can raise + +proc ecRecover*(computation: var BaseComputation) = + computation.gasMeter.consumeGas( + GAS_ECRECOVER, + reason="ECRecover Precompile") + + # TODO: Check endian + # Assumes V is 27 or 28 + var + sig = computation.getSignature() + pubKey: PublicKey + let msgHash = computation.msg.data[0..31] + + if sig.recoverSignatureKey(msgHash, pubKey) != EthKeysStatus.Success: + raise newException(ValidationError, "Could not derive public key from computation") + + computation.rawOutput = @(pubKey.toCanonicalAddress()) + debug "ECRecover derived key ", key = pubKey.toCanonicalAddress() + +proc execPrecompiles*(computation: var BaseComputation): bool {.inline.} = + # TODO: Assumes endian + for i in 0..18: + if computation.msg.codeAddress[i] != 0: return + let lb = computation.msg.codeAddress[19] + if lb < 9: + result = true + let precompile = PrecompileAddresses(lb) + debug "Call precompile ", precompile = precompile, codeAddr = computation.msg.codeAddress + case precompile + of paEcRecover: ecRecover(computation) + else: + raise newException(ValidationError, "Unknown precompile address " & $lb) From e2087f09227ddde2b3b6d3b37dea9826e49d188f Mon Sep 17 00:00:00 2001 From: coffeepots Date: Tue, 2 Oct 2018 15:55:28 +0100 Subject: [PATCH 02/27] Remove precompile hash table --- nimbus/vm_state_transactions.nim | 1 - nimbus/vm_types.nim | 1 - tests/test_opcode.nim | 1 - 3 files changed, 3 deletions(-) diff --git a/nimbus/vm_state_transactions.nim b/nimbus/vm_state_transactions.nim index 1392624be..3bd61ec49 100644 --- a/nimbus/vm_state_transactions.nim +++ b/nimbus/vm_state_transactions.nim @@ -46,7 +46,6 @@ proc setupComputation*(header: BlockHeader, vmState: var BaseVMState, transactio createAddress = transaction.to)) result = newBaseComputation(vmState, header.blockNumber, message) - result.precompiles = initTable[string, Opcode]() doAssert result.isOriginComputation proc execComputation*(computation: var BaseComputation, vmState: BaseVMState): bool = diff --git a/nimbus/vm_types.nim b/nimbus/vm_types.nim index 1cdafb0b4..7d39df0bc 100644 --- a/nimbus/vm_types.nim +++ b/nimbus/vm_types.nim @@ -32,7 +32,6 @@ type shouldEraseReturnData*: bool accountsToDelete*: Table[EthAddress, EthAddress] opcodes*: Table[Op, proc(computation: var BaseComputation){.nimcall.}] - precompiles*: Table[string, Opcode] gasCosts*: GasCosts # TODO - will be hidden at a lower layer opCodeExec*: OpcodeExecutor diff --git a/tests/test_opcode.nim b/tests/test_opcode.nim index b6ef21776..893a3545f 100644 --- a/tests/test_opcode.nim +++ b/tests/test_opcode.nim @@ -44,7 +44,6 @@ proc testCode(code: string, initialGas: GasInt, blockNum: UInt256): BaseComputat c.displayDecompiled() result = newBaseComputation(vmState, blockNum, message) - result.precompiles = initTable[string, Opcode]() result.executeOpcodes() From 36270ff4d5ed4e600c031bb69e08f835784022b3 Mon Sep 17 00:00:00 2001 From: coffeepots Date: Tue, 2 Oct 2018 16:07:16 +0100 Subject: [PATCH 03/27] Fixes for Call gas usage, Calls use precompiles, pass down their opCode --- nimbus/vm/computation.nim | 70 ++++++++++++++++++------ nimbus/vm/interpreter/opcodes_impl.nim | 75 +++++++++++--------------- 2 files changed, 86 insertions(+), 59 deletions(-) diff --git a/nimbus/vm/computation.nim b/nimbus/vm/computation.nim index c3f1dbf3e..a2b2e0776 100644 --- a/nimbus/vm/computation.nim +++ b/nimbus/vm/computation.nim @@ -11,7 +11,7 @@ import ../constants, ../errors, ../validation, ../vm_state, ../vm_types, ./interpreter/[opcode_values, gas_meter, gas_costs, vm_forks], ./code_stream, ./memory, ./message, ./stack, ../db/[state_db, db_chain], - ../utils/header, byteutils, ranges + ../utils/header, byteutils, ranges, eth_keys, precompiles logScope: topics = "vm computation" @@ -85,7 +85,7 @@ proc prepareChildMessage*( code, childOptions) -proc applyMessage(computation: var BaseComputation) = +proc applyMessage(computation: var BaseComputation, opCode: static[Op]) = var transaction = computation.vmState.beginTransaction() defer: transaction.dispose() @@ -97,28 +97,66 @@ proc applyMessage(computation: var BaseComputation) = computation.vmState.chainDb.getStateDb( computation.vmState.blockHeader.hash, false). getBalance(computation.msg.sender) + var newBalance = senderBalance if sender_balance < computation.msg.value: raise newException(InsufficientFunds, &"Insufficient funds: {senderBalance} < {computation.msg.value}" ) + when opCode in {Call, CallCode}: + let + insufficientFunds = senderBalance < computation.msg.value + stackTooDeep = computation.msg.depth >= MaxCallDepth - computation.vmState.mutateStateDb: - db.setBalance(computation.msg.sender, db.getBalance(computation.msg.sender) - computation.msg.value) - db.addBalance(computation.msg.storage_address, computation.msg.value) + if insufficientFunds or stackTooDeep: + computation.returnData = @[] + var errMessage: string + if insufficientFunds: + errMessage = &"Insufficient Funds: have: {$senderBalance} need: {$computation.msg.value}" + elif stackTooDeep: + errMessage = "Stack Limit Reached" + else: + raise newException(VMError, "Invariant: Unreachable code path") + + debug "Computation failure", msg = errMessage + computation.gasMeter.returnGas(computation.msg.gas) + push: 0 + return + + newBalance = senderBalance - computation.msg.value + computation.vmState.mutateStateDb: + db.setBalance(computation.msg.sender, newBalance) + db.addBalance(computation.msg.storage_address, computation.msg.value) + + debug "Value transferred", + source = computation.msg.sender, + dest = computation.msg.storage_address, + value = computation.msg.value, + oldSenderBalance = senderBalance, + newSenderBalance = newBalance, + gasPrice = computation.msg.gasPrice, + gas = computation.msg.gas debug "Apply message", value = computation.msg.value, + senderBalance = newBalance, sender = computation.msg.sender.toHex, - address = computation.msg.storage_address.toHex + address = computation.msg.storage_address.toHex, + gasPrice = computation.msg.gasPrice, + gas = computation.msg.gas - computation.opcodeExec(computation) + # Run code + if not computation.execPrecompiles: + computation.opcodeExec(computation) if not computation.isError: + debug "Computation committed" transaction.commit() + else: + debug "Computation rolled back due to error" -proc applyCreateMessage(fork: Fork, computation: var BaseComputation) = - computation.applyMessage() +proc applyCreateMessage(fork: Fork, computation: var BaseComputation, opCode: static[Op]) = + computation.applyMessage(opCode) var transaction: DbTransaction defer: transaction.safeDispose() @@ -157,13 +195,13 @@ proc applyCreateMessage(fork: Fork, computation: var BaseComputation) = else: # Different from Frontier: # Reverts state on gas failure while writing contract code. - # TODO: Revert snapshot + # Transaction are reverted automatically by safeDispose. discard else: if transaction != nil: transaction.commit() -proc generateChildComputation*(fork: Fork, computation: BaseComputation, childMsg: Message): BaseComputation = +proc generateChildComputation*(fork: Fork, computation: BaseComputation, childMsg: Message, opCode: static[Op]): BaseComputation = var childComp = newBaseComputation( computation.vmState, computation.vmState.blockHeader.blockNumber, @@ -171,11 +209,11 @@ proc generateChildComputation*(fork: Fork, computation: BaseComputation, childMs # Copy the fork op code executor proc (assumes child computation is in the same fork) childComp.opCodeExec = computation.opCodeExec - + if childMsg.isCreate: - fork.applyCreateMessage(childComp) + fork.applyCreateMessage(childComp, opCode) else: - applyMessage(childComp) + applyMessage(childComp, opCode) return childComp proc addChildComputation(fork: Fork, computation: BaseComputation, child: BaseComputation) = @@ -193,10 +231,10 @@ proc addChildComputation(fork: Fork, computation: BaseComputation, child: BaseCo computation.returnData = child.output computation.children.add(child) -proc applyChildComputation*(computation: BaseComputation, childMsg: Message): BaseComputation = +proc applyChildComputation*(computation: BaseComputation, childMsg: Message, opCode: static[Op]): BaseComputation = ## Apply the vm message childMsg as a child computation. let fork = computation.vmState.blockHeader.blockNumber.toFork - result = fork.generateChildComputation(computation, childMsg) + result = fork.generateChildComputation(computation, childMsg, opCode) fork.addChildComputation(computation, result) proc registerAccountForDeletion*(c: var BaseComputation, beneficiary: EthAddress) = diff --git a/nimbus/vm/interpreter/opcodes_impl.nim b/nimbus/vm/interpreter/opcodes_impl.nim index c95035424..b3cbaad08 100644 --- a/nimbus/vm/interpreter/opcodes_impl.nim +++ b/nimbus/vm/interpreter/opcodes_impl.nim @@ -14,6 +14,9 @@ import ../../vm_state, ../../errors, ../../constants, ../../vm_types, ../../db/[db_chain, state_db], ../../utils/addresses +logScope: + topics = "opcode impl" + # ################################## # Syntactic sugar @@ -545,6 +548,18 @@ op create, inline = false, value, startPosition, size: contractAddress = generateAddress(computation.msg.storageAddress, creationNonce) isCollision = db.hasCodeOrNonce(contractAddress) + + let (gasCost, childMsgGas) = computation.gasCosts[Op.Create].c_handler( + value, + GasParams(kind: Call, + c_isNewAccount: true, # TODO stub + c_gasBalance: 0, + c_contractGas: 0, + c_currentMemSize: computation.memory.len, + c_memOffset: 0, # TODO make sure if we pass the largest mem requested + c_memLength: 0 # or an addition of mem requested + )) + if isCollision: debug("Address collision while creating contract", address = contractAddress.toHex) push: 0 @@ -552,7 +567,7 @@ op create, inline = false, value, startPosition, size: let childMsg = prepareChildMessage( computation, - gas = 0, # TODO refactor gas + gas = childMsgGas, to = CREATE_CONTRACT_ADDRESS, value = value, data = @[], @@ -560,10 +575,7 @@ op create, inline = false, value, startPosition, size: options = MessageOptions(createAddress: contractAddress) ) - # let childComputation = applyChildBaseComputation(computation, childMsg) - var childComputation: BaseComputation # TODO - stub - new childComputation - childComputation.gasMeter.init(0) + let childComputation = computation.applyChildComputation(childMsg, Create) if childComputation.isError: push: 0 @@ -652,13 +664,12 @@ proc staticCallParams(computation: var BaseComputation): (UInt256, UInt256, EthA memoryOutputSize, emvcStatic) # is_static -template genCall(callName: untyped): untyped = +template genCall(callName: untyped, opCode: Op): untyped = op callName, inline = false: ## CALL, 0xf1, Message-Call into an account ## CALLCODE, 0xf2, Message-call into this account with an alternative account's code. ## DELEGATECALL, 0xf4, Message-call into this account with an alternative account's code, but persisting the current values for sender and value. ## STATICCALL, 0xfa, Static message-call into an account. - # TODO: forked calls for Homestead let (gas, value, to, sender, codeAddress, @@ -668,7 +679,7 @@ template genCall(callName: untyped): untyped = let (memInPos, memInLen, memOutPos, memOutLen) = (memoryInputStartPosition.cleanMemRef, memoryInputSize.cleanMemRef, memoryOutputStartPosition.cleanMemRef, memoryOutputSize.cleanMemRef) - let (gasCost, childMsgGas) = computation.gasCosts[Op.Call].c_handler( + let (gasCost, childMsgGas) = computation.gasCosts[opCode].c_handler( value, GasParams(kind: Call, c_isNewAccount: true, # TODO stub @@ -678,41 +689,19 @@ template genCall(callName: untyped): untyped = c_memOffset: 0, # TODO make sure if we pass the largest mem requested c_memLength: 0 # or an addition of mem requested )) + debug "Call", gasCost = gasCost, childCost = childMsgGas + computation.gasMeter.consumeGas(gasCost, reason = $opCode) computation.memory.extend(memInPos, memInLen) computation.memory.extend(memOutPos, memOutLen) let callData = computation.memory.read(memInPos, memInLen) - senderBalance = computation.vmState.readOnlyStateDb.getBalance(computation.msg.storageAddress) - # TODO check gas balance rollover - # TODO: shouldTransferValue in py-evm is: - # True for call and callCode - # False for callDelegate and callStatic - insufficientFunds = senderBalance < value # TODO: and shouldTransferValue - stackTooDeep = computation.msg.depth >= MaxCallDepth - - if insufficientFunds or stackTooDeep: - computation.returnData = @[] - var errMessage: string - if insufficientFunds: - # Note: for some reason we can't use strformat here, we get undeclared identifiers - errMessage = &"Insufficient Funds: have: " & $senderBalance & "need: " & $value - elif stackTooDeep: - errMessage = "Stack Limit Reached" - else: - raise newException(VMError, "Invariant: Unreachable code path") - - # computation.logger.debug(&"failure: {errMessage}") # TODO: Error: expression 'logger' has no type (or is ambiguous) - computation.gasMeter.returnGas(childMsgGas) - push: 0 - return - - let code = - if codeAddress != ZERO_ADDRESS: - computation.vmState.readOnlyStateDb.getCode(codeAddress) - else: - computation.vmState.readOnlyStateDb.getCode(to) + code = + if codeAddress != ZERO_ADDRESS: + computation.vmState.readOnlyStateDb.getCode(codeAddress) + else: + computation.vmState.readOnlyStateDb.getCode(to) var childMsg = prepareChildMessage( computation, @@ -727,13 +716,13 @@ template genCall(callName: untyped): untyped = if sender != ZERO_ADDRESS: childMsg.sender = sender - var childComputation = applyChildComputation(computation, childMsg) + var childComputation = applyChildComputation(computation, childMsg, opCode) if childComputation.isError: push: 0 else: push: 1 - + if not childComputation.shouldEraseReturnData: let actualOutputSize = min(memOutLen, childComputation.output.len) computation.memory.write( @@ -742,10 +731,10 @@ template genCall(callName: untyped): untyped = if not childComputation.shouldBurnGas: computation.gasMeter.returnGas(childComputation.gasMeter.gasRemaining) -genCall(call) -genCall(callCode) -genCall(delegateCall) -genCall(staticCall) +genCall(call, Call) +genCall(callCode, CallCode) +genCall(delegateCall, DelegateCall) +genCall(staticCall, StaticCall) op returnOp, inline = false, startPos, size: ## 0xf3, Halt execution returning output data. From fcffd94469511bab0d69877352979c436e75467a Mon Sep 17 00:00:00 2001 From: coffeepots Date: Tue, 2 Oct 2018 16:39:01 +0100 Subject: [PATCH 04/27] Support different endians --- nimbus/vm/precompiles.nim | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/nimbus/vm/precompiles.nim b/nimbus/vm/precompiles.nim index 58e7637cd..779e0a1a7 100644 --- a/nimbus/vm/precompiles.nim +++ b/nimbus/vm/precompiles.nim @@ -41,10 +41,15 @@ proc ecRecover*(computation: var BaseComputation) = debug "ECRecover derived key ", key = pubKey.toCanonicalAddress() proc execPrecompiles*(computation: var BaseComputation): bool {.inline.} = - # TODO: Assumes endian - for i in 0..18: + const + bRange = when system.cpuEndian == bigEndian: 0..18 else: 1..19 + bOffset = when system.cpuEndian == bigEndian: 19 else: 0 + + for i in bRange: if computation.msg.codeAddress[i] != 0: return - let lb = computation.msg.codeAddress[19] + + let lb = computation.msg.codeAddress[bOffset] + if lb < 9: result = true let precompile = PrecompileAddresses(lb) From 3deb09bbb690ae68ca332ed2649ebe7e57c161fd Mon Sep 17 00:00:00 2001 From: coffeepots Date: Wed, 3 Oct 2018 13:33:19 +0100 Subject: [PATCH 05/27] Add SHA256, RIPEMD160 and Identity precompiles --- nimbus/vm/precompiles.nim | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/nimbus/vm/precompiles.nim b/nimbus/vm/precompiles.nim index 779e0a1a7..ea08665b7 100644 --- a/nimbus/vm/precompiles.nim +++ b/nimbus/vm/precompiles.nim @@ -1,7 +1,7 @@ import ../vm_types, interpreter/[gas_meter, gas_costs], ../errors, stint, eth_keys, eth_common, chronicles, tables, macros, - message + message, math, nimcrypto type PrecompileAddresses = enum @@ -38,7 +38,34 @@ proc ecRecover*(computation: var BaseComputation) = raise newException(ValidationError, "Could not derive public key from computation") computation.rawOutput = @(pubKey.toCanonicalAddress()) - debug "ECRecover derived key ", key = pubKey.toCanonicalAddress() + debug "ECRecover precompile", derivedKey = pubKey.toCanonicalAddress() + +proc sha256*(computation: var BaseComputation) = + let + wordCount = computation.msg.data.len div 32 + gasFee = GAS_SHA256 + wordCount * GAS_SHA256WORD + + computation.gasMeter.consumeGas(gasFee, reason="SHA256 Precompile") + computation.rawOutput = @(keccak_256.digest(computation.msg.data).data) + debug "SHA256 precompile", output = computation.rawOutput + +proc ripemd160(computation: var BaseComputation) = + let + wordCount = computation.msg.data.len div 32 + gasFee = GAS_RIPEMD160 + wordCount * GAS_RIPEMD160WORD + + computation.gasMeter.consumeGas(gasFee, reason="RIPEMD160 Precompile") + computation.rawOutput = @(nimcrypto.ripemd160.digest(computation.msg.data).data) + debug "RIPEMD160 precompile", output = computation.rawOutput + +proc identity*(computation: var BaseComputation) = + let + wordCount = computation.msg.data.len div 32 + gasFee = GAS_IDENTITY + wordCount * GAS_IDENTITYWORD + + computation.gasMeter.consumeGas(gas_fee, reason="Identity Precompile") + computation.rawOutput = computation.msg.data + debug "Identity precompile", output = computation.rawOutput proc execPrecompiles*(computation: var BaseComputation): bool {.inline.} = const @@ -56,5 +83,8 @@ proc execPrecompiles*(computation: var BaseComputation): bool {.inline.} = debug "Call precompile ", precompile = precompile, codeAddr = computation.msg.codeAddress case precompile of paEcRecover: ecRecover(computation) + of paSha256: sha256(computation) + of paRipeMd160: ripeMd160(computation) + of paIdentity: identity(computation) else: raise newException(ValidationError, "Unknown precompile address " & $lb) From 3249c3e048daa35598dadb27c940b42d40f99bd5 Mon Sep 17 00:00:00 2001 From: coffeepots Date: Wed, 3 Oct 2018 16:39:34 +0100 Subject: [PATCH 06/27] Add precompile costs --- nimbus/vm/interpreter/gas_costs.nim | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/nimbus/vm/interpreter/gas_costs.nim b/nimbus/vm/interpreter/gas_costs.nim index 42a86aad5..158899818 100644 --- a/nimbus/vm/interpreter/gas_costs.nim +++ b/nimbus/vm/interpreter/gas_costs.nim @@ -585,3 +585,17 @@ proc forkToSchedule*(fork: Fork): GasCosts = HomesteadGasCosts else: TangerineGasCosts + +const + ## Precompile costs + GAS_SHA256* = 60 + GAS_SHA256WORD* = 12 + GAS_RIPEMD160* = 600 + GAS_RIPEMD160WORD* = 120 + GAS_IDENTITY* = 15 + GAS_IDENTITYWORD* = 3 + GAS_ECRECOVER* = 3000 + GAS_ECADD* = 500 + GAS_ECMUL* = 40000 + GAS_ECPAIRING_BASE* = 100000 + GAS_ECPAIRING_PER_POINT* = 80000 From 6a4cd4ec679408cd330c07c70ecbab03cf5bafdf Mon Sep 17 00:00:00 2001 From: coffeepots Date: Wed, 3 Oct 2018 17:59:41 +0100 Subject: [PATCH 07/27] Update precompile gas costs case (cosmetic change) --- nimbus/vm/interpreter/gas_costs.nim | 22 +++++++++++----------- nimbus/vm/precompiles.nim | 12 ++++++------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/nimbus/vm/interpreter/gas_costs.nim b/nimbus/vm/interpreter/gas_costs.nim index 158899818..0162ad284 100644 --- a/nimbus/vm/interpreter/gas_costs.nim +++ b/nimbus/vm/interpreter/gas_costs.nim @@ -588,14 +588,14 @@ proc forkToSchedule*(fork: Fork): GasCosts = const ## Precompile costs - GAS_SHA256* = 60 - GAS_SHA256WORD* = 12 - GAS_RIPEMD160* = 600 - GAS_RIPEMD160WORD* = 120 - GAS_IDENTITY* = 15 - GAS_IDENTITYWORD* = 3 - GAS_ECRECOVER* = 3000 - GAS_ECADD* = 500 - GAS_ECMUL* = 40000 - GAS_ECPAIRING_BASE* = 100000 - GAS_ECPAIRING_PER_POINT* = 80000 + GasSHA256* = 60 + GasSHA256Word* = 12 + GasRIPEMD160* = 600 + GasRIPEMD160Word* = 120 + GasIdentity* = 15 + GasIdentityWord* = 3 + GasECRecover* = 3000 + GasECAdd* = 500 + GasECMul* = 40000 + GasECPairingBase* = 100000 + GasECPairingPerPoint* = 80000 diff --git a/nimbus/vm/precompiles.nim b/nimbus/vm/precompiles.nim index ea08665b7..0c4141c59 100644 --- a/nimbus/vm/precompiles.nim +++ b/nimbus/vm/precompiles.nim @@ -24,7 +24,7 @@ proc getSignature*(computation: BaseComputation): Signature = proc ecRecover*(computation: var BaseComputation) = computation.gasMeter.consumeGas( - GAS_ECRECOVER, + GasECRecover, reason="ECRecover Precompile") # TODO: Check endian @@ -43,7 +43,7 @@ proc ecRecover*(computation: var BaseComputation) = proc sha256*(computation: var BaseComputation) = let wordCount = computation.msg.data.len div 32 - gasFee = GAS_SHA256 + wordCount * GAS_SHA256WORD + gasFee = GasSHA256 + wordCount * GasSHA256Word computation.gasMeter.consumeGas(gasFee, reason="SHA256 Precompile") computation.rawOutput = @(keccak_256.digest(computation.msg.data).data) @@ -52,7 +52,7 @@ proc sha256*(computation: var BaseComputation) = proc ripemd160(computation: var BaseComputation) = let wordCount = computation.msg.data.len div 32 - gasFee = GAS_RIPEMD160 + wordCount * GAS_RIPEMD160WORD + gasFee = GasRIPEMD160 + wordCount * GasRIPEMD160Word computation.gasMeter.consumeGas(gasFee, reason="RIPEMD160 Precompile") computation.rawOutput = @(nimcrypto.ripemd160.digest(computation.msg.data).data) @@ -61,9 +61,9 @@ proc ripemd160(computation: var BaseComputation) = proc identity*(computation: var BaseComputation) = let wordCount = computation.msg.data.len div 32 - gasFee = GAS_IDENTITY + wordCount * GAS_IDENTITYWORD + gasFee = GasIdentity + wordCount * GasIdentityWord - computation.gasMeter.consumeGas(gas_fee, reason="Identity Precompile") + computation.gasMeter.consumeGas(gasFee, reason="Identity Precompile") computation.rawOutput = computation.msg.data debug "Identity precompile", output = computation.rawOutput @@ -77,7 +77,7 @@ proc execPrecompiles*(computation: var BaseComputation): bool {.inline.} = let lb = computation.msg.codeAddress[bOffset] - if lb < 9: + if lb in PrecompileAddresses.low.byte .. PrecompileAddresses.high.byte: result = true let precompile = PrecompileAddresses(lb) debug "Call precompile ", precompile = precompile, codeAddr = computation.msg.codeAddress From 9318ea93cf22e142b85dfc10a63760a64bb4e5c3 Mon Sep 17 00:00:00 2001 From: cheatfate Date: Fri, 5 Oct 2018 12:15:04 +0300 Subject: [PATCH 08/27] Added nim-bncurve dependency. Added implementation of `ecAdd`, `ecMul`, `ecPairing` precompiles. --- nimbus.nimble | 3 +- nimbus/vm/precompiles.nim | 111 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 110 insertions(+), 4 deletions(-) diff --git a/nimbus.nimble b/nimbus.nimble index 55882e712..a774fc365 100644 --- a/nimbus.nimble +++ b/nimbus.nimble @@ -19,7 +19,8 @@ requires "nim >= 0.18.1", "asyncdispatch2", "eth_p2p", "eth_keyfile", - "eth_keys" + "eth_keys", + "https://github.com/status-im/nim-bncurve" proc buildBinary(name: string, srcDir = ".", lang = "c") = if not dirExists "build": mkDir "build" diff --git a/nimbus/vm/precompiles.nim b/nimbus/vm/precompiles.nim index 0c4141c59..52947081c 100644 --- a/nimbus/vm/precompiles.nim +++ b/nimbus/vm/precompiles.nim @@ -1,7 +1,7 @@ import ../vm_types, interpreter/[gas_meter, gas_costs], ../errors, stint, eth_keys, eth_common, chronicles, tables, macros, - message, math, nimcrypto + message, math, nimcrypto, bncurve/[fields, groups] type PrecompileAddresses = enum @@ -22,6 +22,29 @@ proc getSignature*(computation: BaseComputation): Signature = bytes[64..63] = computation.msg.data[96..128] # S result = initSignature(bytes) # Can raise +proc getPoint[T: G1|G2](t: typedesc[T], data: openarray[byte]): Point[T] = + when T is G1: + const nextOffset = 32 + var px, py: FQ + else: + const nextOffset = 64 + var px, py: FQ2 + if not px.fromBytes(data.toOpenArray(0, nextOffset - 1)): + raise newException(ValidationError, "Could not get point value") + if not py.fromBytes(data.toOpenArray(nextOffset, nextOffset * 2 - 1)): + raise newException(ValidationError, "Could not get point value") + if px.isZero() and py.isZero(): + result = T.zero() + else: + var ap: AffinePoint[T] + if not ap.init(px, py): + raise newException(ValidationError, "Point is not on curve") + result = ap.toJacobian() + +proc getFR(data: openarray[byte]): FR = + if not result.fromBytes(data): + raise newException(ValidationError, "Could not get FR value") + proc ecRecover*(computation: var BaseComputation) = computation.gasMeter.consumeGas( GasECRecover, @@ -36,7 +59,7 @@ proc ecRecover*(computation: var BaseComputation) = if sig.recoverSignatureKey(msgHash, pubKey) != EthKeysStatus.Success: raise newException(ValidationError, "Could not derive public key from computation") - + computation.rawOutput = @(pubKey.toCanonicalAddress()) debug "ECRecover precompile", derivedKey = pubKey.toCanonicalAddress() @@ -67,6 +90,85 @@ proc identity*(computation: var BaseComputation) = computation.rawOutput = computation.msg.data debug "Identity precompile", output = computation.rawOutput +proc bn256ecAdd*(computation: var BaseComputation) = + var + input: array[128, byte] + output: array[64, byte] + + # Padding data + let msglen = len(computation.msg.data) + let tocopy = if msglen < 128: msglen else: 128 + if tocopy > 0: + copyMem(addr input[0], addr computation.msg.data[0], tocopy) + + var p1 = G1.getPoint(input.toOpenArray(0, 63)) + var p2 = G1.getPoint(input.toOpenArray(64, 127)) + var apo = (p1 + p2).toAffine() + if isSome(apo): + let p = apo.get() + # we can discard here because we supply proper buffer + discard p.toBytes(output) + + # TODO: gas computation + # computation.gasMeter.consumeGas(gasFee, reason = "ecAdd Precompile") + computation.rawOutput = @output + +proc bn256ecMul*(computation: var BaseComputation) = + var + input: array[96, byte] + output: array[64, byte] + + # Padding data + let msglen = len(computation.msg.data) + let tocopy = if msglen < 96: msglen else: 96 + if tocopy > 0: + copyMem(addr input[0], addr computation.msg.data[0], tocopy) + + var p1 = G1.getPoint(input.toOpenArray(0, 63)) + var fr = getFR(input.toOpenArray(64, 95)) + var apo = (p1 * fr).toAffine() + if isSome(apo): + let p = apo.get() + # we can discard here because we supply buffer of proper size + discard p.toBytes(output) + + # TODO: gas computation + # computation.gasMeter.consumeGas(gasFee, reason="ecMul Precompile") + computation.rawOutput = @output + +proc bn256ecPairing*(computation: var BaseComputation) = + var output: array[32, byte] + + let msglen = len(computation.msg.data) + if msglen mod 192 != 0: + raise newException(ValidationError, "Invalid input length") + + if msglen == 0: + # we can discard here because we supply buffer of proper size + discard BNU256.one().toBytes(output) + else: + # Calculate number of pairing pairs + let count = msglen div 192 + # Pairing accumulator + var acc = FQ12.one() + + for i in 0.. Date: Fri, 5 Oct 2018 17:26:20 +0200 Subject: [PATCH 09/27] Add modExp precompile + gas costs --- nimbus/vm/interpreter/gas_costs.nim | 6 +- nimbus/vm/interpreter/utils/utils_numeric.nim | 6 +- nimbus/vm/precompiles.nim | 63 ++++++++++++++++++- 3 files changed, 71 insertions(+), 4 deletions(-) diff --git a/nimbus/vm/interpreter/gas_costs.nim b/nimbus/vm/interpreter/gas_costs.nim index 0162ad284..b79dbc588 100644 --- a/nimbus/vm/interpreter/gas_costs.nim +++ b/nimbus/vm/interpreter/gas_costs.nim @@ -49,7 +49,6 @@ type GasSha3Word, # Paid for each word (rounded up) for input data to a SHA3 operation. GasCopy, # Partial payment for COPY operations, multiplied by words copied, rounded up. GasBlockhash # Payment for BLOCKHASH operation. - # GasQuadDivisor # The quadratic coefficient of the input sizes of the exponentiation-over-modulo precompiled contract. GasFeeSchedule = array[GasFeeKind, GasInt] @@ -547,7 +546,6 @@ const GasSha3Word: 6, GasCopy: 3, GasBlockhash: 20 - # GasQuadDivisor: 100 # Unused, do not confuse with the quadratic coefficient 512 for memory expansion ] # Create the schedule for each forks @@ -599,3 +597,7 @@ const GasECMul* = 40000 GasECPairingBase* = 100000 GasECPairingPerPoint* = 80000 + # The Yellow Paper is special casing the GasQuadDivisor. + # It is defined in Appendix G with the other GasFeeKind constants + # instead of Appendix E for precompiled contracts + GasQuadDivisor* = 100 diff --git a/nimbus/vm/interpreter/utils/utils_numeric.nim b/nimbus/vm/interpreter/utils/utils_numeric.nim index 2dffcf77d..673fcdd9b 100644 --- a/nimbus/vm/interpreter/utils/utils_numeric.nim +++ b/nimbus/vm/interpreter/utils/utils_numeric.nim @@ -12,8 +12,12 @@ import # some methods based on py-evm utils/numeric +func log2*(value: UInt256): Natural {.inline.}= + # TODO: do we use ln for log2 like Nim convention? + 255 - value.countLeadingZeroBits + func log256*(value: UInt256): Natural {.inline.}= - (255 - value.countLeadingZeroBits) shr 3 # div 8 + value.log2 shr 3 # div 8 (= log2(256), Logb x = Loga x/Loga b) func ceil32*(value: Natural): Natural {.inline.}= # Round input to the nearest bigger multiple of 32 diff --git a/nimbus/vm/precompiles.nim b/nimbus/vm/precompiles.nim index 52947081c..53f951f15 100644 --- a/nimbus/vm/precompiles.nim +++ b/nimbus/vm/precompiles.nim @@ -1,5 +1,5 @@ import - ../vm_types, interpreter/[gas_meter, gas_costs], + ../vm_types, interpreter/[gas_meter, gas_costs, utils/utils_numeric], ../errors, stint, eth_keys, eth_common, chronicles, tables, macros, message, math, nimcrypto, bncurve/[fields, groups] @@ -90,6 +90,66 @@ proc identity*(computation: var BaseComputation) = computation.rawOutput = computation.msg.data debug "Identity precompile", output = computation.rawOutput +proc modExp(computation: var BaseComputation) = + + # Parsing the data + template rawMsg: untyped {.dirty.} = + computation.msg.data + let + base_len = rawMsg.toOpenArray(0, 31).readUintBE[:256].toInt + exp_len = rawMsg.toOpenArray(32, 63).readUintBE[:256].toInt + mod_len = rawMsg.toOpenArray(64, 95).readUintBE[:256].toInt + + start_exp = 96 + base_len + start_mod = start_exp + exp_len + + base = Uint256.fromBytesBE(rawMsg.toOpenArray(96, start_exp - 1), allowPadding = true) + exp = Uint256.fromBytesBE(rawMsg.toOpenArray(start_exp, start_mod - 1), allowPadding = true) + modulo = Uint256.fromBytesBE(rawMsg.toOpenArray(start_mod, start_mod + mod_len - 1), allowPadding = true) + + # TODO: Whenever the input is too short, the missing bytes are considered to be zero. + + block: # Gas cost + func gasModExp_f(x: Natural): int = + # x: maximum length in bytes between modulo and base + # TODO: Deal with negative max_len + result = case x + of 0 .. 64: x * x + of 65 .. 1024: x * x div 4 + 96 * x - 3072 + else: x * x div 16 + 480 * x - 199680 + + let adj_exp_len = block: + # TODO deal with negative length + if exp_len <= 32: + if exp.isZero(): 0 + else: log2(exp) + else: + # TODO: deal with overflow + let extra = Uint256.fromBytesBE(rawMsg.toOpenArray(96 + base_len, 127 + base_len), allowPadding = true) + if not extra.isZero: + 8 * (exp_len - 32) + extra.log2 + else: + 8 * (exp_len - 32) + + let gasFee = block: + ( + max(mod_len, base_len).gasModExp_f * + max(adj_exp_len, 1) + ) div GasQuadDivisor + + block: # Processing + # Start with EVM special cases + if modulo <= 1: + # If m == 0: EVM returns 0. + # If m == 1: we can shortcut that to 0 as well + computation.rawOutput = @(static(zero(UInt256).toByteArrayBE)) + elif exp.isZero(): + # If 0^0: EVM returns 1 + # For all x != 0, x^0 == 1 as well + computation.rawOutput = @(static(one(UInt256).toByteArrayBE)) + else: + computation.rawOutput = @powmod(base, exp, modulo).toByteArrayBE + proc bn256ecAdd*(computation: var BaseComputation) = var input: array[128, byte] @@ -188,6 +248,7 @@ proc execPrecompiles*(computation: var BaseComputation): bool {.inline.} = of paSha256: sha256(computation) of paRipeMd160: ripeMd160(computation) of paIdentity: identity(computation) + of paModExp: modExp(computation) of paEcAdd: bn256ecAdd(computation) of paEcMul: bn256ecMul(computation) of paPairing: bn256ecPairing(computation) From 0494e2a877a6ded4b37ff2d4b97f690e735418f7 Mon Sep 17 00:00:00 2001 From: mratsim Date: Fri, 5 Oct 2018 17:37:52 +0200 Subject: [PATCH 10/27] Support short inputs with missing bytes --- nimbus/vm/precompiles.nim | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/nimbus/vm/precompiles.nim b/nimbus/vm/precompiles.nim index 53f951f15..0885aedd7 100644 --- a/nimbus/vm/precompiles.nim +++ b/nimbus/vm/precompiles.nim @@ -96,9 +96,9 @@ proc modExp(computation: var BaseComputation) = template rawMsg: untyped {.dirty.} = computation.msg.data let - base_len = rawMsg.toOpenArray(0, 31).readUintBE[:256].toInt - exp_len = rawMsg.toOpenArray(32, 63).readUintBE[:256].toInt - mod_len = rawMsg.toOpenArray(64, 95).readUintBE[:256].toInt + base_len = toInt Uint256.fromBytesBE(rawMsg.toOpenArray(0, 31), allowPadding = true) + exp_len = toInt Uint256.fromBytesBE(rawMsg.toOpenArray(32, 63), allowPadding = true) + mod_len = toInt Uint256.fromBytesBE(rawMsg.toOpenArray(64, 96), allowPadding = true) start_exp = 96 + base_len start_mod = start_exp + exp_len @@ -107,8 +107,6 @@ proc modExp(computation: var BaseComputation) = exp = Uint256.fromBytesBE(rawMsg.toOpenArray(start_exp, start_mod - 1), allowPadding = true) modulo = Uint256.fromBytesBE(rawMsg.toOpenArray(start_mod, start_mod + mod_len - 1), allowPadding = true) - # TODO: Whenever the input is too short, the missing bytes are considered to be zero. - block: # Gas cost func gasModExp_f(x: Natural): int = # x: maximum length in bytes between modulo and base @@ -124,7 +122,6 @@ proc modExp(computation: var BaseComputation) = if exp.isZero(): 0 else: log2(exp) else: - # TODO: deal with overflow let extra = Uint256.fromBytesBE(rawMsg.toOpenArray(96 + base_len, 127 + base_len), allowPadding = true) if not extra.isZero: 8 * (exp_len - 32) + extra.log2 From bb6e1e1d760b4d4cd22033f2201ed96fc5016e9e Mon Sep 17 00:00:00 2001 From: mratsim Date: Wed, 10 Oct 2018 16:26:21 +0200 Subject: [PATCH 11/27] modExp precompiles: fix padding and static evaluation --- nimbus/vm/interpreter/utils/utils_numeric.nim | 16 ++++++++++ nimbus/vm/precompiles.nim | 31 ++++++++++++------- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/nimbus/vm/interpreter/utils/utils_numeric.nim b/nimbus/vm/interpreter/utils/utils_numeric.nim index 673fcdd9b..4274bf861 100644 --- a/nimbus/vm/interpreter/utils/utils_numeric.nim +++ b/nimbus/vm/interpreter/utils/utils_numeric.nim @@ -54,3 +54,19 @@ func cleanMemRef*(x: UInt256): int {.inline.} = if x > upperBound: return high(int32) shr 2 return x.toInt + +proc rangeToPaddedUint256*(x: seq[byte], first, last: int): Uint256 = + ## Convert take a slice of a sequence of bytes interpret it as the big endian + ## representation of an Uint256. Use padding for sequence shorter than 32 bytes + ## including 0-length sequences. + + let lo = max(0, first) + let hi = min(x.high, last) + + if not(lo < hi): + return # 0 + + result = UInt256.fromBytesBE( + x.toOpenArray(lo, hi), + allowPadding = true + ) diff --git a/nimbus/vm/precompiles.nim b/nimbus/vm/precompiles.nim index 0885aedd7..09720bb94 100644 --- a/nimbus/vm/precompiles.nim +++ b/nimbus/vm/precompiles.nim @@ -91,21 +91,21 @@ proc identity*(computation: var BaseComputation) = debug "Identity precompile", output = computation.rawOutput proc modExp(computation: var BaseComputation) = - + ## Modular exponentiation precompiled contract # Parsing the data template rawMsg: untyped {.dirty.} = computation.msg.data let - base_len = toInt Uint256.fromBytesBE(rawMsg.toOpenArray(0, 31), allowPadding = true) - exp_len = toInt Uint256.fromBytesBE(rawMsg.toOpenArray(32, 63), allowPadding = true) - mod_len = toInt Uint256.fromBytesBE(rawMsg.toOpenArray(64, 96), allowPadding = true) + base_len = rawMsg.rangeToPaddedUint256(0, 31).truncate(int) + exp_len = rawMsg.rangeToPaddedUint256(32, 63).truncate(int) + mod_len = rawMsg.rangeToPaddedUint256(64, 95).truncate(int) start_exp = 96 + base_len start_mod = start_exp + exp_len - base = Uint256.fromBytesBE(rawMsg.toOpenArray(96, start_exp - 1), allowPadding = true) - exp = Uint256.fromBytesBE(rawMsg.toOpenArray(start_exp, start_mod - 1), allowPadding = true) - modulo = Uint256.fromBytesBE(rawMsg.toOpenArray(start_mod, start_mod + mod_len - 1), allowPadding = true) + base = rawMsg.rangeToPaddedUint256(96, start_exp - 1) + exp = rawMsg.rangeToPaddedUint256(start_exp, start_mod - 1) + modulo = rawMsg.rangeToPaddedUint256(start_mod, start_mod + mod_len - 1) block: # Gas cost func gasModExp_f(x: Natural): int = @@ -122,7 +122,7 @@ proc modExp(computation: var BaseComputation) = if exp.isZero(): 0 else: log2(exp) else: - let extra = Uint256.fromBytesBE(rawMsg.toOpenArray(96 + base_len, 127 + base_len), allowPadding = true) + let extra = rawMsg.rangeToPaddedUint256(96 + base_len, 127 + base_len) if not extra.isZero: 8 * (exp_len - 32) + extra.log2 else: @@ -136,16 +136,25 @@ proc modExp(computation: var BaseComputation) = block: # Processing # Start with EVM special cases + + # Force static evaluation + func zero256(): static array[32, byte] = discard + func one256(): static array[32, byte] = + when cpuEndian == bigEndian: + result[^1] = 1 + else: + result[0] = 1 + if modulo <= 1: # If m == 0: EVM returns 0. # If m == 1: we can shortcut that to 0 as well - computation.rawOutput = @(static(zero(UInt256).toByteArrayBE)) + computation.rawOutput = @(zero256()) elif exp.isZero(): # If 0^0: EVM returns 1 # For all x != 0, x^0 == 1 as well - computation.rawOutput = @(static(one(UInt256).toByteArrayBE)) + computation.rawOutput = @(one256()) else: - computation.rawOutput = @powmod(base, exp, modulo).toByteArrayBE + computation.rawOutput = @(powmod(base, exp, modulo).toByteArrayBE) proc bn256ecAdd*(computation: var BaseComputation) = var From 2ee9861a9e48e39751f1662c203e5bc71845822b Mon Sep 17 00:00:00 2001 From: coffeepots Date: Wed, 10 Oct 2018 17:25:54 +0100 Subject: [PATCH 12/27] Precompile test data --- tests/fixtures/PrecompileTests/bn256Add.json | 85 ++++++++++++++ tests/fixtures/PrecompileTests/bn256mul.json | 107 ++++++++++++++++++ tests/fixtures/PrecompileTests/ecrecover.json | 17 +++ tests/fixtures/PrecompileTests/identity.json | 10 ++ tests/fixtures/PrecompileTests/modexp.json | 90 +++++++++++++++ tests/fixtures/PrecompileTests/pairing.json | 75 ++++++++++++ tests/fixtures/PrecompileTests/ripemd160.json | 10 ++ tests/fixtures/PrecompileTests/sha256.json | 26 +++++ 8 files changed, 420 insertions(+) create mode 100644 tests/fixtures/PrecompileTests/bn256Add.json create mode 100644 tests/fixtures/PrecompileTests/bn256mul.json create mode 100644 tests/fixtures/PrecompileTests/ecrecover.json create mode 100644 tests/fixtures/PrecompileTests/identity.json create mode 100644 tests/fixtures/PrecompileTests/modexp.json create mode 100644 tests/fixtures/PrecompileTests/pairing.json create mode 100644 tests/fixtures/PrecompileTests/ripemd160.json create mode 100644 tests/fixtures/PrecompileTests/sha256.json diff --git a/tests/fixtures/PrecompileTests/bn256Add.json b/tests/fixtures/PrecompileTests/bn256Add.json new file mode 100644 index 000000000..4db466395 --- /dev/null +++ b/tests/fixtures/PrecompileTests/bn256Add.json @@ -0,0 +1,85 @@ +{ + "bn256Add": + [ + { + "name": "chfast1", + "input": "18b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f3726607c2b7f58a84bd6145f00c9c2bc0bb1a187f20ff2c92963a88019e7c6a014eed06614e20c147e940f2d70da3f74c9a17df361706a4485c742bd6788478fa17d7", + "expected": "2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c915" + }, + { + "name": "chfast2", + "input": "2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c91518b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f37266", + "expected": "2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb721611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb204" + }, + { + "name": "cdetrio1", + "input": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "cdetrio2", + "input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "cdetrio3", + "input": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "cdetrio4", + "input": "", + "expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "cdetrio5", + "input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "cdetrio6", + "input": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", + "expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + }, + { + "name": "cdetrio7", + "input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + }, + { + "name": "cdetrio8", + "input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", + "expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + }, + { + "name": "cdetrio9", + "input": "0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + }, + { + "name": "cdetrio10", + "input": "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "expected": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002" + }, + { + "name": "cdetrio11", + "input": "0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002", + "expected": "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4" + }, + { + "name": "cdetrio12", + "input": "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "expected": "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4" + }, + { + "name": "cdetrio13", + "input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98", + "expected": "15bf2bb17880144b5d1cd2b1f46eff9d617bffd1ca57c37fb5a49bd84e53cf66049c797f9ce0d17083deb32b5e36f2ea2a212ee036598dd7624c168993d1355f" + }, + { + "name": "cdetrio14", + "input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa92e83f8d734803fc370eba25ed1f6b8768bd6d83887b87165fc2434fe11a830cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + ] +} \ No newline at end of file diff --git a/tests/fixtures/PrecompileTests/bn256mul.json b/tests/fixtures/PrecompileTests/bn256mul.json new file mode 100644 index 000000000..3716c85a2 --- /dev/null +++ b/tests/fixtures/PrecompileTests/bn256mul.json @@ -0,0 +1,107 @@ +{ + "bn256mul": + [ + { + "name": "chfast1", + "input": "2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb721611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb20400000000000000000000000000000000000000000000000011138ce750fa15c2", + "expected": "070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc" + }, + { + "name": "chfast2", + "input": "070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46", + "expected": "025a6f4181d2b4ea8b724290ffb40156eb0adb514c688556eb79cdea0752c2bb2eff3f31dea215f1eb86023a133a996eb6300b44da664d64251d05381bb8a02e" + }, + { + "name": "chfast3", + "input": "025a6f4181d2b4ea8b724290ffb40156eb0adb514c688556eb79cdea0752c2bb2eff3f31dea215f1eb86023a133a996eb6300b44da664d64251d05381bb8a02e183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7ea3", + "expected": "14789d0d4a730b354403b5fac948113739e276c23e0258d8596ee72f9cd9d3230af18a63153e0ec25ff9f2951dd3fa90ed0197bfef6e2a1a62b5095b9d2b4a27" + }, + { + "name": "cdetrio1", + "input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "expected": "2cde5879ba6f13c0b5aa4ef627f159a3347df9722efce88a9afbb20b763b4c411aa7e43076f6aee272755a7f9b84832e71559ba0d2e0b17d5f9f01755e5b0d11" + }, + { + "name": "cdetrio2", + "input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f630644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000", + "expected": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe3163511ddc1c3f25d396745388200081287b3fd1472d8339d5fecb2eae0830451", + "noBenchmark": true + }, + { + "name": "cdetrio3", + "input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000100000000000000000000000000000000", + "expected": "1051acb0700ec6d42a88215852d582efbaef31529b6fcbc3277b5c1b300f5cf0135b2394bb45ab04b8bd7611bd2dfe1de6a4e6e2ccea1ea1955f577cd66af85b", + "noBenchmark": true + }, + { + "name": "cdetrio4", + "input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000000000000000000000000000000000009", + "expected": "1dbad7d39dbc56379f78fac1bca147dc8e66de1b9d183c7b167351bfe0aeab742cd757d51289cd8dbd0acf9e673ad67d0f0a89f912af47ed1be53664f5692575", + "noBenchmark": true + }, + { + "name": "cdetrio5", + "input": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000000000000000000000000000000000001", + "expected": "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f6", + "noBenchmark": true + }, + { + "name": "cdetrio6", + "input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "expected": "29e587aadd7c06722aabba753017c093f70ba7eb1f1c0104ec0564e7e3e21f6022b1143f6a41008e7755c71c3d00b6b915d386de21783ef590486d8afa8453b1" + }, + { + "name": "cdetrio7", + "input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000", + "expected": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa92e83f8d734803fc370eba25ed1f6b8768bd6d83887b87165fc2434fe11a830cb", + "noBenchmark": true + }, + { + "name": "cdetrio8", + "input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c0000000000000000000000000000000100000000000000000000000000000000", + "expected": "221a3577763877920d0d14a91cd59b9479f83b87a653bb41f82a3f6f120cea7c2752c7f64cdd7f0e494bff7b60419f242210f2026ed2ec70f89f78a4c56a1f15", + "noBenchmark": true + }, + { + "name": "cdetrio9", + "input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c0000000000000000000000000000000000000000000000000000000000000009", + "expected": "228e687a379ba154554040f8821f4e41ee2be287c201aa9c3bc02c9dd12f1e691e0fd6ee672d04cfd924ed8fdc7ba5f2d06c53c1edc30f65f2af5a5b97f0a76a", + "noBenchmark": true + }, + { + "name": "cdetrio10", + "input": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c0000000000000000000000000000000000000000000000000000000000000001", + "expected": "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c", + "noBenchmark": true + }, + { + "name": "cdetrio11", + "input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "expected": "00a1a234d08efaa2616607e31eca1980128b00b415c845ff25bba3afcb81dc00242077290ed33906aeb8e42fd98c41bcb9057ba03421af3f2d08cfc441186024" + }, + { + "name": "cdetrio12", + "input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d9830644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000", + "expected": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b8692929ee761a352600f54921df9bf472e66217e7bb0cee9032e00acc86b3c8bfaf", + "noBenchmark": true + }, + { + "name": "cdetrio13", + "input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d980000000000000000000000000000000100000000000000000000000000000000", + "expected": "1071b63011e8c222c5a771dfa03c2e11aac9666dd097f2c620852c3951a4376a2f46fe2f73e1cf310a168d56baa5575a8319389d7bfa6b29ee2d908305791434", + "noBenchmark": true + }, + { + "name": "cdetrio14", + "input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d980000000000000000000000000000000000000000000000000000000000000009", + "expected": "19f75b9dd68c080a688774a6213f131e3052bd353a304a189d7a2ee367e3c2582612f545fb9fc89fde80fd81c68fc7dcb27fea5fc124eeda69433cf5c46d2d7f", + "noBenchmark": true + }, + { + "name": "cdetrio15", + "input": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d980000000000000000000000000000000000000000000000000000000000000001", + "expected": "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98", + "noBenchmark": true + } + ] +} diff --git a/tests/fixtures/PrecompileTests/ecrecover.json b/tests/fixtures/PrecompileTests/ecrecover.json new file mode 100644 index 000000000..f976ccd64 --- /dev/null +++ b/tests/fixtures/PrecompileTests/ecrecover.json @@ -0,0 +1,17 @@ +{ + "ecRecover": + [ + { + "name": "ecRecover", + "input": "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02", + "expected": "000000000000000000000000ceaccac640adf55b2028469bd36ba501f28b699d" + }, + { + "name": "ecRecoverR", + "input": "47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03", + "expected": "000000000000000000000000c08b5542d177ac6686946920409741463a15dddb" + } + ] +} + + diff --git a/tests/fixtures/PrecompileTests/identity.json b/tests/fixtures/PrecompileTests/identity.json new file mode 100644 index 000000000..c498a4016 --- /dev/null +++ b/tests/fixtures/PrecompileTests/identity.json @@ -0,0 +1,10 @@ +{ + "Identity": + [ + { + "name": "128", + "input": "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02", + "expected": "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02" + } + ], +} \ No newline at end of file diff --git a/tests/fixtures/PrecompileTests/modexp.json b/tests/fixtures/PrecompileTests/modexp.json new file mode 100644 index 000000000..cd877bfaa --- /dev/null +++ b/tests/fixtures/PrecompileTests/modexp.json @@ -0,0 +1,90 @@ +{ + "modExp": + [ + { + "name": "eip_example1", + "input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002003fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "expected": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "name": "eip_example2", + "input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "expected": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "nagydani-1-square", + "input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb502fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b", + "expected": "60008f1614cc01dcfb6bfb09c625cf90b47d4468db81b5f8b7a39d42f332eab9b2da8f2d95311648a8f243f4bb13cfb3d8f7f2a3c014122ebb3ed41b02783adc" + }, + { + "name": "nagydani-1-qube", + "input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb503fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b", + "expected": "4834a46ba565db27903b1c720c9d593e84e4cbd6ad2e64b31885d944f68cd801f92225a8961c952ddf2797fa4701b330c85c4b363798100b921a1a22a46a7fec" + }, + { + "name": "nagydani-1-pow0x10001", + "input": "000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000040e09ad9675465c53a109fac66a445c91b292d2bb2c5268addb30cd82f80fcb0033ff97c80a5fc6f39193ae969c6ede6710a6b7ac27078a06d90ef1c72e5c85fb5010001fc9e1f6beb81516545975218075ec2af118cd8798df6e08a147c60fd6095ac2bb02c2908cf4dd7c81f11c289e4bce98f3553768f392a80ce22bf5c4f4a248c6b", + "expected": "c36d804180c35d4426b57b50c5bfcca5c01856d104564cd513b461d3c8b8409128a5573e416d0ebe38f5f736766d9dc27143e4da981dfa4d67f7dc474cbee6d2" + }, + { + "name": "nagydani-2-square", + "input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5102e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087", + "expected": "981dd99c3b113fae3e3eaa9435c0dc96779a23c12a53d1084b4f67b0b053a27560f627b873e3f16ad78f28c94f14b6392def26e4d8896c5e3c984e50fa0b3aa44f1da78b913187c6128baa9340b1e9c9a0fd02cb78885e72576da4a8f7e5a113e173a7a2889fde9d407bd9f06eb05bc8fc7b4229377a32941a02bf4edcc06d70" + }, + { + "name": "nagydani-2-qube", + "input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf5103e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087", + "expected": "d89ceb68c32da4f6364978d62aaa40d7b09b59ec61eb3c0159c87ec3a91037f7dc6967594e530a69d049b64adfa39c8fa208ea970cfe4b7bcd359d345744405afe1cbf761647e32b3184c7fbe87cee8c6c7ff3b378faba6c68b83b6889cb40f1603ee68c56b4c03d48c595c826c041112dc941878f8c5be828154afd4a16311f" + }, + { + "name": "nagydani-2-pow0x10001", + "input": "000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000080cad7d991a00047dd54d3399b6b0b937c718abddef7917c75b6681f40cc15e2be0003657d8d4c34167b2f0bbbca0ccaa407c2a6a07d50f1517a8f22979ce12a81dcaf707cc0cebfc0ce2ee84ee7f77c38b9281b9822a8d3de62784c089c9b18dcb9a2a5eecbede90ea788a862a9ddd9d609c2c52972d63e289e28f6a590ffbf51010001e6d893b80aeed5e6e9ce9afa8a5d5675c93a32ac05554cb20e9951b2c140e3ef4e433068cf0fb73bc9f33af1853f64aa27a0028cbf570d7ac9048eae5dc7b28c87c31e5810f1e7fa2cda6adf9f1076dbc1ec1238560071e7efc4e9565c49be9e7656951985860a558a754594115830bcdb421f741408346dd5997bb01c287087", + "expected": "ad85e8ef13fd1dd46eae44af8b91ad1ccae5b7a1c92944f92a19f21b0b658139e0cabe9c1f679507c2de354bf2c91ebd965d1e633978a830d517d2f6f8dd5fd58065d58559de7e2334a878f8ec6992d9b9e77430d4764e863d77c0f87beede8f2f7f2ab2e7222f85cc9d98b8467f4bb72e87ef2882423ebdb6daf02dddac6db2" + }, + { + "name": "nagydani-3-square", + "input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb02d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d", + "expected": "affc7507ea6d84751ec6b3f0d7b99dbcc263f33330e450d1b3ff0bc3d0874320bf4edd57debd587306988157958cb3cfd369cc0c9c198706f635c9e0f15d047df5cb44d03e2727f26b083c4ad8485080e1293f171c1ed52aef5993a5815c35108e848c951cf1e334490b4a539a139e57b68f44fee583306f5b85ffa57206b3ee5660458858534e5386b9584af3c7f67806e84c189d695e5eb96e1272d06ec2df5dc5fabc6e94b793718c60c36be0a4d031fc84cd658aa72294b2e16fc240aef70cb9e591248e38bd49c5a554d1afa01f38dab72733092f7555334bbef6c8c430119840492380aa95fa025dcf699f0a39669d812b0c6946b6091e6e235337b6f8" + }, + { + "name": "nagydani-3-qube", + "input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb03d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d", + "expected": "1b280ecd6a6bf906b806d527c2a831e23b238f89da48449003a88ac3ac7150d6a5e9e6b3be4054c7da11dd1e470ec29a606f5115801b5bf53bc1900271d7c3ff3cd5ed790d1c219a9800437a689f2388ba1a11d68f6a8e5b74e9a3b1fac6ee85fc6afbac599f93c391f5dc82a759e3c6c0ab45ce3f5d25d9b0c1bf94cf701ea6466fc9a478dacc5754e593172b5111eeba88557048bceae401337cd4c1182ad9f700852bc8c99933a193f0b94cf1aedbefc48be3bc93ef5cb276d7c2d5462ac8bb0c8fe8923a1db2afe1c6b90d59c534994a6a633f0ead1d638fdc293486bb634ff2c8ec9e7297c04241a61c37e3ae95b11d53343d4ba2b4cc33d2cfa7eb705e" + }, + { + "name": "nagydani-3-pow0x10001", + "input": "000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000100c9130579f243e12451760976261416413742bd7c91d39ae087f46794062b8c239f2a74abf3918605a0e046a7890e049475ba7fbb78f5de6490bd22a710cc04d30088179a919d86c2da62cf37f59d8f258d2310d94c24891be2d7eeafaa32a8cb4b0cfe5f475ed778f45907dc8916a73f03635f233f7a77a00a3ec9ca6761a5bbd558a2318ecd0caa1c5016691523e7e1fa267dd35e70c66e84380bdcf7c0582f540174e572c41f81e93da0b757dff0b0fe23eb03aa19af0bdec3afb474216febaacb8d0381e631802683182b0fe72c28392539850650b70509f54980241dc175191a35d967288b532a7a8223ce2440d010615f70df269501944d4ec16fe4a3cb010001d7a85909174757835187cb52e71934e6c07ef43b4c46fc30bbcd0bc72913068267c54a4aabebb493922492820babdeb7dc9b1558fcf7bd82c37c82d3147e455b623ab0efa752fe0b3a67ca6e4d126639e645a0bf417568adbb2a6a4eef62fa1fa29b2a5a43bebea1f82193a7dd98eb483d09bb595af1fa9c97c7f41f5649d976aee3e5e59e2329b43b13bea228d4a93f16ba139ccb511de521ffe747aa2eca664f7c9e33da59075cc335afcd2bf3ae09765f01ab5a7c3e3938ec168b74724b5074247d200d9970382f683d6059b94dbc336603d1dfee714e4b447ac2fa1d99ecb4961da2854e03795ed758220312d101e1e3d87d5313a6d052aebde75110363d", + "expected": "37843d7c67920b5f177372fa56e2a09117df585f81df8b300fba245b1175f488c99476019857198ed459ed8d9799c377330e49f4180c4bf8e8f66240c64f65ede93d601f957b95b83efdee1e1bfde74169ff77002eaf078c71815a9220c80b2e3b3ff22c2f358111d816ebf83c2999026b6de50bfc711ff68705d2f40b753424aefc9f70f08d908b5a20276ad613b4ab4309a3ea72f0c17ea9df6b3367d44fb3acab11c333909e02e81ea2ed404a712d3ea96bba87461720e2d98723e7acd0520ac1a5212dbedcd8dc0c1abf61d4719e319ff4758a774790b8d463cdfe131d1b2dcfee52d002694e98e720cb6ae7ccea353bc503269ba35f0f63bf8d7b672a76" + }, + { + "name": "nagydani-4-square", + "input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8102df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f", + "expected": "8a5aea5f50dcc03dc7a7a272b5aeebc040554dbc1ffe36753c4fc75f7ed5f6c2cc0de3a922bf96c78bf0643a73025ad21f45a4a5cadd717612c511ab2bff1190fe5f1ae05ba9f8fe3624de1de2a817da6072ddcdb933b50216811dbe6a9ca79d3a3c6b3a476b079fd0d05f04fb154e2dd3e5cb83b148a006f2bcbf0042efb2ae7b916ea81b27aac25c3bf9a8b6d35440062ad8eae34a83f3ffa2cc7b40346b62174a4422584f72f95316f6b2bee9ff232ba9739301c97c99a9ded26c45d72676eb856ad6ecc81d36a6de36d7f9dafafee11baa43a4b0d5e4ecffa7b9b7dcefd58c397dd373e6db4acd2b2c02717712e6289bed7c813b670c4a0c6735aa7f3b0f1ce556eae9fcc94b501b2c8781ba50a8c6220e8246371c3c7359fe4ef9da786ca7d98256754ca4e496be0a9174bedbecb384bdf470779186d6a833f068d2838a88d90ef3ad48ff963b67c39cc5a3ee123baf7bf3125f64e77af7f30e105d72c4b9b5b237ed251e4c122c6d8c1405e736299c3afd6db16a28c6a9cfa68241e53de4cd388271fe534a6a9b0dbea6171d170db1b89858468885d08fecbd54c8e471c3e25d48e97ba450b96d0d87e00ac732aaa0d3ce4309c1064bd8a4c0808a97e0143e43a24cfa847635125cd41c13e0574487963e9d725c01375db99c31da67b4cf65eff555f0c0ac416c727ff8d438ad7c42030551d68c2e7adda0abb1ca7c10" + }, + { + "name": "nagydani-4-qube", + "input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b8103df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f", + "expected": "5a2664252aba2d6e19d9600da582cdd1f09d7a890ac48e6b8da15ae7c6ff1856fc67a841ac2314d283ffa3ca81a0ecf7c27d89ef91a5a893297928f5da0245c99645676b481b7e20a566ee6a4f2481942bee191deec5544600bb2441fd0fb19e2ee7d801ad8911c6b7750affec367a4b29a22942c0f5f4744a4e77a8b654da2a82571037099e9c6d930794efe5cdca73c7b6c0844e386bdca8ea01b3d7807146bb81365e2cdc6475f8c23e0ff84463126189dc9789f72bbce2e3d2d114d728a272f1345122de23df54c922ec7a16e5c2a8f84da8871482bd258c20a7c09bbcd64c7a96a51029bbfe848736a6ba7bf9d931a9b7de0bcaf3635034d4958b20ae9ab3a95a147b0421dd5f7ebff46c971010ebfc4adbbe0ad94d5498c853e7142c450d8c71de4b2f84edbf8acd2e16d00c8115b150b1c30e553dbb82635e781379fe2a56360420ff7e9f70cc64c00aba7e26ed13c7c19622865ae07248daced36416080f35f8cc157a857ed70ea4f347f17d1bee80fa038abd6e39b1ba06b97264388b21364f7c56e192d4b62d9b161405f32ab1e2594e86243e56fcf2cb30d21adef15b9940f91af681da24328c883d892670c6aa47940867a81830a82b82716895db810df1b834640abefb7db2092dd92912cb9a735175bc447be40a503cf22dfe565b4ed7a3293ca0dfd63a507430b323ee248ec82e843b673c97ad730728cebc" + }, + { + "name": "nagydani-4-pow0x10001", + "input": "000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000200db34d0e438249c0ed685c949cc28776a05094e1c48691dc3f2dca5fc3356d2a0663bd376e4712839917eb9a19c670407e2c377a2de385a3ff3b52104f7f1f4e0c7bf7717fb913896693dc5edbb65b760ef1b00e42e9d8f9af17352385e1cd742c9b006c0f669995cb0bb21d28c0aced2892267637b6470d8cee0ab27fc5d42658f6e88240c31d6774aa60a7ebd25cd48b56d0da11209f1928e61005c6eb709f3e8e0aaf8d9b10f7d7e296d772264dc76897ccdddadc91efa91c1903b7232a9e4c3b941917b99a3bc0c26497dedc897c25750af60237aa67934a26a2bc491db3dcc677491944bc1f51d3e5d76b8d846a62db03dedd61ff508f91a56d71028125035c3a44cbb041497c83bf3e4ae2a9613a401cc721c547a2afa3b16a2969933d3626ed6d8a7428648f74122fd3f2a02a20758f7f693892c8fd798b39abac01d18506c45e71432639e9f9505719ee822f62ccbf47f6850f096ff77b5afaf4be7d772025791717dbe5abf9b3f40cff7d7aab6f67e38f62faf510747276e20a42127e7500c444f9ed92baf65ade9e836845e39c4316d9dce5f8e2c8083e2c0acbb95296e05e51aab13b6b8f53f06c9c4276e12b0671133218cc3ea907da3bd9a367096d9202128d14846cc2e20d56fc8473ecb07cecbfb8086919f3971926e7045b853d85a69d026195c70f9f7a823536e2a8f4b3e12e94d9b53a934353451094b81010001df3143a0057457d75e8c708b6337a6f5a4fd1a06727acf9fb93e2993c62f3378b37d56c85e7b1e00f0145ebf8e4095bd723166293c60b6ac1252291ef65823c9e040ddad14969b3b340a4ef714db093a587c37766d68b8d6b5016e741587e7e6bf7e763b44f0247e64bae30f994d248bfd20541a333e5b225ef6a61199e301738b1e688f70ec1d7fb892c183c95dc543c3e12adf8a5e8b9ca9d04f9445cced3ab256f29e998e69efaa633a7b60e1db5a867924ccab0a171d9d6e1098dfa15acde9553de599eaa56490c8f411e4985111f3d40bddfc5e301edb01547b01a886550a61158f7e2033c59707789bf7c854181d0c2e2a42a93cf09209747d7082e147eb8544de25c3eb14f2e35559ea0c0f5877f2f3fc92132c0ae9da4e45b2f6c866a224ea6d1f28c05320e287750fbc647368d41116e528014cc1852e5531d53e4af938374daba6cee4baa821ed07117253bb3601ddd00d59a3d7fb2ef1f5a2fbba7c429f0cf9a5b3462410fd833a69118f8be9c559b1000cc608fd877fb43f8e65c2d1302622b944462579056874b387208d90623fcdaf93920ca7a9e4ba64ea208758222ad868501cc2c345e2d3a5ea2a17e5069248138c8a79c0251185d29ee73e5afab5354769142d2bf0cb6712727aa6bf84a6245fcdae66e4938d84d1b9dd09a884818622080ff5f98942fb20acd7e0c916c2d5ea7ce6f7e173315384518f", + "expected": "bed8b970c4a34849fc6926b08e40e20b21c15ed68d18f228904878d4370b56322d0da5789da0318768a374758e6375bfe4641fca5285ec7171828922160f48f5ca7efbfee4d5148612c38ad683ae4e3c3a053d2b7c098cf2b34f2cb19146eadd53c86b2d7ccf3d83b2c370bfb840913ee3879b1057a6b4e07e110b6bcd5e958bc71a14798c91d518cc70abee264b0d25a4110962a764b364ac0b0dd1ee8abc8426d775ec0f22b7e47b32576afaf1b5a48f64573ed1c5c29f50ab412188d9685307323d990802b81dacc06c6e05a1e901830ba9fcc67688dc29c5e27bde0a6e845ca925f5454b6fb3747edfaa2a5820838fb759eadf57f7cb5cec57fc213ddd8a4298fa079c3c0f472b07fb15aa6a7f0a3780bd296ff6a62e58ef443870b02260bd4fd2bbc98255674b8e1f1f9f8d33c7170b0ebbea4523b695911abbf26e41885344823bd0587115fdd83b721a4e8457a31c9a84b3d3520a07e0e35df7f48e5a9d534d0ec7feef1ff74de6a11e7f93eab95175b6ce22c68d78a642ad642837897ec11349205d8593ac19300207572c38d29ca5dfa03bc14cdbc32153c80e5cc3e739403d34c75915e49beb43094cc6dcafb3665b305ddec9286934ae66ec6b777ca528728c851318eb0f207b39f1caaf96db6eeead6b55ed08f451939314577d42bcc9f97c0b52d0234f88fd07e4c1d7780fdebc025cfffcb572cb27a8c33963" + }, + { + "name": "nagydani-5-square", + "input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf02e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad", + "expected": "d61fe4e3f32ac260915b5b03b78a86d11bfc41d973fce5b0cc59035cf8289a8a2e3878ea15fa46565b0d806e2f85b53873ea20ed653869b688adf83f3ef444535bf91598ff7e80f334fb782539b92f39f55310cc4b35349ab7b278346eda9bc37c0d8acd3557fae38197f412f8d9e57ce6a76b7205c23564cab06e5615be7c6f05c3d05ec690cba91da5e89d55b152ff8dd2157dc5458190025cf94b1ad98f7cbe64e9482faba95e6b33844afc640892872b44a9932096508f4a782a4805323808f23e54b6ff9b841dbfa87db3505ae4f687972c18ea0f0d0af89d36c1c2a5b14560c153c3fee406f5cf15cfd1c0bb45d767426d465f2f14c158495069d0c5955a00150707862ecaae30624ebacdd8ac33e4e6aab3ff90b6ba445a84689386b9e945d01823a65874444316e83767290fcff630d2477f49d5d8ffdd200e08ee1274270f86ed14c687895f6caf5ce528bd970c20d2408a9ba66216324c6a011ac4999098362dbd98a038129a2d40c8da6ab88318aa3046cb660327cc44236d9e5d2163bd0959062195c51ed93d0088b6f92051fc99050ece2538749165976233697ab4b610385366e5ce0b02ad6b61c168ecfbedcdf74278a38de340fd7a5fead8e588e294795f9b011e2e60377a89e25c90e145397cdeabc60fd32444a6b7642a611a83c464d8b8976666351b4865c37b02e6dc21dbcdf5f930341707b618cc0f03c3122646b3385c9df9f2ec730eec9d49e7dfc9153b6e6289da8c4f0ebea9ccc1b751948e3bb7171c9e4d57423b0eeeb79095c030cb52677b3f7e0b45c30f645391f3f9c957afa549c4e0b2465b03c67993cd200b1af01035962edbc4c9e89b31c82ac121987d6529dafdeef67a132dc04b6dc68e77f22862040b75e2ceb9ff16da0fca534e6db7bd12fa7b7f51b6c08c1e23dfcdb7acbd2da0b51c87ffbced065a612e9b1c8bba9b7e2d8d7a2f04fcc4aaf355b60d764879a76b5e16762d5f2f55d585d0c8e82df6940960cddfb72c91dfa71f6b4e1c6ca25dfc39a878e998a663c04fe29d5e83b9586d047b4d7ff70a9f0d44f127e7d741685ca75f11629128d916a0ffef4be586a30c4b70389cc746e84ebf177c01ee8a4511cfbb9d1ecf7f7b33c7dd8177896e10bbc82f838dcd6db7ac67de62bf46b6a640fb580c5d1d2708f3862e3d2b645d0d18e49ef088053e3a220adc0e033c2afcfe61c90e32151152eb3caaf746c5e377d541cafc6cbb0cc0fa48b5caf1728f2e1957f5addfc234f1a9d89e40d49356c9172d0561a695fce6dab1d412321bbf407f63766ffd7b6b3d79bcfa07991c5a9709849c1008689e3b47c50d613980bec239fb64185249d055b30375ccb4354d71fe4d05648fbf6c80634dfc3575f2f24abb714c1e4c95e8896763bf4316e954c7ad19e5780ab7a040ca6fb9271f90a8b22ae738daf6cb" + }, + { + "name": "nagydani-5-qube", + "input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf03e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad", + "expected": "5f9c70ec884926a89461056ad20ac4c30155e817f807e4d3f5bb743d789c83386762435c3627773fa77da5144451f2a8aad8adba88e0b669f5377c5e9bad70e45c86fe952b613f015a9953b8a5de5eaee4566acf98d41e327d93a35bd5cef4607d025e58951167957df4ff9b1627649d3943805472e5e293d3efb687cfd1e503faafeb2840a3e3b3f85d016051a58e1c9498aab72e63b748d834b31eb05d85dcde65e27834e266b85c75cc4ec0135135e0601cb93eeeb6e0010c8ceb65c4c319623c5e573a2c8c9fbbf7df68a930beb412d3f4dfd146175484f45d7afaa0d2e60684af9b34730f7c8438465ad3e1d0c3237336722f2aa51095bd5759f4b8ab4dda111b684aa3dac62a761722e7ae43495b7709933512c81c4e3c9133a51f7ce9f2b51fcec064f65779666960b4e45df3900f54311f5613e8012dd1b8efd359eda31a778264c72aa8bb419d862734d769076bce2810011989a45374e5c5d8729fec21427f0bf397eacbb4220f603cf463a4b0c94efd858ffd9768cd60d6ce68d755e0fbad007ce5c2223d70c7018345a102e4ab3c60a13a9e7794303156d4c2063e919f2153c13961fb324c80b240742f47773a7a8e25b3e3fb19b00ce839346c6eb3c732fbc6b888df0b1fe0a3d07b053a2e9402c267b2d62f794d8a2840526e3ade15ce2264496ccd7519571dfde47f7a4bb16292241c20b2be59f3f8fb4f6383f232d838c5a22d8c95b6834d9d2ca493f5a505ebe8899503b0e8f9b19e6e2dd81c1628b80016d02097e0134de51054c4e7674824d4d758760fc52377d2cad145e259aa2ffaf54139e1a66b1e0c1c191e32ac59474c6b526f5b3ba07d3e5ec286eddf531fcd5292869be58c9f22ef91026159f7cf9d05ef66b4299f4da48cc1635bf2243051d342d378a22c83390553e873713c0454ce5f3234397111ac3fe3207b86f0ed9fc025c81903e1748103692074f83824fda6341be4f95ff00b0a9a208c267e12fa01825054cc0513629bf3dbb56dc5b90d4316f87654a8be18227978ea0a8a522760cad620d0d14fd38920fb7321314062914275a5f99f677145a6979b156bd82ecd36f23f8e1273cc2759ecc0b2c69d94dad5211d1bed939dd87ed9e07b91d49713a6e16ade0a98aea789f04994e318e4ff2c8a188cd8d43aeb52c6daa3bc29b4af50ea82a247c5cd67b573b34cbadcc0a376d3bbd530d50367b42705d870f2e27a8197ef46070528bfe408360faa2ebb8bf76e9f388572842bcb119f4d84ee34ae31f5cc594f23705a49197b181fb78ed1ec99499c690f843a4d0cf2e226d118e9372271054fbabdcc5c92ae9fefaef0589cd0e722eaf30c1703ec4289c7fd81beaa8a455ccee5298e31e2080c10c366a6fcf56f7d13582ad0bcad037c612b710fc595b70fbefaaca23623b60c6c39b11beb8e5843b6b3dac60f" + }, + { + "name": "nagydani-5-pow0x10001", + "input": "000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000400c5a1611f8be90071a43db23cc2fe01871cc4c0e8ab5743f6378e4fef77f7f6db0095c0727e20225beb665645403453e325ad5f9aeb9ba99bf3c148f63f9c07cf4fe8847ad5242d6b7d4499f93bd47056ddab8f7dee878fc2314f344dbee2a7c41a5d3db91eff372c730c2fdd3a141a4b61999e36d549b9870cf2f4e632c4d5df5f024f81c028000073a0ed8847cfb0593d36a47142f578f05ccbe28c0c06aeb1b1da027794c48db880278f79ba78ae64eedfea3c07d10e0562668d839749dc95f40467d15cf65b9cfc52c7c4bcef1cda3596dd52631aac942f146c7cebd46065131699ce8385b0db1874336747ee020a5698a3d1a1082665721e769567f579830f9d259cec1a836845109c21cf6b25da572512bf3c42fd4b96e43895589042ab60dd41f497db96aec102087fe784165bb45f942859268fd2ff6c012d9d00c02ba83eace047cc5f7b2c392c2955c58a49f0338d6fc58749c9db2155522ac17914ec216ad87f12e0ee95574613942fa615898c4d9e8a3be68cd6afa4e7a003dedbdf8edfee31162b174f965b20ae752ad89c967b3068b6f722c16b354456ba8e280f987c08e0a52d40a2e8f3a59b94d590aeef01879eb7a90b3ee7d772c839c85519cbeaddc0c193ec4874a463b53fcaea3271d80ebfb39b33489365fc039ae549a17a9ff898eea2f4cb27b8dbee4c17b998438575b2b8d107e4a0d66ba7fca85b41a58a8d51f191a35c856dfbe8aef2b00048a694bbccff832d23c8ca7a7ff0b6c0b3011d00b97c86c0628444d267c951d9e4fb8f83e154b8f74fb51aa16535e498235c5597dac9606ed0be3173a3836baa4e7d756ffe1e2879b415d3846bccd538c05b847785699aefde3e305decb600cd8fb0e7d8de5efc26971a6ad4e6d7a2d91474f1023a0ac4b78dc937da0ce607a45974d2cac1c33a2631ff7fe6144a3b2e5cf98b531a9627dea92c1dc82204d09db0439b6a11dd64b484e1263aa45fd9539b6020b55e3baece3986a8bffc1003406348f5c61265099ed43a766ee4f93f5f9c5abbc32a0fd3ac2b35b87f9ec26037d88275bd7dd0a54474995ee34ed3727f3f97c48db544b1980193a4b76a8a3ddab3591ce527f16d91882e67f0103b5cda53f7da54d489fc4ac08b6ab358a5a04aa9daa16219d50bd672a7cb804ed769d218807544e5993f1c27427104b349906a0b654df0bf69328afd3013fbe430155339c39f236df5557bf92f1ded7ff609a8502f49064ec3d1dbfb6c15d3a4c11a4f8acd12278cbf68acd5709463d12e3338a6eddb8c112f199645e23154a8e60879d2a654e3ed9296aa28f134168619691cd2c6b9e2eba4438381676173fc63c2588a3c5910dc149cf3760f0aa9fa9c3f5faa9162b0bf1aac9dd32b706a60ef53cbdb394b6b40222b5bc80eea82ba8958386672564cae3794f977871ab62337cf010001e30049201ec12937e7ce79d0f55d9c810e20acf52212aca1d3888949e0e4830aad88d804161230eb89d4d329cc83570fe257217d2119134048dd2ed167646975fc7d77136919a049ea74cf08ddd2b896890bb24a0ba18094a22baa351bf29ad96c66bbb1a598f2ca391749620e62d61c3561a7d3653ccc8892c7b99baaf76bf836e2991cb06d6bc0514568ff0d1ec8bb4b3d6984f5eaefb17d3ea2893722375d3ddb8e389a8eef7d7d198f8e687d6a513983df906099f9a2d23f4f9dec6f8ef2f11fc0a21fac45353b94e00486f5e17d386af42502d09db33cf0cf28310e049c07e88682aeeb00cb833c5174266e62407a57583f1f88b304b7c6e0c84bbe1c0fd423072d37a5bd0aacf764229e5c7cd02473460ba3645cd8e8ae144065bf02d0dd238593d8e230354f67e0b2f23012c23274f80e3ee31e35e2606a4a3f31d94ab755e6d163cff52cbb36b6d0cc67ffc512aeed1dce4d7a0d70ce82f2baba12e8d514dc92a056f994adfb17b5b9712bd5186f27a2fda1f7039c5df2c8587fdc62f5627580c13234b55be4df3056050e2d1ef3218f0dd66cb05265fe1acfb0989d8213f2c19d1735a7cf3fa65d88dad5af52dc2bba22b7abf46c3bc77b5091baab9e8f0ddc4d5e581037de91a9f8dcbc69309be29cc815cf19a20a7585b8b3073edf51fc9baeb3e509b97fa4ecfd621e0fd57bd61cac1b895c03248ff12bdbc57509250df3517e8a3fe1d776836b34ab352b973d932ef708b14f7418f9eceb1d87667e61e3e758649cb083f01b133d37ab2f5afa96d6c84bcacf4efc3851ad308c1e7d9113624fce29fab460ab9d2a48d92cdb281103a5250ad44cb2ff6e67ac670c02fdafb3e0f1353953d6d7d5646ca1568dea55275a050ec501b7c6250444f7219f1ba7521ba3b93d089727ca5f3bbe0d6c1300b423377004954c5628fdb65770b18ced5c9b23a4a5a6d6ef25fe01b4ce278de0bcc4ed86e28a0a68818ffa40970128cf2c38740e80037984428c1bd5113f40ff47512ee6f4e4d8f9b8e8e1b3040d2928d003bd1c1329dc885302fbce9fa81c23b4dc49c7c82d29b52957847898676c89aa5d32b5b0e1c0d5a2b79a19d67562f407f19425687971a957375879d90c5f57c857136c17106c9ab1b99d80e69c8c954ed386493368884b55c939b8d64d26f643e800c56f90c01079d7c534e3b2b7ae352cefd3016da55f6a85eb803b85e2304915fd2001f77c74e28746293c46e4f5f0fd49cf988aafd0026b8e7a3bab2da5cdce1ea26c2e29ec03f4807fac432662b2d6c060be1c7be0e5489de69d0a6e03a4b9117f9244b34a0f1ecba89884f781c6320412413a00c4980287409a2a78c2cd7e65cecebbe4ec1c28cac4dd95f6998e78fc6f1392384331c9436aa10e10e2bf8ad2c4eafbcf276aa7bae64b74428911b3269c749338b0fc5075ad", + "expected": "5a0eb2bdf0ac1cae8e586689fa16cd4b07dfdedaec8a110ea1fdb059dd5253231b6132987598dfc6e11f86780428982d50cf68f67ae452622c3b336b537ef3298ca645e8f89ee39a26758206a5a3f6409afc709582f95274b57b71fae5c6b74619ae6f089a5393c5b79235d9caf699d23d88fb873f78379690ad8405e34c19f5257d596580c7a6a7206a3712825afe630c76b31cdb4a23e7f0632e10f14f4e282c81a66451a26f8df2a352b5b9f607a7198449d1b926e27036810368e691a74b91c61afa73d9d3b99453e7c8b50fd4f09c039a2f2feb5c419206694c31b92df1d9586140cb3417b38d0c503c7b508cc2ed12e813a1c795e9829eb39ee78eeaf360a169b491a1d4e419574e712402de9d48d54c1ae5e03739b7156615e8267e1fb0a897f067afd11fb33f6e24182d7aaaaa18fe5bc1982f20d6b871e5a398f0f6f718181d31ec225cfa9a0a70124ed9a70031bdf0c1c7829f708b6e17d50419ef361cf77d99c85f44607186c8d683106b8bd38a49b5d0fb503b397a83388c5678dcfcc737499d84512690701ed621a6f0172aecf037184ddf0f2453e4053024018e5ab2e30d6d5363b56e8b41509317c99042f517247474ab3abc848e00a07f69c254f46f2a05cf6ed84e5cc906a518fdcfdf2c61ce731f24c5264f1a25fc04934dc28aec112134dd523f70115074ca34e3807aa4cb925147f3a0ce152d323bd8c675ace446d0fd1ae30c4b57f0eb2c23884bc18f0964c0114796c5b6d080c3d89175665fbf63a6381a6a9da39ad070b645c8bb1779506da14439a9f5b5d481954764ea114fac688930bc68534d403cff4210673b6a6ff7ae416b7cd41404c3d3f282fcd193b86d0f54d0006c2a503b40d5c3930da980565b8f9630e9493a79d1c03e74e5f93ac8e4dc1a901ec5e3b3e57049124c7b72ea345aa359e782285d9e6a5c144a378111dd02c40855ff9c2be9b48425cb0b2fd62dc8678fd151121cf26a65e917d65d8e0dacfae108eb5508b601fb8ffa370be1f9a8b749a2d12eeab81f41079de87e2d777994fa4d28188c579ad327f9957fb7bdecec5c680844dd43cb57cf87aeb763c003e65011f73f8c63442df39a92b946a6bd968a1c1e4d5fa7d88476a68bd8e20e5b70a99259c7d3f85fb1b65cd2e93972e6264e74ebf289b8b6979b9b68a85cd5b360c1987f87235c3c845d62489e33acf85d53fa3561fe3a3aee18924588d9c6eba4edb7a4d106b31173e42929f6f0c48c80ce6a72d54eca7c0fe870068b7a7c89c63cdda593f5b32d3cb4ea8a32c39f00ab449155757172d66763ed9527019d6de6c9f2416aa6203f4d11c9ebee1e1d3845099e55504446448027212616167eb36035726daa7698b075286f5379cd3e93cb3e0cf4f9cb8d017facbb5550ed32d5ec5400ae57e47e2bf78d1eaeff9480cc765ceff39db500" + } + ] +} \ No newline at end of file diff --git a/tests/fixtures/PrecompileTests/pairing.json b/tests/fixtures/PrecompileTests/pairing.json new file mode 100644 index 000000000..73e4b4c0f --- /dev/null +++ b/tests/fixtures/PrecompileTests/pairing.json @@ -0,0 +1,75 @@ +{ + "ecpairing": + [ + { + "name": "jeff1", + "input": "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "expected": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "name": "jeff2", + "input": "2eca0c7238bf16e83e7a1e6c5d49540685ff51380f309842a98561558019fc0203d3260361bb8451de5ff5ecd17f010ff22f5c31cdf184e9020b06fa5997db841213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f06967a1237ebfeca9aaae0d6d0bab8e28c198c5a339ef8a2407e31cdac516db922160fa257a5fd5b280642ff47b65eca77e626cb685c84fa6d3b6882a283ddd1198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "expected": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "name": "jeff3", + "input": "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb314a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee245901b9e027bd5cfc2cb5db82d4dc9677ac795ec500ecd47deee3b5da006d6d049b811d7511c78158de484232fc68daf8a45cf217d1c2fae693ff5871e8752d73b21198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "expected": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "name": "jeff4", + "input": "2f2ea0b3da1e8ef11914acf8b2e1b32d99df51f5f4f206fc6b947eae860eddb6068134ddb33dc888ef446b648d72338684d678d2eb2371c61a50734d78da4b7225f83c8b6ab9de74e7da488ef02645c5a16a6652c3c71a15dc37fe3a5dcb7cb122acdedd6308e3bb230d226d16a105295f523a8a02bfc5e8bd2da135ac4c245d065bbad92e7c4e31bf3757f1fe7362a63fbfee50e7dc68da116e67d600d9bf6806d302580dc0661002994e7cd3a7f224e7ddc27802777486bf80f40e4ca3cfdb186bac5188a98c45e6016873d107f5cd131f3a3e339d0375e58bd6219347b008122ae2b09e539e152ec5364e7e2204b03d11d3caa038bfc7cd499f8176aacbee1f39e4e4afc4bc74790a4a028aff2c3d2538731fb755edefd8cb48d6ea589b5e283f150794b6736f670d6a1033f9b46c6f5204f50813eb85c8dc4b59db1c5d39140d97ee4d2b36d99bc49974d18ecca3e7ad51011956051b464d9e27d46cc25e0764bb98575bd466d32db7b15f582b2d5c452b36aa394b789366e5e3ca5aabd415794ab061441e51d01e94640b7e3084a07e02c78cf3103c542bc5b298669f211b88da1679b0b64a63b7e0e7bfe52aae524f73a55be7fe70c7e9bfc94b4cf0da1213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f", + "expected": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "name": "jeff5", + "input": "20a754d2071d4d53903e3b31a7e98ad6882d58aec240ef981fdf0a9d22c5926a29c853fcea789887315916bbeb89ca37edb355b4f980c9a12a94f30deeed30211213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f1abb4a25eb9379ae96c84fff9f0540abcfc0a0d11aeda02d4f37e4baf74cb0c11073b3ff2cdbb38755f8691ea59e9606696b3ff278acfc098fa8226470d03869217cee0a9ad79a4493b5253e2e4e3a39fc2df38419f230d341f60cb064a0ac290a3d76f140db8418ba512272381446eb73958670f00cf46f1d9e64cba057b53c26f64a8ec70387a13e41430ed3ee4a7db2059cc5fc13c067194bcc0cb49a98552fd72bd9edb657346127da132e5b82ab908f5816c826acb499e22f2412d1a2d70f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2198a1f162a73261f112401aa2db79c7dab1533c9935c77290a6ce3b191f2318d198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "expected": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "name": "jeff6", + "input": "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c103188585e2364128fe25c70558f1560f4f9350baf3959e603cc91486e110936198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "expected": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "empty_data", + "input": "", + "expected": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "name": "one_point", + "input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "expected": "0000000000000000000000000000000000000000000000000000000000000000" + }, + { + "name": "two_point_match_2", + "input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d", + "expected": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "name": "two_point_match_3", + "input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "expected": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "name": "two_point_match_4", + "input": "105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c51bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e60071f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b4a106054688728c9972c8512e9789e9567aae23e302ccd75", + "expected": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "name": "ten_point_match_1", + "input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d", + "expected": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "name": "ten_point_match_2", + "input": "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + "expected": "0000000000000000000000000000000000000000000000000000000000000001" + }, + { + "name": "ten_point_match_3", + "input": "105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c51bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e60071f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b4a106054688728c9972c8512e9789e9567aae23e302ccd75", + "expected": "0000000000000000000000000000000000000000000000000000000000000001" + } + ] +} diff --git a/tests/fixtures/PrecompileTests/ripemd160.json b/tests/fixtures/PrecompileTests/ripemd160.json new file mode 100644 index 000000000..e81c0f9dc --- /dev/null +++ b/tests/fixtures/PrecompileTests/ripemd160.json @@ -0,0 +1,10 @@ +{ + "RIPEMD": + [ + { + "name": "128", + "input": "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02", + "expected": "0000000000000000000000009215b8d9882ff46f0dfde6684d78e831467f65e6" + } + ] +} \ No newline at end of file diff --git a/tests/fixtures/PrecompileTests/sha256.json b/tests/fixtures/PrecompileTests/sha256.json new file mode 100644 index 000000000..6e050a951 --- /dev/null +++ b/tests/fixtures/PrecompileTests/sha256.json @@ -0,0 +1,26 @@ +{ + "SHA256": + [ + { + "name": "128", + "input": "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02", + "expected": "811c7003375852fabd0d362e40e68607a12bdabae61a7d068fe5fdd1dbbf2a5d" + }, + { + "name": "128", + "input": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "expected": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + }, + { + "name": "128", + "input": "ffffffffffffffff", + "expected": "e3b0c44298fc1c14" + }, + { + "name": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "input": "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02", + "expected": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855ffff" + } + ] + +} From 7c778867a2f7e2e4b229c7d5ea275a3b73566731 Mon Sep 17 00:00:00 2001 From: coffeepots Date: Wed, 10 Oct 2018 17:26:32 +0100 Subject: [PATCH 13/27] Allow simpler json files to be processed, add dir sep for echo --- tests/test_helpers.nim | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/test_helpers.nim b/tests/test_helpers.nim index 33841fd4c..421358539 100644 --- a/tests/test_helpers.nim +++ b/tests/test_helpers.nim @@ -105,7 +105,8 @@ proc lacksHomesteadPostStates*(filename: string): bool = fixture = child break - return fixture.has_key("transaction") and not fixture["post"].has_key("Homestead") + return fixture.kind == JObject and fixture.has_key("transaction") and + (fixture.has_key("post") and not fixture["post"].has_key("Homestead")) macro jsonTest*(s: static[string], handler: untyped): untyped = let @@ -129,7 +130,7 @@ macro jsonTest*(s: static[string], handler: untyped): untyped = for child in filenames: let (filename, folder, name) = child test filename: - echo folder, name + echo folder / name status[folder][name] = Status.FAIL try: `handler`(parseJSON(readFile(filename)), `testStatusIMPL`) From e53222c7abf38e1914df0ee7b20dd92c570601a5 Mon Sep 17 00:00:00 2001 From: coffeepots Date: Wed, 10 Oct 2018 17:27:00 +0100 Subject: [PATCH 14/27] Test suite for precompiles --- tests/test_precompiles.nim | 57 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 tests/test_precompiles.nim diff --git a/tests/test_precompiles.nim b/tests/test_precompiles.nim new file mode 100644 index 000000000..c25c7f79e --- /dev/null +++ b/tests/test_precompiles.nim @@ -0,0 +1,57 @@ +# Nimbus +# Copyright (c) 2018 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 + unittest, ../nimbus/vm/precompiles, json, byteutils, test_helpers, ospaths, tables, + strformat, strutils, eth_trie/[types, memdb], eth_common, ../nimbus/db/[db_chain, state_db], + ../nimbus/[constants, vm_types, vm_state], ../nimbus/vm/[computation, message], macros + +proc initAddress(i: byte): EthAddress = result[19] = i + +template doTest(fixture: JsonNode, address: byte, action: untyped): untyped = + for test in fixture: + let + blockNum = 1.u256 # TODO: Check other forks + header = BlockHeader(blockNumber: blockNum) + expected = test["expected"].getStr.hexToSeqByte + var addressBytes = newSeq[byte](32) + addressBytes[31] = address # TODO: Endian + var + # Data has the address injected at the start to simulate the real call. + dataStr = test["input"].getStr + data = if dataStr.len > 0: dataStr.hexToSeqByte else: @[] + memDb = newMemDB() + vmState = newBaseVMState(header, newBaseChainDB(newMemoryDb())) + gas = 1_000_000.GasInt + gasPrice = 1.GasInt + sender: EthAddress + to = initAddress(address) + message = newMessage(gas, gasPrice, to, sender, 0.u256, data, @[]) + computation = newBaseComputation(vmState, header.blockNumber, message) + echo "Running ", action.astToStr, " - ", test["name"] + `action`(computation) + let c = computation.rawOutput == expected + if not c: echo "Output : " & computation.rawOutput.toHex & "\nExpected: " & expected.toHex + check c + +proc testFixture(fixtures: JsonNode, testStatusIMPL: var TestStatus) = + for label, child in fixtures: + case toLowerAscii(label) + of "ecrecover": child.doTest(paEcRecover.ord, ecRecover) + of "sha256": child.doTest(paSha256.ord, sha256) + of "ripemd": child.doTest(paRipeMd160.ord, ripemd160) + of "identity": child.doTest(paIdentity.ord, identity) + of "modexp": child.doTest(paModExp.ord, modexp) + of "bn256add": child.doTest(paEcAdd.ord, bn256ECAdd) + of "bn256mul": child.doTest(paEcMul.ord, bn256ECMul) + of "ecpairing": child.doTest(paPairing.ord, bn256ecPairing) + else: + #raise newException(ValueError, "Unknown test vector '" & $label & "'") + echo "Unknown test vector '" & $label & "'" + +suite "Precompiles": + jsonTest("PrecompileTests", testFixture) From 67df44e917f13f7cf051ce6b04eef926f8826a31 Mon Sep 17 00:00:00 2001 From: coffeepots Date: Wed, 10 Oct 2018 17:36:11 +0100 Subject: [PATCH 15/27] Fix ecrecover, pad ripemd result and use sha256 vs keccak256 --- nimbus/vm/precompiles.nim | 51 ++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/nimbus/vm/precompiles.nim b/nimbus/vm/precompiles.nim index 09720bb94..56fb0b94a 100644 --- a/nimbus/vm/precompiles.nim +++ b/nimbus/vm/precompiles.nim @@ -4,7 +4,7 @@ import message, math, nimcrypto, bncurve/[fields, groups] type - PrecompileAddresses = enum + PrecompileAddresses* = enum paEcRecover = 1, paSha256, paRipeMd160, @@ -15,12 +15,24 @@ type paEcMul, paPairing = 8 -proc getSignature*(computation: BaseComputation): Signature = - var bytes: array[128, byte] - bytes[0..31] = computation.msg.data[32..63] # V - bytes[32..63] = computation.msg.data[64..95] # R - bytes[64..63] = computation.msg.data[96..128] # S - result = initSignature(bytes) # Can raise +proc getSignature*(computation: BaseComputation): (array[32, byte], Signature) = + # input is Hash, V, R, S + template data: untyped = computation.msg.data + var bytes: array[65, byte] + let maxPos = min(data.high, 127) + if maxPos >= 32: + # extract message hash + result[0][0..31] = data[0..31] + if maxPos >= 127: + # Copy message data to buffer + # Note that we need to rearrange to R, S, V + bytes[0..63] = data[64..127] + let v = data[63] # TODO: Endian + assert v.int in 27..28 + bytes[64] = v - 27 + + if recoverSignature(bytes, result[1]) != EthKeysStatus.Success: + raise newException(ValidationError, "Could not recover signature computation") proc getPoint[T: G1|G2](t: typedesc[T], data: openarray[byte]): Point[T] = when T is G1: @@ -50,17 +62,15 @@ proc ecRecover*(computation: var BaseComputation) = GasECRecover, reason="ECRecover Precompile") - # TODO: Check endian - # Assumes V is 27 or 28 var - sig = computation.getSignature() + (msgHash, sig) = computation.getSignature() pubKey: PublicKey - let msgHash = computation.msg.data[0..31] if sig.recoverSignatureKey(msgHash, pubKey) != EthKeysStatus.Success: raise newException(ValidationError, "Could not derive public key from computation") - - computation.rawOutput = @(pubKey.toCanonicalAddress()) + + computation.rawOutput.setLen(32) + computation.rawOutput[12..31] = pubKey.toCanonicalAddress() debug "ECRecover precompile", derivedKey = pubKey.toCanonicalAddress() proc sha256*(computation: var BaseComputation) = @@ -69,17 +79,18 @@ proc sha256*(computation: var BaseComputation) = gasFee = GasSHA256 + wordCount * GasSHA256Word computation.gasMeter.consumeGas(gasFee, reason="SHA256 Precompile") - computation.rawOutput = @(keccak_256.digest(computation.msg.data).data) - debug "SHA256 precompile", output = computation.rawOutput + computation.rawOutput = @(nimcrypto.sha_256.digest(computation.msg.data).data) + debug "SHA256 precompile", output = computation.rawOutput.toHex -proc ripemd160(computation: var BaseComputation) = +proc ripemd160*(computation: var BaseComputation) = let wordCount = computation.msg.data.len div 32 gasFee = GasRIPEMD160 + wordCount * GasRIPEMD160Word computation.gasMeter.consumeGas(gasFee, reason="RIPEMD160 Precompile") - computation.rawOutput = @(nimcrypto.ripemd160.digest(computation.msg.data).data) - debug "RIPEMD160 precompile", output = computation.rawOutput + computation.rawOutput.setLen(32) + computation.rawOutput[12..31] = @(nimcrypto.ripemd160.digest(computation.msg.data).data) + debug "RIPEMD160 precompile", output = computation.rawOutput.toHex proc identity*(computation: var BaseComputation) = let @@ -88,9 +99,9 @@ proc identity*(computation: var BaseComputation) = computation.gasMeter.consumeGas(gasFee, reason="Identity Precompile") computation.rawOutput = computation.msg.data - debug "Identity precompile", output = computation.rawOutput + debug "Identity precompile", output = computation.rawOutput.toHex -proc modExp(computation: var BaseComputation) = +proc modExp*(computation: var BaseComputation) = ## Modular exponentiation precompiled contract # Parsing the data template rawMsg: untyped {.dirty.} = From 4ca4a859ad3a3644e879f74258d419677e5c622c Mon Sep 17 00:00:00 2001 From: coffeepots Date: Wed, 10 Oct 2018 18:47:54 +0100 Subject: [PATCH 16/27] Remove bogus sha256 tests --- tests/fixtures/PrecompileTests/sha256.json | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/tests/fixtures/PrecompileTests/sha256.json b/tests/fixtures/PrecompileTests/sha256.json index 6e050a951..431759443 100644 --- a/tests/fixtures/PrecompileTests/sha256.json +++ b/tests/fixtures/PrecompileTests/sha256.json @@ -5,21 +5,6 @@ "name": "128", "input": "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02", "expected": "811c7003375852fabd0d362e40e68607a12bdabae61a7d068fe5fdd1dbbf2a5d" - }, - { - "name": "128", - "input": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "expected": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - }, - { - "name": "128", - "input": "ffffffffffffffff", - "expected": "e3b0c44298fc1c14" - }, - { - "name": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "input": "38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e000000000000000000000000000000000000000000000000000000000000001b38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02", - "expected": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855ffff" } ] From 6e4616e4432ef306a52abb6f419dd251ceb07bdd Mon Sep 17 00:00:00 2001 From: coffeepots Date: Fri, 12 Oct 2018 16:16:14 +0100 Subject: [PATCH 17/27] Precompiles now executed if called from vm_state_transactions --- nimbus/vm/interpreter_dispatch.nim | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nimbus/vm/interpreter_dispatch.nim b/nimbus/vm/interpreter_dispatch.nim index a64b9bd62..cb6e1cd72 100644 --- a/nimbus/vm/interpreter_dispatch.nim +++ b/nimbus/vm/interpreter_dispatch.nim @@ -10,7 +10,7 @@ import chronicles, ./interpreter/[opcode_values, opcodes_impl, vm_forks, gas_costs, gas_meter, utils/macros_gen_opcodes], ./code_stream, - ../vm_types, ../errors, + ../vm_types, ../errors, precompiles, ./stack, ./computation, terminal # Those are only needed for logging func invalidInstruction*(computation: var BaseComputation) {.inline.} = @@ -220,7 +220,8 @@ macro genFrontierDispatch(computation: BaseComputation): untyped = result = opTableToCaseStmt(FrontierOpDispatch, computation) proc frontierVM(computation: var BaseComputation) = - genFrontierDispatch(computation) + if not computation.execPrecompiles: + genFrontierDispatch(computation) proc updateOpcodeExec*(computation: var BaseComputation, fork: Fork) = case fork From 0b15b8619514284edb7831d9cefbfc6e18f5f207 Mon Sep 17 00:00:00 2001 From: cheatfate Date: Tue, 16 Oct 2018 11:49:13 +0300 Subject: [PATCH 18/27] Fix ecMul, ecPairing, ecAdd. --- nimbus.nimble | 2 +- nimbus/vm/precompiles.nim | 14 +++++--------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/nimbus.nimble b/nimbus.nimble index a774fc365..9e898d043 100644 --- a/nimbus.nimble +++ b/nimbus.nimble @@ -20,7 +20,7 @@ requires "nim >= 0.18.1", "eth_p2p", "eth_keyfile", "eth_keys", - "https://github.com/status-im/nim-bncurve" + "https://github.com/status-im/nim-bncurve >= 1.0.1" proc buildBinary(name: string, srcDir = ".", lang = "c") = if not dirExists "build": mkDir "build" diff --git a/nimbus/vm/precompiles.nim b/nimbus/vm/precompiles.nim index 56fb0b94a..8abffd4a1 100644 --- a/nimbus/vm/precompiles.nim +++ b/nimbus/vm/precompiles.nim @@ -41,9 +41,9 @@ proc getPoint[T: G1|G2](t: typedesc[T], data: openarray[byte]): Point[T] = else: const nextOffset = 64 var px, py: FQ2 - if not px.fromBytes(data.toOpenArray(0, nextOffset - 1)): + if not px.fromBytes2(data.toOpenArray(0, nextOffset - 1)): raise newException(ValidationError, "Could not get point value") - if not py.fromBytes(data.toOpenArray(nextOffset, nextOffset * 2 - 1)): + if not py.fromBytes2(data.toOpenArray(nextOffset, nextOffset * 2 - 1)): raise newException(ValidationError, "Could not get point value") if px.isZero() and py.isZero(): result = T.zero() @@ -54,7 +54,7 @@ proc getPoint[T: G1|G2](t: typedesc[T], data: openarray[byte]): Point[T] = result = ap.toJacobian() proc getFR(data: openarray[byte]): FR = - if not result.fromBytes(data): + if not result.fromBytes2(data): raise newException(ValidationError, "Could not get FR value") proc ecRecover*(computation: var BaseComputation) = @@ -171,20 +171,17 @@ proc bn256ecAdd*(computation: var BaseComputation) = var input: array[128, byte] output: array[64, byte] - # Padding data let msglen = len(computation.msg.data) let tocopy = if msglen < 128: msglen else: 128 if tocopy > 0: copyMem(addr input[0], addr computation.msg.data[0], tocopy) - var p1 = G1.getPoint(input.toOpenArray(0, 63)) var p2 = G1.getPoint(input.toOpenArray(64, 127)) var apo = (p1 + p2).toAffine() if isSome(apo): - let p = apo.get() # we can discard here because we supply proper buffer - discard p.toBytes(output) + discard apo.get().toBytes(output) # TODO: gas computation # computation.gasMeter.consumeGas(gasFee, reason = "ecAdd Precompile") @@ -205,9 +202,8 @@ proc bn256ecMul*(computation: var BaseComputation) = var fr = getFR(input.toOpenArray(64, 95)) var apo = (p1 * fr).toAffine() if isSome(apo): - let p = apo.get() # we can discard here because we supply buffer of proper size - discard p.toBytes(output) + discard apo.get().toBytes(output) # TODO: gas computation # computation.gasMeter.consumeGas(gasFee, reason="ecMul Precompile") From 826ce4f0f91d1b7f5e2b6ef3e29f27beea711a6d Mon Sep 17 00:00:00 2001 From: coffeepots Date: Tue, 16 Oct 2018 21:51:32 +0100 Subject: [PATCH 19/27] Current test output --- PrecompileTests.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 PrecompileTests.md diff --git a/PrecompileTests.md b/PrecompileTests.md new file mode 100644 index 000000000..73046d08d --- /dev/null +++ b/PrecompileTests.md @@ -0,0 +1,14 @@ +PrecompileTests +=== +## PrecompileTests +```diff ++ bn256Add.json OK ++ bn256mul.json OK ++ ecrecover.json OK ++ identity.json OK +- modexp.json Fail ++ pairing.json OK ++ ripemd160.json OK ++ sha256.json OK +``` +OK: 7/8 Fail: 1/8 Skip: 0/8 From 434edcc2ae0aa3d3661ed0a75cba7a549b877223 Mon Sep 17 00:00:00 2001 From: coffeepots Date: Thu, 18 Oct 2018 17:47:54 +0100 Subject: [PATCH 20/27] Fix incorrect message parameters (had sender and destination swapped) --- nimbus/vm/computation.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimbus/vm/computation.nim b/nimbus/vm/computation.nim index a2b2e0776..68a25f385 100644 --- a/nimbus/vm/computation.nim +++ b/nimbus/vm/computation.nim @@ -78,8 +78,8 @@ proc prepareChildMessage*( result = newMessage( gas, c.msg.gasPrice, - c.msg.origin, to, + c.msg.origin, value, data, code, From 7ba1cfaf132553046892a6db581d0b465e74535e Mon Sep 17 00:00:00 2001 From: coffeepots Date: Fri, 19 Oct 2018 14:41:04 +0100 Subject: [PATCH 21/27] Remove endian code, precompiles should now run. Removed raise as case stmt is full now. --- nimbus/vm/precompiles.nim | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/nimbus/vm/precompiles.nim b/nimbus/vm/precompiles.nim index 8abffd4a1..dca91742e 100644 --- a/nimbus/vm/precompiles.nim +++ b/nimbus/vm/precompiles.nim @@ -243,15 +243,10 @@ proc bn256ecPairing*(computation: var BaseComputation) = computation.rawOutput = @output proc execPrecompiles*(computation: var BaseComputation): bool {.inline.} = - const - bRange = when system.cpuEndian == bigEndian: 0..18 else: 1..19 - bOffset = when system.cpuEndian == bigEndian: 19 else: 0 - - for i in bRange: + for i in 0..18: if computation.msg.codeAddress[i] != 0: return - let lb = computation.msg.codeAddress[bOffset] - + let lb = computation.msg.codeAddress[19] if lb in PrecompileAddresses.low.byte .. PrecompileAddresses.high.byte: result = true let precompile = PrecompileAddresses(lb) @@ -265,5 +260,3 @@ proc execPrecompiles*(computation: var BaseComputation): bool {.inline.} = of paEcAdd: bn256ecAdd(computation) of paEcMul: bn256ecMul(computation) of paPairing: bn256ecPairing(computation) - else: - raise newException(ValidationError, "Unknown precompile address " & $lb) From 6b1e989ff0db8ca65001efd7eb1bd63d3c904c37 Mon Sep 17 00:00:00 2001 From: coffeepots Date: Thu, 8 Nov 2018 15:47:48 +0000 Subject: [PATCH 22/27] Add initial gas cost for CREATE --- nimbus/vm/interpreter/gas_costs.nim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nimbus/vm/interpreter/gas_costs.nim b/nimbus/vm/interpreter/gas_costs.nim index b79dbc588..f3943c18d 100644 --- a/nimbus/vm/interpreter/gas_costs.nim +++ b/nimbus/vm/interpreter/gas_costs.nim @@ -168,7 +168,9 @@ template gasCosts(FeeSchedule: GasFeeSchedule, prefix, ResultGasCostsName: untyp result += static(FeeSchedule[GasExpByte]) * (1 + log256(value)) func `prefix gasCreate`(currentMemSize, memOffset, memLength: Natural): GasInt {.nimcall.} = - result = static(FeeSchedule[GasCodeDeposit]) * memLength + result = + static(FeeSchedule[GasCreate]) + + static(FeeSchedule[GasCodeDeposit]) * memLength func `prefix gasSha3`(currentMemSize, memOffset, memLength: Natural): GasInt {.nimcall.} = From 492d2ae67608e8170fdf76ddb7e69759467b0854 Mon Sep 17 00:00:00 2001 From: coffeepots Date: Thu, 8 Nov 2018 15:48:32 +0000 Subject: [PATCH 23/27] Debug message for new messages --- nimbus/vm/message.nim | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/nimbus/vm/message.nim b/nimbus/vm/message.nim index 5ef0be4aa..c3f215b54 100644 --- a/nimbus/vm/message.nim +++ b/nimbus/vm/message.nim @@ -7,7 +7,10 @@ import eth_common, - ../constants, ../validation, ../vm_types + ../constants, ../validation, ../vm_types, chronicles + +logScope: + topics = "message" proc `origin=`*(message: var Message, value: EthAddress) = message.internalOrigin = value @@ -44,6 +47,16 @@ proc newMessage*( validateGte(options.depth, minimum=0, title="Message.depth") + debug "New message", + gas = gas, + gasPrice = gasPrice, + destination = to, + sender = sender, + value = value, + depth = options.depth, + storageAddress = options.createAddress, + codeAddress = options.codeAddress + new(result) result.gas = gas result.gasPrice = gasPrice From 6eb430fd52e16272a905e3311ac7c764646f83ae Mon Sep 17 00:00:00 2001 From: coffeepots Date: Thu, 8 Nov 2018 16:00:21 +0000 Subject: [PATCH 24/27] Fix CREATE op code gas costs, more debug output, call transactions --- nimbus/vm/interpreter/opcodes_impl.nim | 48 ++++++++++++++++---------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/nimbus/vm/interpreter/opcodes_impl.nim b/nimbus/vm/interpreter/opcodes_impl.nim index b3cbaad08..7fd501033 100644 --- a/nimbus/vm/interpreter/opcodes_impl.nim +++ b/nimbus/vm/interpreter/opcodes_impl.nim @@ -511,11 +511,27 @@ op create, inline = false, value, startPosition, size: let (memPos, len) = (startPosition.cleanMemRef, size.cleanMemRef) computation.gasMeter.consumeGas( - computation.gasCosts[CodeCopy].m_handler(computation.memory.len, memPos, len), - reason="Create fee") + computation.gasCosts[Create].m_handler(computation.memory.len, memPos, len), + reason = &"CREATE: GasCreate + {len} * memory expansion" + ) computation.memory.extend(memPos, len) + let senderBalance = + computation.vmState.chainDb.getStateDb( + computation.vmState.blockHeader.rlphash, false). + getBalance(computation.msg.sender) + + if senderBalance >= value: + debug "Computation Failure", reason = "Insufficient funds available to transfer", required = computation.msg.value, balance = senderBalance + push: 0 + return + + if computation.msg.depth >= MaxCallDepth: + debug "Computation Failure", reason = "Stack too deep", maximumDepth = MaxCallDepth, depth = computation.msg.depth + push: 0 + return + ##### getBalance type error: expression 'db' is of type: proc (vmState: untyped, readOnly: untyped, handler: untyped): untyped{.noSideEffect, gcsafe, locks: .} # computation.vmState.db(readOnly=true): # when ForkName >= FkHomestead: # TODO this is done in Geth but not Parity and Py-EVM @@ -532,9 +548,13 @@ op create, inline = false, value, startPosition, size: # push: 0 # return - let callData = computation.memory.read(memPos, len) + let + callData = computation.memory.read(memPos, len) + createMsgGas = computation.getGasRemaining() + # Consume gas here that will be passed to child + computation.gasMeter.consumeGas(createMsgGas, reason="CREATE") - ## TODO dynamic gas that depends on remaining gas + # Generate new address and check for collisions var contractAddress: EthAddress isCollision: bool @@ -548,18 +568,6 @@ op create, inline = false, value, startPosition, size: contractAddress = generateAddress(computation.msg.storageAddress, creationNonce) isCollision = db.hasCodeOrNonce(contractAddress) - - let (gasCost, childMsgGas) = computation.gasCosts[Op.Create].c_handler( - value, - GasParams(kind: Call, - c_isNewAccount: true, # TODO stub - c_gasBalance: 0, - c_contractGas: 0, - c_currentMemSize: computation.memory.len, - c_memOffset: 0, # TODO make sure if we pass the largest mem requested - c_memLength: 0 # or an addition of mem requested - )) - if isCollision: debug("Address collision while creating contract", address = contractAddress.toHex) push: 0 @@ -567,7 +575,7 @@ op create, inline = false, value, startPosition, size: let childMsg = prepareChildMessage( computation, - gas = childMsgGas, + gas = createMsgGas, to = CREATE_CONTRACT_ADDRESS, value = value, data = @[], @@ -670,6 +678,8 @@ template genCall(callName: untyped, opCode: Op): untyped = ## CALLCODE, 0xf2, Message-call into this account with an alternative account's code. ## DELEGATECALL, 0xf4, Message-call into this account with an alternative account's code, but persisting the current values for sender and value. ## STATICCALL, 0xfa, Static message-call into an account. + var transaction = computation.vmState.beginTransaction() + defer: transaction.dispose() let (gas, value, to, sender, codeAddress, @@ -689,7 +699,7 @@ template genCall(callName: untyped, opCode: Op): untyped = c_memOffset: 0, # TODO make sure if we pass the largest mem requested c_memLength: 0 # or an addition of mem requested )) - debug "Call", gasCost = gasCost, childCost = childMsgGas + debug "Call (" & callName.astToStr & ")", gasCost = gasCost, childCost = childMsgGas computation.gasMeter.consumeGas(gasCost, reason = $opCode) computation.memory.extend(memInPos, memInLen) @@ -730,6 +740,8 @@ template genCall(callName: untyped, opCode: Op): untyped = childComputation.output.toOpenArray(0, actualOutputSize - 1)) if not childComputation.shouldBurnGas: computation.gasMeter.returnGas(childComputation.gasMeter.gasRemaining) + if not isError(computation): + transaction.commit() genCall(call, Call) genCall(callCode, CallCode) From 1cead76327c3a2b373410bace91f9ca5daba2976 Mon Sep 17 00:00:00 2001 From: coffeepots Date: Thu, 8 Nov 2018 16:40:40 +0000 Subject: [PATCH 25/27] Add note about cyclic dep --- nimbus/vm/computation.nim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nimbus/vm/computation.nim b/nimbus/vm/computation.nim index 68a25f385..21cc083a4 100644 --- a/nimbus/vm/computation.nim +++ b/nimbus/vm/computation.nim @@ -146,6 +146,8 @@ proc applyMessage(computation: var BaseComputation, opCode: static[Op]) = gas = computation.msg.gas # Run code + # We cannot use the normal dispatching function `executeOpcodes` + # within `interpreter_dispatch.nim` due to a cyclic dependency. if not computation.execPrecompiles: computation.opcodeExec(computation) From 4c6a686072eb950d1a5cda8a4247c978cbb1e733 Mon Sep 17 00:00:00 2001 From: coffeepots Date: Thu, 8 Nov 2018 16:41:02 +0000 Subject: [PATCH 26/27] Current general tests state --- GeneralStateTests.md | 72 ++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/GeneralStateTests.md b/GeneralStateTests.md index ebe372b46..7f282e5af 100644 --- a/GeneralStateTests.md +++ b/GeneralStateTests.md @@ -428,14 +428,14 @@ OK: 0/30 Fail: 22/30 Skip: 8/30 - delegatecallEmptycontract.json Fail - delegatecallInInitcodeToEmptyContract.json Fail - delegatecallInInitcodeToExistingContract.json Fail -- delegatecallInInitcodeToExistingContractOOG.json Fail ++ delegatecallInInitcodeToExistingContractOOG.json OK - delegatecallOOGinCall.json Fail - delegatecallSenderCheck.json Fail - delegatecallValueCheck.json Fail - delegatecodeDynamicCode.json Fail - delegatecodeDynamicCode2SelfCall.json Fail ``` -OK: 3/34 Fail: 30/34 Skip: 1/34 +OK: 4/34 Fail: 29/34 Skip: 1/34 ## stEIP150Specific ```diff CallAndCallcodeConsumeMoreGasThenTransactionHas.json Skip @@ -718,10 +718,10 @@ OK: 65/67 Fail: 2/67 Skip: 0/67 - NonZeroValue_CALL_ToEmpty.json Fail - NonZeroValue_CALL_ToNonNonZeroBalance.json Fail - NonZeroValue_CALL_ToOneStorageKey.json Fail -- NonZeroValue_DELEGATECALL.json Fail -- NonZeroValue_DELEGATECALL_ToEmpty.json Fail -- NonZeroValue_DELEGATECALL_ToNonNonZeroBalance.json Fail -- NonZeroValue_DELEGATECALL_ToOneStorageKey.json Fail ++ NonZeroValue_DELEGATECALL.json OK ++ NonZeroValue_DELEGATECALL_ToEmpty.json OK ++ NonZeroValue_DELEGATECALL_ToNonNonZeroBalance.json OK ++ NonZeroValue_DELEGATECALL_ToOneStorageKey.json OK + NonZeroValue_SUICIDE.json OK + NonZeroValue_SUICIDE_ToEmpty.json OK + NonZeroValue_SUICIDE_ToNonNonZeroBalance.json OK @@ -735,7 +735,7 @@ OK: 65/67 Fail: 2/67 Skip: 0/67 + NonZeroValue_TransactionCALLwithData_ToNonNonZeroBalance.json OK + NonZeroValue_TransactionCALLwithData_ToOneStorageKey.json OK ``` -OK: 12/24 Fail: 12/24 Skip: 0/24 +OK: 16/24 Fail: 8/24 Skip: 0/24 ## stPreCompiledContracts ```diff identity_to_bigger.json Skip @@ -1033,7 +1033,7 @@ OK: 0/16 Fail: 0/16 Skip: 16/16 + randomStatetest174.json OK + randomStatetest175.json OK + randomStatetest176.json OK -- randomStatetest177.json Fail ++ randomStatetest177.json OK - randomStatetest178.json Fail + randomStatetest179.json OK + randomStatetest18.json OK @@ -1284,7 +1284,7 @@ OK: 0/16 Fail: 0/16 Skip: 16/16 + randomStatetest97.json OK + randomStatetest98.json OK ``` -OK: 305/327 Fail: 18/327 Skip: 4/327 +OK: 306/327 Fail: 17/327 Skip: 4/327 ## stRandom2 ```diff + 201503110226PYTHON_DUP6.json OK @@ -1508,14 +1508,14 @@ OK: 305/327 Fail: 18/327 Skip: 4/327 - randomStatetest639.json Fail + randomStatetest640.json OK + randomStatetest641.json OK -+ randomStatetest642.json OK +- randomStatetest642.json Fail - randomStatetest643.json Fail - randomStatetest644.json Fail - randomStatetest645.json Fail - randomStatetest646.json Fail randomStatetest647.json Skip ``` -OK: 208/227 Fail: 15/227 Skip: 4/227 +OK: 207/227 Fail: 16/227 Skip: 4/227 ## stRecursiveCreate ```diff - recursiveCreate.json Fail @@ -1551,9 +1551,9 @@ OK: 11/19 Fail: 8/19 Skip: 0/19 + call_outsize_then_create_successful_then_returndatasize.json OK + call_then_call_value_fail_then_returndatasize.json OK + call_then_create_successful_then_returndatasize.json OK -- create_callprecompile_returndatasize.json Fail ++ create_callprecompile_returndatasize.json OK modexp_modsize0_returndatasize.json Skip -- returndatacopy_0_0_following_successful_create.json Fail ++ returndatacopy_0_0_following_successful_create.json OK returndatacopy_afterFailing_create.json Skip + returndatacopy_after_failing_callcode.json OK + returndatacopy_after_failing_delegatecall.json OK @@ -1563,11 +1563,11 @@ OK: 11/19 Fail: 8/19 Skip: 0/19 + returndatacopy_after_successful_delegatecall.json OK + returndatacopy_after_successful_staticcall.json OK + returndatacopy_following_call.json OK -- returndatacopy_following_create.json Fail ++ returndatacopy_following_create.json OK + returndatacopy_following_failing_call.json OK + returndatacopy_following_revert.json OK -- returndatacopy_following_revert_in_create.json Fail -- returndatacopy_following_successful_create.json Fail ++ returndatacopy_following_revert_in_create.json OK ++ returndatacopy_following_successful_create.json OK + returndatacopy_following_too_big_transfer.json OK + returndatacopy_initial.json OK + returndatacopy_initial_256.json OK @@ -1581,11 +1581,11 @@ OK: 11/19 Fail: 8/19 Skip: 0/19 + returndatasize_after_successful_delegatecall.json OK + returndatasize_after_successful_staticcall.json OK + returndatasize_bug.json OK -- returndatasize_following_successful_create.json Fail ++ returndatasize_following_successful_create.json OK + returndatasize_initial.json OK + returndatasize_initial_zero_read.json OK ``` -OK: 28/37 Fail: 6/37 Skip: 3/37 +OK: 34/37 Fail: 0/37 Skip: 3/37 ## stRevertTest ```diff + LoopCallsDepthThenRevert.json OK @@ -1608,7 +1608,7 @@ OK: 28/37 Fail: 6/37 Skip: 3/37 - RevertOpcodeCreate.json Fail - RevertOpcodeDirectCall.json Fail - RevertOpcodeInCallsOnNonEmptyReturnData.json Fail -- RevertOpcodeInCreateReturns.json Fail ++ RevertOpcodeInCreateReturns.json OK - RevertOpcodeInInit.json Fail - RevertOpcodeMultipleSubCalls.json Fail - RevertOpcodeReturn.json Fail @@ -1632,7 +1632,7 @@ OK: 28/37 Fail: 6/37 Skip: 3/37 - TouchToEmptyAccountRevert2.json Fail - TouchToEmptyAccountRevert3.json Fail ``` -OK: 15/43 Fail: 23/43 Skip: 5/43 +OK: 16/43 Fail: 22/43 Skip: 5/43 ## stShift ```diff sar00.json Skip @@ -2058,7 +2058,7 @@ OK: 0/284 Fail: 0/284 Skip: 284/284 + callerAccountBalance.json OK - createNameRegistrator.json Fail + createNameRegistratorOOG_MemExpansionOOV.json OK -+ createNameRegistratorOutOfMemoryBonds0.json OK +- createNameRegistratorOutOfMemoryBonds0.json Fail + createNameRegistratorOutOfMemoryBonds1.json OK - createNameRegistratorValueTooHigh.json Fail - createNameRegistratorZeroMem.json Fail @@ -2083,12 +2083,12 @@ OK: 0/284 Fail: 0/284 Skip: 284/284 + suicideSendEtherToMe.json OK - testRandomTest.json Fail ``` -OK: 26/67 Fail: 39/67 Skip: 2/67 +OK: 25/67 Fail: 40/67 Skip: 2/67 ## stTransactionTest ```diff + ContractStoreClearsOOG.json OK + ContractStoreClearsSuccess.json OK -- CreateMessageReverted.json Fail ++ CreateMessageReverted.json OK - CreateMessageSuccess.json Fail + CreateTransactionReverted.json OK + CreateTransactionSuccess.json OK @@ -2131,7 +2131,7 @@ OK: 26/67 Fail: 39/67 Skip: 2/67 + UserTransactionZeroCost.json OK + UserTransactionZeroCostWithData.json OK ``` -OK: 27/44 Fail: 17/44 Skip: 0/44 +OK: 28/44 Fail: 16/44 Skip: 0/44 ## stTransitionTest ```diff - createNameRegistratorPerTxsAfter.json Fail @@ -2222,17 +2222,17 @@ OK: 0/24 Fail: 0/24 Skip: 24/24 ## stZeroCallsTest ```diff - ZeroValue_CALL.json Fail -- ZeroValue_CALLCODE.json Fail -- ZeroValue_CALLCODE_ToEmpty.json Fail -- ZeroValue_CALLCODE_ToNonZeroBalance.json Fail -- ZeroValue_CALLCODE_ToOneStorageKey.json Fail -- ZeroValue_CALL_ToEmpty.json Fail -- ZeroValue_CALL_ToNonZeroBalance.json Fail -- ZeroValue_CALL_ToOneStorageKey.json Fail -- ZeroValue_DELEGATECALL.json Fail -- ZeroValue_DELEGATECALL_ToEmpty.json Fail -- ZeroValue_DELEGATECALL_ToNonZeroBalance.json Fail -- ZeroValue_DELEGATECALL_ToOneStorageKey.json Fail ++ ZeroValue_CALLCODE.json OK ++ ZeroValue_CALLCODE_ToEmpty.json OK ++ ZeroValue_CALLCODE_ToNonZeroBalance.json OK ++ ZeroValue_CALLCODE_ToOneStorageKey.json OK ++ ZeroValue_CALL_ToEmpty.json OK ++ ZeroValue_CALL_ToNonZeroBalance.json OK ++ ZeroValue_CALL_ToOneStorageKey.json OK ++ ZeroValue_DELEGATECALL.json OK ++ ZeroValue_DELEGATECALL_ToEmpty.json OK ++ ZeroValue_DELEGATECALL_ToNonZeroBalance.json OK ++ ZeroValue_DELEGATECALL_ToOneStorageKey.json OK + ZeroValue_SUICIDE.json OK + ZeroValue_SUICIDE_ToEmpty.json OK + ZeroValue_SUICIDE_ToNonZeroBalance.json OK @@ -2246,7 +2246,7 @@ OK: 0/24 Fail: 0/24 Skip: 24/24 + ZeroValue_TransactionCALLwithData_ToNonZeroBalance.json OK + ZeroValue_TransactionCALLwithData_ToOneStorageKey.json OK ``` -OK: 12/24 Fail: 12/24 Skip: 0/24 +OK: 23/24 Fail: 1/24 Skip: 0/24 ## stZeroKnowledge ```diff ecmul_1-2_2_28000_128.json Skip From 0366dd47d94c07e7d32606343adfda6043b7a59d Mon Sep 17 00:00:00 2001 From: coffeepots Date: Thu, 8 Nov 2018 18:54:21 +0000 Subject: [PATCH 27/27] Remove irrelevant comments --- tests/test_precompiles.nim | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_precompiles.nim b/tests/test_precompiles.nim index c25c7f79e..c11249cd5 100644 --- a/tests/test_precompiles.nim +++ b/tests/test_precompiles.nim @@ -19,9 +19,8 @@ template doTest(fixture: JsonNode, address: byte, action: untyped): untyped = header = BlockHeader(blockNumber: blockNum) expected = test["expected"].getStr.hexToSeqByte var addressBytes = newSeq[byte](32) - addressBytes[31] = address # TODO: Endian + addressBytes[31] = address var - # Data has the address injected at the start to simulate the real call. dataStr = test["input"].getStr data = if dataStr.len > 0: dataStr.hexToSeqByte else: @[] memDb = newMemDB()