mirror of
https://github.com/logos-storage/nim-nitro.git
synced 2026-01-04 06:33:12 +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 "nim >= 1.2.6 & < 2.0.0"
|
||||||
requires "nimcrypto >= 0.5.4 & < 0.6.0"
|
requires "nimcrypto >= 0.5.4 & < 0.6.0"
|
||||||
|
requires "secp256k1"
|
||||||
requires "stint"
|
requires "stint"
|
||||||
requires "stew"
|
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/testChannel
|
||||||
import ./nitro/testOutcome
|
import ./nitro/testOutcome
|
||||||
import ./nitro/testState
|
import ./nitro/testState
|
||||||
|
import ./nitro/testSignature
|
||||||
|
|
||||||
{.warning[UnusedImport]: off.}
|
{.warning[UnusedImport]: off.}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user