mirror of
https://github.com/logos-storage/nim-nitro.git
synced 2026-01-02 13:43:06 +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/results
|
||||
import pkg/stew/byteutils
|
||||
@ -19,3 +20,4 @@ func parse*(_: type EthAddress, hex: string): ?EthAddress =
|
||||
EthAddress(array[20, byte].fromHex(hex)).catch.option
|
||||
|
||||
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 ./ledger
|
||||
import ./balances
|
||||
import ./nonces
|
||||
|
||||
push: {.upraises:[].}
|
||||
|
||||
@ -17,6 +18,7 @@ type
|
||||
Wallet* = object
|
||||
key: EthPrivateKey
|
||||
channels: Table[ChannelId, SignedState]
|
||||
nonces: Nonces
|
||||
ChannelId* = Destination
|
||||
Payment* = tuple
|
||||
destination: Destination
|
||||
@ -39,11 +41,16 @@ func sign(wallet: Wallet, state: SignedState): SignedState =
|
||||
signed.signatures &= wallet.key.sign(state.state)
|
||||
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 =
|
||||
let id = getChannelId(state.state.channel)
|
||||
if wallet.channels.contains(id):
|
||||
return ChannelId.failure("channel with id " & $id & " already exists")
|
||||
wallet.channels[id] = wallet.sign(state)
|
||||
wallet.incNonce(state)
|
||||
ok id
|
||||
|
||||
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)
|
||||
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 =
|
||||
if not signed.hasParticipant(wallet.address):
|
||||
return ChannelId.failure "wallet owner is not a participant"
|
||||
|
||||
@ -31,6 +31,12 @@ suite "wallet: opening ledger channel":
|
||||
check definition.nonce == nonce
|
||||
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":
|
||||
let outcome = wallet.state(channel).get.outcome
|
||||
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/testState
|
||||
import ./nitro/protocol/testSignature
|
||||
import ./nitro/wallet/testNonces
|
||||
import ./nitro/testWallet
|
||||
import ./nitro/testJson
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user