Update to latest version of questionable

This commit is contained in:
Mark Spanbroek 2021-04-15 11:15:32 +02:00
parent 76cc0a9bcc
commit 85ffad6fb1
4 changed files with 43 additions and 43 deletions

View File

@ -1,11 +1,11 @@
version = "0.2.0" version = "0.3.0"
author = "Nim Nitro developers" author = "Nim Nitro developers"
license = "MIT" license = "MIT"
description = "Nitro state channels" 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 "questionable >= 0.5.0 & < 0.6.0" requires "questionable >= 0.6.2 & < 0.7.0"
requires "upraises >= 0.1.0 & < 0.2.0" requires "upraises >= 0.1.0 & < 0.2.0"
requires "secp256k1" requires "secp256k1"
requires "stint" requires "stint"

View File

@ -31,7 +31,7 @@ func move*(balances: var Balances,
amount: UInt256): ?!void = amount: UInt256): ?!void =
try: try:
if balances[source] < amount: if balances[source] < amount:
return void.failure "insufficient funds" return failure "insufficient funds"
balances[source] -= amount balances[source] -= amount
if (balances.contains(destination)): if (balances.contains(destination)):
@ -39,6 +39,6 @@ func move*(balances: var Balances,
else: else:
balances[destination] = amount balances[destination] = amount
ok() success()
except KeyError: except KeyError:
void.failure "no funds" failure "no funds"

View File

@ -48,10 +48,10 @@ func incNonce(wallet: var Wallet, state: SignedState) =
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 failure "channel with id " & $id & " already exists"
wallet.channels[id] = wallet.sign(state) wallet.channels[id] = wallet.sign(state)
wallet.incNonce(state) wallet.incNonce(state)
ok id success id
func updateChannel(wallet: var Wallet, state: SignedState) = func updateChannel(wallet: var Wallet, state: SignedState) =
let signed = wallet.sign(state) let signed = wallet.sign(state)
@ -77,10 +77,10 @@ func openLedgerChannel*(wallet: var Wallet,
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 failure "wallet owner is not a participant"
if not verifySignatures(signed): if not verifySignatures(signed):
return ChannelId.failure "incorrect signatures" return failure "incorrect signatures"
wallet.createChannel(signed) wallet.createChannel(signed)
@ -155,11 +155,11 @@ func pay*(wallet: var Wallet,
?balances.move(wallet.destination, receiver, amount) ?balances.move(wallet.destination, receiver, amount)
state.outcome.update(asset, balances) state.outcome.update(asset, balances)
wallet.updateChannel(SignedState(state: state)) wallet.updateChannel(SignedState(state: state))
ok(wallet.channels.?[channel].get) success wallet.channels.?[channel].get
else: else:
SignedState.failure "asset not found" failure "asset not found"
else: else:
SignedState.failure "channel not found" failure "channel not found"
func pay*(wallet: var Wallet, func pay*(wallet: var Wallet,
channel: ChannelId, channel: ChannelId,
@ -174,31 +174,31 @@ func acceptPayment*(wallet: var Wallet,
sender: EthAddress, sender: EthAddress,
payment: SignedState): ?!void = payment: SignedState): ?!void =
if not wallet.channels.contains(channel): if not wallet.channels.contains(channel):
return void.failure "unknown channel" return failure "unknown channel"
if not (getChannelId(payment.state.channel) == channel): if not (getChannelId(payment.state.channel) == channel):
return void.failure "payment does not match channel" return failure "payment does not match channel"
let currentBalance = wallet.balance(channel, asset) let currentBalance = wallet.balance(channel, asset)
let futureBalance = payment.state.balance(asset, wallet.destination) let futureBalance = payment.state.balance(asset, wallet.destination)
if futureBalance <= currentBalance: if futureBalance <= currentBalance:
return void.failure "payment should not decrease balance" return failure "payment should not decrease balance"
let currentTotal = wallet.total(channel, asset) let currentTotal = wallet.total(channel, asset)
let futureTotal = payment.state.total(asset) let futureTotal = payment.state.total(asset)
if futureTotal != currentTotal: if futureTotal != currentTotal:
return void.failure "total supply of asset should not change" return failure "total supply of asset should not change"
if not payment.isSignedBy(sender): if not payment.isSignedBy(sender):
return void.failure "missing signature on payment" return failure "missing signature on payment"
if updatedBalances =? payment.state.outcome.balances(asset): if updatedBalances =? payment.state.outcome.balances(asset):
var expectedState: State = wallet.channels.?[channel].?state.get var expectedState: State = wallet.channels.?[channel].?state.get
expectedState.outcome.update(asset, updatedBalances) expectedState.outcome.update(asset, updatedBalances)
if payment.state != expectedState: if payment.state != expectedState:
return void.failure "payment has unexpected changes in state" return failure "payment has unexpected changes in state"
else: else:
return void.failure "payment misses balances for asset" return failure "payment misses balances for asset"
wallet.channels[channel] = payment wallet.channels[channel] = payment
ok() success()

View File

@ -51,7 +51,7 @@ suite "wallet: opening ledger channel":
check wallet.state(channel).get.appData.len == 0 check wallet.state(channel).get.appData.len == 0
test "does not allow opening a channel that already exists": test "does not allow opening a channel that already exists":
check wallet.openLedgerChannel(hub, chainId, nonce, asset, amount).isErr check wallet.openLedgerChannel(hub, chainId, nonce, asset, amount).isFailure
suite "wallet: accepting incoming channel": suite "wallet: accepting incoming channel":
@ -76,15 +76,15 @@ suite "wallet: accepting incoming channel":
test "fails when wallet address is not a participant": test "fails when wallet address is not a participant":
let wrongParticipants = seq[EthAddress].example let wrongParticipants = seq[EthAddress].example
signed.state.channel.participants = wrongParticipants signed.state.channel.participants = wrongParticipants
check wallet.acceptChannel(signed).isErr check wallet.acceptChannel(signed).isFailure
test "fails when signatures are incorrect": test "fails when signatures are incorrect":
signed.signatures = @[key.sign(State.example)] signed.signatures = @[key.sign(State.example)]
check wallet.acceptChannel(signed).isErr check wallet.acceptChannel(signed).isFailure
test "fails when channel with this id already exists": test "fails when channel with this id already exists":
check wallet.acceptChannel(signed).isOk check wallet.acceptChannel(signed).isSuccess
check wallet.acceptChannel(signed).isErr check wallet.acceptChannel(signed).isFailure
suite "wallet: making payments": suite "wallet: making payments":
@ -101,18 +101,18 @@ suite "wallet: making payments":
wallet = Wallet.init(key) wallet = Wallet.init(key)
channel = wallet.openLedgerChannel(hub, chainId, nonce, asset, 100.u256).get channel = wallet.openLedgerChannel(hub, chainId, nonce, asset, 100.u256).get
check wallet.pay(channel, asset, hub, 1.u256).isOk check wallet.pay(channel, asset, hub, 1.u256).isSuccess
check wallet.balance(channel, asset) == 99.u256 check wallet.balance(channel, asset) == 99.u256
check wallet.balance(channel, asset, hub) == 1.u256 check wallet.balance(channel, asset, hub) == 1.u256
check wallet.pay(channel, asset, hub, 2.u256).isOk check wallet.pay(channel, asset, hub, 2.u256).isSuccess
check wallet.balance(channel, asset) == 97.u256 check wallet.balance(channel, asset) == 97.u256
check wallet.balance(channel, asset, hub) == 3.u256 check wallet.balance(channel, asset, hub) == 3.u256
test "paying updates signatures": test "paying updates signatures":
wallet = Wallet.init(key) wallet = Wallet.init(key)
channel = wallet.openLedgerChannel(hub, chainId, nonce, asset, 100.u256).get channel = wallet.openLedgerChannel(hub, chainId, nonce, asset, 100.u256).get
check wallet.pay(channel, asset, hub, 1.u256).isOk check wallet.pay(channel, asset, hub, 1.u256).isSuccess
let expectedSignature = key.sign(wallet.state(channel).get) let expectedSignature = key.sign(wallet.state(channel).get)
check wallet.signature(channel, wallet.address) == expectedSignature.some check wallet.signature(channel, wallet.address) == expectedSignature.some
@ -125,14 +125,14 @@ suite "wallet: making payments":
test "payment fails when channel not found": test "payment fails when channel not found":
wallet = Wallet.init(key) wallet = Wallet.init(key)
check wallet.pay(channel, asset, hub, 1.u256).isErr check wallet.pay(channel, asset, hub, 1.u256).isFailure
test "payment fails when asset not found": test "payment fails when asset not found":
wallet = Wallet.init(key) wallet = Wallet.init(key)
var state = State.example var state = State.example
state.channel.participants &= wallet.address state.channel.participants &= wallet.address
channel = wallet.acceptChannel(SignedState(state: state)).get channel = wallet.acceptChannel(SignedState(state: state)).get
check wallet.pay(channel, asset, hub, 1.u256).isErr check wallet.pay(channel, asset, hub, 1.u256).isFailure
test "payment fails when payer has no allocation": test "payment fails when payer has no allocation":
wallet = Wallet.init(key) wallet = Wallet.init(key)
@ -140,13 +140,13 @@ suite "wallet: making payments":
state.channel = ChannelDefinition(participants: @[wallet.address]) state.channel = ChannelDefinition(participants: @[wallet.address])
state.outcome = Outcome.init(asset, @[]) state.outcome = Outcome.init(asset, @[])
channel = wallet.acceptChannel(SignedState(state: state)).get channel = wallet.acceptChannel(SignedState(state: state)).get
check wallet.pay(channel, asset, hub, 1.u256).isErr check wallet.pay(channel, asset, hub, 1.u256).isFailure
test "payment fails when payer has insufficient funds": test "payment fails when payer has insufficient funds":
wallet = Wallet.init(key) wallet = Wallet.init(key)
channel = wallet.openLedgerChannel(hub, chainId, nonce, asset, 1.u256).get 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).isSuccess
check wallet.pay(channel, asset, hub, 1.u256).isErr check wallet.pay(channel, asset, hub, 1.u256).isFailure
suite "wallet: accepting payments": suite "wallet: accepting payments":
@ -168,15 +168,15 @@ suite "wallet: accepting payments":
test "updates channel state": test "updates channel state":
let payment = payer.pay(channel, asset, receiver.address, 42.u256).get let payment = payer.pay(channel, asset, receiver.address, 42.u256).get
check receiver.acceptPayment(channel, asset, payer.address, payment).isOk check receiver.acceptPayment(channel, asset, payer.address, payment).isSuccess
check receiver.balance(channel, asset) == 42.u256 check receiver.balance(channel, asset) == 42.u256
test "fails when receiver balance is decreased": test "fails when receiver balance is decreased":
let payment1 = payer.pay(channel, asset, receiver.address, 10.u256).get let payment1 = payer.pay(channel, asset, receiver.address, 10.u256).get
let payment2 = payer.pay(channel, asset, receiver.address, 10.u256).get let payment2 = payer.pay(channel, asset, receiver.address, 10.u256).get
check receiver.acceptPayment(channel, asset, payer.address, payment1).isOk check receiver.acceptPayment(channel, asset, payer.address, payment1).isSuccess
check receiver.acceptPayment(channel, asset, payer.address, payment2).isOk check receiver.acceptPayment(channel, asset, payer.address, payment2).isSuccess
check receiver.acceptPayment(channel, asset, payer.address, payment1).isErr check receiver.acceptPayment(channel, asset, payer.address, payment1).isFailure
check receiver.balance(channel, asset) == 20 check receiver.balance(channel, asset) == 20
test "fails when the total supply of the asset changes": test "fails when the total supply of the asset changes":
@ -184,32 +184,32 @@ suite "wallet: accepting payments":
var balances = payment.state.outcome.balances(asset).get var balances = payment.state.outcome.balances(asset).get
balances[payer.destination] += 10.u256 balances[payer.destination] += 10.u256
payment.state.outcome.update(asset, balances) payment.state.outcome.update(asset, balances)
check receiver.acceptPayment(channel, asset, payer.address, payment).isErr check receiver.acceptPayment(channel, asset, payer.address, payment).isFailure
test "fails without a signature": test "fails without a signature":
var payment = payer.pay(channel, asset, receiver.address, 10.u256).get var payment = payer.pay(channel, asset, receiver.address, 10.u256).get
payment.signatures = @[] payment.signatures = @[]
check receiver.acceptPayment(channel, asset, payer.address, payment).isErr check receiver.acceptPayment(channel, asset, payer.address, payment).isFailure
test "fails with an incorrect signature": test "fails with an incorrect signature":
var payment = payer.pay(channel, asset, receiver.address, 10.u256).get var payment = payer.pay(channel, asset, receiver.address, 10.u256).get
payment.signatures = @[Signature.example] payment.signatures = @[Signature.example]
check receiver.acceptPayment(channel, asset, payer.address, payment).isErr check receiver.acceptPayment(channel, asset, payer.address, payment).isFailure
test "fails when channel is unknown": test "fails when channel is unknown":
let newChannel = payer.openLedgerChannel( let newChannel = payer.openLedgerChannel(
receiver.address, chainId, nonce + 1, asset, 100.u256).get receiver.address, chainId, nonce + 1, asset, 100.u256).get
let payment = payer.pay(newChannel, asset, receiver.address, 10.u256).get let payment = payer.pay(newChannel, asset, receiver.address, 10.u256).get
check receiver.acceptPayment(newChannel, asset, payer.address, payment).isErr check receiver.acceptPayment(newChannel, asset, payer.address, payment).isFailure
test "fails when payment does not match channel": test "fails when payment does not match channel":
let newChannel = payer.openLedgerChannel( let newChannel = payer.openLedgerChannel(
receiver.address, chainId, nonce + 1, asset, 100.u256).get receiver.address, chainId, nonce + 1, asset, 100.u256).get
let payment = payer.pay(newChannel, asset, receiver.address, 10.u256).get let payment = payer.pay(newChannel, asset, receiver.address, 10.u256).get
check receiver.acceptPayment(channel, asset, payer.address, payment).isErr check receiver.acceptPayment(channel, asset, payer.address, payment).isFailure
test "fails when state is updated in unrelated areas": test "fails when state is updated in unrelated areas":
var payment = payer.pay(channel, asset, receiver.address, 10.u256).get var payment = payer.pay(channel, asset, receiver.address, 10.u256).get
payment.state.appDefinition = EthAddress.example payment.state.appDefinition = EthAddress.example
payment.signatures = @[payerKey.sign(payment.state)] payment.signatures = @[payerKey.sign(payment.state)]
check receiver.acceptPayment(channel, asset, payer.address, payment).isErr check receiver.acceptPayment(channel, asset, payer.address, payment).isFailure