mirror of
https://github.com/logos-storage/nim-nitro.git
synced 2026-01-07 16:13:09 +00:00
Wallet keeps track of nonces
This commit is contained in:
parent
04beab5b91
commit
76cc0a9bcc
@ -1,3 +1,4 @@
|
|||||||
|
import std/hashes
|
||||||
import pkg/questionable
|
import pkg/questionable
|
||||||
import pkg/questionable/results
|
import pkg/questionable/results
|
||||||
import pkg/stew/byteutils
|
import pkg/stew/byteutils
|
||||||
@ -19,3 +20,4 @@ func parse*(_: type EthAddress, hex: string): ?EthAddress =
|
|||||||
EthAddress(array[20, byte].fromHex(hex)).catch.option
|
EthAddress(array[20, byte].fromHex(hex)).catch.option
|
||||||
|
|
||||||
proc `==`*(a, b: EthAddress): bool {.borrow.}
|
proc `==`*(a, b: EthAddress): bool {.borrow.}
|
||||||
|
proc `hash`*(a: EthAddress): Hash {.borrow.}
|
||||||
|
|||||||
34
nitro/wallet/nonces.nim
Normal file
34
nitro/wallet/nonces.nim
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import std/tables
|
||||||
|
import std/sets
|
||||||
|
import std/hashes
|
||||||
|
import ../basics
|
||||||
|
|
||||||
|
push: {.upraises: [].}
|
||||||
|
|
||||||
|
type
|
||||||
|
Nonces* = object
|
||||||
|
next: Table[NonceKey, UInt48]
|
||||||
|
NonceKey = object
|
||||||
|
chainId: UInt256
|
||||||
|
participants: HashSet[EthAddress]
|
||||||
|
|
||||||
|
func hash(key: NonceKey): Hash =
|
||||||
|
var h: Hash
|
||||||
|
h = h !& key.chainId.hash
|
||||||
|
h = h !& key.participants.hash
|
||||||
|
!$h
|
||||||
|
|
||||||
|
func key(chainId: UInt256, participants: openArray[EthAddress]): NonceKey =
|
||||||
|
NonceKey(chainId: chainId, participants: participants.toHashSet)
|
||||||
|
|
||||||
|
func getNonce*(nonces: var Nonces,
|
||||||
|
chainId: UInt256,
|
||||||
|
participants: varargs[EthAddress]): UInt48 =
|
||||||
|
nonces.next.?[key(chainId, participants)] |? 0
|
||||||
|
|
||||||
|
func incNonce*(nonces: var Nonces,
|
||||||
|
oldNonce: UInt48,
|
||||||
|
chainId: UInt256,
|
||||||
|
participants: varargs[EthAddress]) =
|
||||||
|
let next = max(oldNonce, nonces.getNonce(chainId, participants)) + 1
|
||||||
|
nonces.next[key(chainId, participants)] = next
|
||||||
@ -5,6 +5,7 @@ import ../protocol
|
|||||||
import ./signedstate
|
import ./signedstate
|
||||||
import ./ledger
|
import ./ledger
|
||||||
import ./balances
|
import ./balances
|
||||||
|
import ./nonces
|
||||||
|
|
||||||
push: {.upraises:[].}
|
push: {.upraises:[].}
|
||||||
|
|
||||||
@ -17,6 +18,7 @@ type
|
|||||||
Wallet* = object
|
Wallet* = object
|
||||||
key: EthPrivateKey
|
key: EthPrivateKey
|
||||||
channels: Table[ChannelId, SignedState]
|
channels: Table[ChannelId, SignedState]
|
||||||
|
nonces: Nonces
|
||||||
ChannelId* = Destination
|
ChannelId* = Destination
|
||||||
Payment* = tuple
|
Payment* = tuple
|
||||||
destination: Destination
|
destination: Destination
|
||||||
@ -39,11 +41,16 @@ func sign(wallet: Wallet, state: SignedState): SignedState =
|
|||||||
signed.signatures &= wallet.key.sign(state.state)
|
signed.signatures &= wallet.key.sign(state.state)
|
||||||
signed
|
signed
|
||||||
|
|
||||||
|
func incNonce(wallet: var Wallet, state: SignedState) =
|
||||||
|
let channel = state.state.channel
|
||||||
|
wallet.nonces.incNonce(channel.nonce, channel.chainId, channel.participants)
|
||||||
|
|
||||||
func createChannel(wallet: var Wallet, state: SignedState): ?!ChannelId =
|
func createChannel(wallet: var Wallet, state: SignedState): ?!ChannelId =
|
||||||
let id = getChannelId(state.state.channel)
|
let id = getChannelId(state.state.channel)
|
||||||
if wallet.channels.contains(id):
|
if wallet.channels.contains(id):
|
||||||
return ChannelId.failure("channel with id " & $id & " already exists")
|
return ChannelId.failure("channel with id " & $id & " already exists")
|
||||||
wallet.channels[id] = wallet.sign(state)
|
wallet.channels[id] = wallet.sign(state)
|
||||||
|
wallet.incNonce(state)
|
||||||
ok id
|
ok id
|
||||||
|
|
||||||
func updateChannel(wallet: var Wallet, state: SignedState) =
|
func updateChannel(wallet: var Wallet, state: SignedState) =
|
||||||
@ -60,6 +67,14 @@ func openLedgerChannel*(wallet: var Wallet,
|
|||||||
let state = startLedger(wallet.address, hub, chainId, nonce, asset, amount)
|
let state = startLedger(wallet.address, hub, chainId, nonce, asset, amount)
|
||||||
wallet.createChannel(state)
|
wallet.createChannel(state)
|
||||||
|
|
||||||
|
func openLedgerChannel*(wallet: var Wallet,
|
||||||
|
hub: EthAddress,
|
||||||
|
chainId: UInt256,
|
||||||
|
asset: EthAddress,
|
||||||
|
amount: UInt256): ?!ChannelId =
|
||||||
|
let nonce = wallet.nonces.getNonce(chainId, wallet.address, hub)
|
||||||
|
openLedgerChannel(wallet, hub, chainId, nonce, asset, amount)
|
||||||
|
|
||||||
func acceptChannel*(wallet: var Wallet, signed: SignedState): ?!ChannelId =
|
func acceptChannel*(wallet: var Wallet, signed: SignedState): ?!ChannelId =
|
||||||
if not signed.hasParticipant(wallet.address):
|
if not signed.hasParticipant(wallet.address):
|
||||||
return ChannelId.failure "wallet owner is not a participant"
|
return ChannelId.failure "wallet owner is not a participant"
|
||||||
|
|||||||
@ -31,6 +31,12 @@ suite "wallet: opening ledger channel":
|
|||||||
check definition.nonce == nonce
|
check definition.nonce == nonce
|
||||||
check definition.participants == @[wallet.address, hub]
|
check definition.participants == @[wallet.address, hub]
|
||||||
|
|
||||||
|
test "uses consecutive nonces when none is provided":
|
||||||
|
channel = wallet.openLedgerChannel(hub, chainId, asset, amount).get
|
||||||
|
check wallet.state(channel).get.channel.nonce == nonce + 1
|
||||||
|
channel = wallet.openLedgerChannel(hub, chainId, asset, amount).get
|
||||||
|
check wallet.state(channel).get.channel.nonce == nonce + 2
|
||||||
|
|
||||||
test "provides correct outcome":
|
test "provides correct outcome":
|
||||||
let outcome = wallet.state(channel).get.outcome
|
let outcome = wallet.state(channel).get.outcome
|
||||||
check outcome == Outcome.init(asset, {wallet.destination: amount})
|
check outcome == Outcome.init(asset, {wallet.destination: amount})
|
||||||
|
|||||||
37
tests/nitro/wallet/testNonces.nim
Normal file
37
tests/nitro/wallet/testNonces.nim
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import ../basics
|
||||||
|
import pkg/nitro/wallet/nonces
|
||||||
|
|
||||||
|
suite "nonces":
|
||||||
|
|
||||||
|
let chainId = UInt256.example
|
||||||
|
let participants = seq[EthAddress].example
|
||||||
|
|
||||||
|
var nonces: Nonces
|
||||||
|
|
||||||
|
setup:
|
||||||
|
nonces = Nonces()
|
||||||
|
|
||||||
|
test "nonces start at 0":
|
||||||
|
check nonces.getNonce(chainId, participants) == 0
|
||||||
|
|
||||||
|
test "nonces increase by 1":
|
||||||
|
nonces.incNonce(0, chainId, participants)
|
||||||
|
check nonces.getNonce(chainId, participants) == 1
|
||||||
|
nonces.incNonce(1, chainId, participants)
|
||||||
|
check nonces.getNonce(chainId, participants) == 2
|
||||||
|
|
||||||
|
test "nonces do not decrease":
|
||||||
|
nonces.incNonce(100, chainId, participants)
|
||||||
|
check nonces.getNonce(chainId, participants) == 101
|
||||||
|
nonces.incNonce(0, chainId, participants)
|
||||||
|
check nonces.getNonce(chainId, participants) == 102
|
||||||
|
|
||||||
|
test "nonces are different when participants differ":
|
||||||
|
let otherParticipants = seq[EthAddress].example
|
||||||
|
nonces.incNonce(0, chainId, participants)
|
||||||
|
check nonces.getNonce(chainId, otherParticipants) == 0
|
||||||
|
|
||||||
|
test "nonces are different when chain ids differ":
|
||||||
|
let otherChainId = UInt256.example
|
||||||
|
nonces.incNonce(0, chainId, participants)
|
||||||
|
check nonces.getNonce(otherChainId, participants) == 0
|
||||||
@ -3,6 +3,7 @@ import ./nitro/protocol/testChannel
|
|||||||
import ./nitro/protocol/testOutcome
|
import ./nitro/protocol/testOutcome
|
||||||
import ./nitro/protocol/testState
|
import ./nitro/protocol/testState
|
||||||
import ./nitro/protocol/testSignature
|
import ./nitro/protocol/testSignature
|
||||||
|
import ./nitro/wallet/testNonces
|
||||||
import ./nitro/testWallet
|
import ./nitro/testWallet
|
||||||
import ./nitro/testJson
|
import ./nitro/testJson
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user