diff --git a/nitro/wallet/wallet.nim b/nitro/wallet/wallet.nim index ca84f1c..6707e4a 100644 --- a/nitro/wallet/wallet.nim +++ b/nitro/wallet/wallet.nim @@ -36,11 +36,12 @@ func sign(wallet: Wallet, state: SignedState): SignedState = signed.signatures &= wallet.key.sign(state.state) signed -func createChannel(wallet: var Wallet, state: SignedState): ChannelId = - let signed = wallet.sign(state) - let id = getChannelId(signed.state.channel) - wallet.channels[id] = signed - id +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) + ok id func updateChannel(wallet: var Wallet, state: SignedState) = let signed = wallet.sign(state) @@ -52,7 +53,7 @@ func openLedgerChannel*(wallet: var Wallet, chainId: UInt256, nonce: UInt48, asset: EthAddress, - amount: UInt256): ChannelId = + amount: UInt256): ?!ChannelId = let state = startLedger(wallet.address, hub, chainId, nonce, asset, amount) wallet.createChannel(state) @@ -63,7 +64,7 @@ func acceptChannel*(wallet: var Wallet, signed: SignedState): ?!ChannelId = if not verifySignatures(signed): return ChannelId.failure "incorrect signatures" - wallet.createChannel(signed).success + wallet.createChannel(signed) func latestSignedState*(wallet: Wallet, channel: ChannelId): ?SignedState = wallet.channels?[channel] diff --git a/tests/nitro/testWallet.nim b/tests/nitro/testWallet.nim index 64852fd..84965ef 100644 --- a/tests/nitro/testWallet.nim +++ b/tests/nitro/testWallet.nim @@ -21,7 +21,7 @@ suite "wallet: opening ledger channel": setup: wallet = Wallet.init(key) - channel = wallet.openLedgerChannel(hub, chainId, nonce, asset, amount) + channel = wallet.openLedgerChannel(hub, chainId, nonce, asset, amount).get test "sets correct channel definition": let definition = wallet.state(channel).get.channel @@ -42,6 +42,9 @@ suite "wallet: opening ledger channel": check wallet.state(channel).get.appDefinition == EthAddress.zero check wallet.state(channel).get.appData.len == 0 + test "does not allow opening a channel that already exists": + check wallet.openLedgerChannel(hub, chainId, nonce, asset, amount).isErr + suite "wallet: accepting incoming channel": let key = PrivateKey.random() @@ -71,6 +74,10 @@ suite "wallet: accepting incoming channel": signed.signatures = @[key.sign(State.example)] check wallet.acceptChannel(signed).isErr + test "fails when channel with this id already exists": + check wallet.acceptChannel(signed).isOk + check wallet.acceptChannel(signed).isErr + suite "wallet: making payments": let key = PrivateKey.random() @@ -85,7 +92,7 @@ suite "wallet: making payments": test "paying updates the channel state": wallet = Wallet.init(key) let me = wallet.address - channel = wallet.openLedgerChannel(hub, chainId, nonce, asset, 100.u256) + channel = wallet.openLedgerChannel(hub, chainId, nonce, asset, 100.u256).get check wallet.pay(channel, asset, hub, 1.u256).isOk check wallet.balance(channel, asset, me) == 99.u256 @@ -97,14 +104,14 @@ suite "wallet: making payments": test "paying updates signatures": wallet = Wallet.init(key) - channel = wallet.openLedgerChannel(hub, chainId, nonce, asset, 100.u256) + channel = wallet.openLedgerChannel(hub, chainId, nonce, asset, 100.u256).get check wallet.pay(channel, asset, hub, 1.u256).isOk let expectedSignature = key.sign(wallet.state(channel).get) check wallet.signature(channel, wallet.address) == expectedSignature.some test "pay returns the updated signed state": wallet = Wallet.init(key) - channel = wallet.openLedgerChannel(hub, chainId, nonce, asset, 42.u256) + channel = wallet.openLedgerChannel(hub, chainId, nonce, asset, 42.u256).get let updated = wallet.pay(channel, asset, hub, 1.u256).option check updated?.state == wallet.state(channel) check updated?.signatures == wallet.signatures(channel) @@ -130,7 +137,7 @@ suite "wallet: making payments": test "payment fails when payer has insufficient funds": wallet = Wallet.init(key) - channel = wallet.openLedgerChannel(hub, chainId, nonce, asset, 1.u256) + channel = wallet.openLedgerChannel(hub, chainId, nonce, asset, 1.u256).get check wallet.pay(channel, asset, hub, 1.u256).isOk check wallet.pay(channel, asset, hub, 1.u256).isErr @@ -148,7 +155,7 @@ suite "wallet: accepting payments": payer = Wallet.init(payerKey) receiver = Wallet.init(receiverKey) channel = payer.openLedgerChannel( - receiver.address, chainId, nonce, asset, 100.u256) + receiver.address, chainId, nonce, asset, 100.u256).get let update = payer.latestSignedState(channel).get discard receiver.acceptChannel(update) @@ -184,12 +191,12 @@ suite "wallet: accepting payments": test "does not accept a payment for an unknown channel": let newChannel = payer.openLedgerChannel( - receiver.address, chainId, nonce + 1, asset, 100.u256) + receiver.address, chainId, nonce + 1, asset, 100.u256).get let payment = payer.pay(newChannel, asset, receiver.address, 10.u256).get check receiver.acceptPayment(newChannel, asset, payer.address, payment).isErr test "does not accept a payment for a different channel": let newChannel = payer.openLedgerChannel( - receiver.address, chainId, nonce + 1, asset, 100.u256) + receiver.address, chainId, nonce + 1, asset, 100.u256).get let payment = payer.pay(newChannel, asset, receiver.address, 10.u256).get check receiver.acceptPayment(channel, asset, payer.address, payment).isErr