mirror of
https://github.com/logos-storage/nim-nitro.git
synced 2026-01-02 13:43:06 +00:00
Sign Nitro states
This commit is contained in:
parent
34072f4749
commit
8ddd78ed68
@ -5,5 +5,6 @@ description = "Nitro state channels"
|
||||
|
||||
requires "nim >= 1.2.6 & < 2.0.0"
|
||||
requires "nimcrypto >= 0.5.4 & < 0.6.0"
|
||||
requires "secp256k1"
|
||||
requires "stint"
|
||||
requires "stew"
|
||||
|
||||
48
nitro/signature.nim
Normal file
48
nitro/signature.nim
Normal file
@ -0,0 +1,48 @@
|
||||
import pkg/nimcrypto
|
||||
import pkg/secp256k1
|
||||
import pkg/stew/byteutils
|
||||
import ./state
|
||||
|
||||
export toPublicKey
|
||||
|
||||
type
|
||||
PrivateKey* = SkSecretKey
|
||||
PublicKey* = SkPublicKey
|
||||
Signature* = SkRecoverableSignature
|
||||
|
||||
proc rng(data: var openArray[byte]): bool =
|
||||
randomBytes(data) == data.len
|
||||
|
||||
proc random*(_: type PrivateKey): PrivateKey =
|
||||
PrivateKey.random(rng).get()
|
||||
|
||||
proc `$`*(key: PrivateKey): string =
|
||||
key.toHex()
|
||||
|
||||
proc parse*(_: type PrivateKey, s: string): PrivateKey =
|
||||
SkSecretKey.fromHex(s).tryGet()
|
||||
|
||||
proc sign(key: PrivateKey, data: openArray[byte]): Signature =
|
||||
let hash = keccak256.digest(data).data
|
||||
key.signRecoverable(SkMessage(hash))
|
||||
|
||||
proc signMessage(key: PrivateKey, message: openArray[byte]): Signature =
|
||||
# https://eips.ethereum.org/EIPS/eip-191
|
||||
var data: seq[byte]
|
||||
data.add("\x19Ethereum Signed Message:\n".toBytes)
|
||||
data.add(($message.len).toBytes)
|
||||
data.add(message)
|
||||
key.sign(data)
|
||||
|
||||
proc sign*(key: PrivateKey, state: State): Signature =
|
||||
key.signMessage(hashState(state))
|
||||
|
||||
proc `$`*(signature: Signature): string =
|
||||
var bytes = signature.toRaw()
|
||||
bytes[64] += 27
|
||||
bytes.toHex()
|
||||
|
||||
proc parse*(_: type Signature, s: string): Signature =
|
||||
var bytes = array[65, byte].fromHex(s)
|
||||
bytes[64] -= 27
|
||||
SkRecoverableSignature.fromRaw(bytes).tryGet()
|
||||
47
tests/nitro/testSignature.nim
Normal file
47
tests/nitro/testSignature.nim
Normal file
@ -0,0 +1,47 @@
|
||||
import std/unittest
|
||||
import pkg/nimcrypto
|
||||
import pkg/secp256k1
|
||||
import pkg/stew/byteutils
|
||||
import pkg/nitro/state
|
||||
import pkg/nitro/signature
|
||||
import ./examples
|
||||
|
||||
suite "signature":
|
||||
|
||||
test "signs state hashes":
|
||||
let state = State.example
|
||||
let privateKey = PrivateKey.random()
|
||||
let publicKey = privateKey.toPublicKey()
|
||||
|
||||
let signature = privateKey.sign(state)
|
||||
|
||||
let message = hashState(state)
|
||||
let data = "\x19Ethereum Signed Message:\n32".toBytes & @message
|
||||
let hash = keccak256.digest(data).data
|
||||
check recover(signature, SkMessage(hash)).tryGet() == publicKey
|
||||
|
||||
test "produces the same signatures as the javascript implementation":
|
||||
let state =State(
|
||||
channel: Channel(
|
||||
chainId: 0x1.u256,
|
||||
nonce: 1,
|
||||
participants: @[
|
||||
EthAddress.fromHex("0x8a64E10FF40Bc9C90EA5750313dB5e036495c10E")
|
||||
]
|
||||
),
|
||||
outcome: Outcome(@[]),
|
||||
turnNum: 1,
|
||||
isFinal: false,
|
||||
appData: @[0'u8],
|
||||
appDefinition: EthAddress.default,
|
||||
challengeDuration: 5
|
||||
)
|
||||
let seckey = PrivateKey.parse(
|
||||
"41b0f5f91967dded8af487277874f95116094cc6004ac2b2169b5b6a87608f3e"
|
||||
)
|
||||
let expected = Signature.parse(
|
||||
"9b966cf0065586d59c8b9eb475ac763c96ad8316b81061238f32968a631f9e21" &
|
||||
"251363c193c78c89b3eb2fec23f0ea5c3c72acff7d1f27430cfb84b9da9831fb" &
|
||||
"1c"
|
||||
)
|
||||
check seckey.sign(state) == expected
|
||||
@ -2,5 +2,6 @@ import ./nitro/testAbi
|
||||
import ./nitro/testChannel
|
||||
import ./nitro/testOutcome
|
||||
import ./nitro/testState
|
||||
import ./nitro/testSignature
|
||||
|
||||
{.warning[UnusedImport]: off.}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user