102 lines
2.9 KiB
Nim
102 lines
2.9 KiB
Nim
# Nimbus
|
|
# Copyright (c) 2022-2024 Status Research & Development GmbH
|
|
# Licensed under either of
|
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
|
# http://www.apache.org/licenses/LICENSE-2.0)
|
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
|
# http://opensource.org/licenses/MIT)
|
|
# at your option. This file may not be copied, modified, or distributed except
|
|
# according to those terms.
|
|
|
|
import
|
|
../../nimbus/constants,
|
|
../../nimbus/utils/ec_recover,
|
|
../../nimbus/core/tx_pool/tx_item,
|
|
eth/[common, common/transaction, keys],
|
|
results,
|
|
stint
|
|
|
|
const
|
|
# example from clique, signer: 658bdf435d810c91414ec09147daa6db62406379
|
|
prvKey = "9c647b8b7c4e7c3490668fb6c11473619db80c93704c70893d3813af4090c39c"
|
|
|
|
proc signature(tx: Transaction; key: PrivateKey): (uint64,UInt256,UInt256) =
|
|
let
|
|
hashData = tx.txHashNoSignature.data
|
|
signature = key.sign(SkMessage(hashData)).toRaw
|
|
v = signature[64].uint64
|
|
|
|
result[1] = UInt256.fromBytesBE(signature[0..31])
|
|
result[2] = UInt256.fromBytesBE(signature[32..63])
|
|
|
|
if tx.txType == TxLegacy:
|
|
if tx.V >= EIP155_CHAIN_ID_OFFSET:
|
|
# just a guess which does not always work .. see `txModPair()`
|
|
# see https://eips.ethereum.org/EIPS/eip-155
|
|
result[0] = (tx.V and not 1'u64) or (not v and 1'u64)
|
|
else:
|
|
result[0] = 27 + v
|
|
else:
|
|
# currently unsupported, will skip this one .. see `txModPair()`
|
|
result[0] = 0'u64
|
|
|
|
|
|
proc sign(tx: Transaction; key: PrivateKey): Transaction =
|
|
let (V,R,S) = tx.signature(key)
|
|
result = tx
|
|
result.V = V
|
|
result.R = R
|
|
result.S = S
|
|
|
|
|
|
proc sign(header: BlockHeader; key: PrivateKey): BlockHeader =
|
|
let
|
|
hashData = header.blockHash.data
|
|
signature = key.sign(SkMessage(hashData)).toRaw
|
|
result = header
|
|
result.extraData.add signature
|
|
|
|
# ------------
|
|
|
|
let
|
|
prvTestKey* = PrivateKey.fromHex(prvKey).value
|
|
pubTestKey* = prvTestKey.toPublicKey
|
|
testAddress* = pubTestKey.toCanonicalAddress
|
|
|
|
proc txModPair*(item: TxItemRef; nonce: int; priceBump: int):
|
|
(TxItemRef,Transaction,Transaction) =
|
|
## Produce pair of modified txs, might fail => so try another one
|
|
var tx0 = item.tx
|
|
tx0.nonce = nonce.AccountNonce
|
|
|
|
var tx1 = tx0
|
|
tx1.gasPrice = (tx0.gasPrice * (100 + priceBump).GasInt + 99.GasInt) div 100
|
|
|
|
let
|
|
tx0Signed = tx0.sign(prvTestKey)
|
|
tx1Signed = tx1.sign(prvTestKey)
|
|
block:
|
|
let rc = tx0Signed.ecRecover
|
|
if rc.isErr or rc.value != testAddress:
|
|
return
|
|
block:
|
|
let rc = tx1Signed.ecRecover
|
|
if rc.isErr or rc.value != testAddress:
|
|
return
|
|
(item,tx0Signed,tx1Signed)
|
|
|
|
proc testKeySign*(header: BlockHeader): BlockHeader =
|
|
## Sign the header and embed the signature in extra data
|
|
header.sign(prvTestKey)
|
|
|
|
proc signerFunc*(signer: EthAddress, msg: openArray[byte]):
|
|
Result[array[RawSignatureSize, byte], cstring] {.gcsafe.} =
|
|
doAssert(signer == testAddress)
|
|
let
|
|
data = keccakHash(msg)
|
|
rawSign = sign(prvTestKey, SkMessage(data.data)).toRaw
|
|
|
|
ok(rawSign)
|
|
|
|
# End
|