From 62968bf733bd188da10dda504380ea9efe4b9455 Mon Sep 17 00:00:00 2001 From: coffeepots Date: Tue, 2 Oct 2018 15:46:39 +0100 Subject: [PATCH] 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)