mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-02-03 07:45:18 +00:00
Added nim-bncurve dependency.
Added implementation of `ecAdd`, `ecMul`, `ecPairing` precompiles.
This commit is contained in:
parent
6a4cd4ec67
commit
9318ea93cf
@ -19,7 +19,8 @@ requires "nim >= 0.18.1",
|
|||||||
"asyncdispatch2",
|
"asyncdispatch2",
|
||||||
"eth_p2p",
|
"eth_p2p",
|
||||||
"eth_keyfile",
|
"eth_keyfile",
|
||||||
"eth_keys"
|
"eth_keys",
|
||||||
|
"https://github.com/status-im/nim-bncurve"
|
||||||
|
|
||||||
proc buildBinary(name: string, srcDir = ".", lang = "c") =
|
proc buildBinary(name: string, srcDir = ".", lang = "c") =
|
||||||
if not dirExists "build": mkDir "build"
|
if not dirExists "build": mkDir "build"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import
|
import
|
||||||
../vm_types, interpreter/[gas_meter, gas_costs],
|
../vm_types, interpreter/[gas_meter, gas_costs],
|
||||||
../errors, stint, eth_keys, eth_common, chronicles, tables, macros,
|
../errors, stint, eth_keys, eth_common, chronicles, tables, macros,
|
||||||
message, math, nimcrypto
|
message, math, nimcrypto, bncurve/[fields, groups]
|
||||||
|
|
||||||
type
|
type
|
||||||
PrecompileAddresses = enum
|
PrecompileAddresses = enum
|
||||||
@ -22,6 +22,29 @@ proc getSignature*(computation: BaseComputation): Signature =
|
|||||||
bytes[64..63] = computation.msg.data[96..128] # S
|
bytes[64..63] = computation.msg.data[96..128] # S
|
||||||
result = initSignature(bytes) # Can raise
|
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) =
|
proc ecRecover*(computation: var BaseComputation) =
|
||||||
computation.gasMeter.consumeGas(
|
computation.gasMeter.consumeGas(
|
||||||
GasECRecover,
|
GasECRecover,
|
||||||
@ -36,7 +59,7 @@ proc ecRecover*(computation: var BaseComputation) =
|
|||||||
|
|
||||||
if sig.recoverSignatureKey(msgHash, pubKey) != EthKeysStatus.Success:
|
if sig.recoverSignatureKey(msgHash, pubKey) != EthKeysStatus.Success:
|
||||||
raise newException(ValidationError, "Could not derive public key from computation")
|
raise newException(ValidationError, "Could not derive public key from computation")
|
||||||
|
|
||||||
computation.rawOutput = @(pubKey.toCanonicalAddress())
|
computation.rawOutput = @(pubKey.toCanonicalAddress())
|
||||||
debug "ECRecover precompile", derivedKey = pubKey.toCanonicalAddress()
|
debug "ECRecover precompile", derivedKey = pubKey.toCanonicalAddress()
|
||||||
|
|
||||||
@ -67,6 +90,85 @@ proc identity*(computation: var BaseComputation) =
|
|||||||
computation.rawOutput = computation.msg.data
|
computation.rawOutput = computation.msg.data
|
||||||
debug "Identity precompile", output = computation.rawOutput
|
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..<count:
|
||||||
|
let s = i * 192
|
||||||
|
# Loading AffinePoint[G1], bytes from [0..63]
|
||||||
|
var p1 = G1.getPoint(computation.msg.data.toOpenArray(s, s + 63))
|
||||||
|
# Loading AffinePoint[G2], bytes from [64..191]
|
||||||
|
var p2 = G2.getPoint(computation.msg.data.toOpenArray(s + 64, s + 191))
|
||||||
|
# Accumulate pairing result
|
||||||
|
acc = acc * pairing(p1, p2)
|
||||||
|
|
||||||
|
if acc == FQ12.one():
|
||||||
|
# we can discard here because we supply buffer of proper size
|
||||||
|
discard BNU256.one().toBytes(output)
|
||||||
|
|
||||||
|
# TODO: gas computation
|
||||||
|
# computation.gasMeter.consumeGas(gasFee, reason="ecPairing Precompile")
|
||||||
|
computation.rawOutput = @output
|
||||||
|
|
||||||
proc execPrecompiles*(computation: var BaseComputation): bool {.inline.} =
|
proc execPrecompiles*(computation: var BaseComputation): bool {.inline.} =
|
||||||
const
|
const
|
||||||
bRange = when system.cpuEndian == bigEndian: 0..18 else: 1..19
|
bRange = when system.cpuEndian == bigEndian: 0..18 else: 1..19
|
||||||
@ -74,7 +176,7 @@ proc execPrecompiles*(computation: var BaseComputation): bool {.inline.} =
|
|||||||
|
|
||||||
for i in bRange:
|
for i in bRange:
|
||||||
if computation.msg.codeAddress[i] != 0: return
|
if computation.msg.codeAddress[i] != 0: return
|
||||||
|
|
||||||
let lb = computation.msg.codeAddress[bOffset]
|
let lb = computation.msg.codeAddress[bOffset]
|
||||||
|
|
||||||
if lb in PrecompileAddresses.low.byte .. PrecompileAddresses.high.byte:
|
if lb in PrecompileAddresses.low.byte .. PrecompileAddresses.high.byte:
|
||||||
@ -86,5 +188,8 @@ proc execPrecompiles*(computation: var BaseComputation): bool {.inline.} =
|
|||||||
of paSha256: sha256(computation)
|
of paSha256: sha256(computation)
|
||||||
of paRipeMd160: ripeMd160(computation)
|
of paRipeMd160: ripeMd160(computation)
|
||||||
of paIdentity: identity(computation)
|
of paIdentity: identity(computation)
|
||||||
|
of paEcAdd: bn256ecAdd(computation)
|
||||||
|
of paEcMul: bn256ecMul(computation)
|
||||||
|
of paPairing: bn256ecPairing(computation)
|
||||||
else:
|
else:
|
||||||
raise newException(ValidationError, "Unknown precompile address " & $lb)
|
raise newException(ValidationError, "Unknown precompile address " & $lb)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user