diff --git a/nitro/basics.nim b/nitro/basics.nim index 1e20cea..1ff669d 100644 --- a/nitro/basics.nim +++ b/nitro/basics.nim @@ -3,9 +3,11 @@ import pkg/questionable/results import pkg/stint import ./uint48 import ./ethaddress +import ./destination export questionable export results export stint export uint48 export ethaddress +export destination diff --git a/nitro/destination.nim b/nitro/destination.nim new file mode 100644 index 0000000..d0baded --- /dev/null +++ b/nitro/destination.nim @@ -0,0 +1,25 @@ +import pkg/questionable +import pkg/questionable/results +import pkg/stew/byteutils +import ./ethaddress + +include questionable/errorban + +type Destination* = distinct array[32, byte] + +proc toArray*(destination: Destination): array[32, byte] = + array[32, byte](destination) + +proc `$`*(destination: Destination): string = + destination.toArray().toHex() + +proc parse*(_: type Destination, s: string): ?Destination = + Destination(array[32, byte].fromHex(s)).catch.toOption() + +proc `==`*(a, b: Destination): bool {.borrow.} + +proc toDestination*(address: EthAddress): Destination = + var bytes: array[32, byte] + for i in 0..<20: + bytes[12 + i] = array[20, byte](address)[i] + Destination(bytes) diff --git a/nitro/protocol/abi.nim b/nitro/protocol/abi.nim index e45fc0a..15d384f 100644 --- a/nitro/protocol/abi.nim +++ b/nitro/protocol/abi.nim @@ -99,6 +99,9 @@ proc encode(encoder: var AbiEncoder, bytes: seq[byte]) = proc encode(encoder: var AbiEncoder, address: EthAddress) = encoder.padleft(address.toArray) +proc encode(encoder: var AbiEncoder, destination: Destination) = + encoder.encode(destination.toArray) + proc encode[I, T](encoder: var AbiEncoder, value: array[I, T]) = encoder.startTuple() for element in value: diff --git a/nitro/protocol/channel.nim b/nitro/protocol/channel.nim index d454a86..aa85ebc 100644 --- a/nitro/protocol/channel.nim +++ b/nitro/protocol/channel.nim @@ -12,11 +12,11 @@ type participants*: seq[EthAddress] chainId*: UInt256 -proc getChannelId*(channel: ChannelDefinition): array[32, byte] = +proc getChannelId*(channel: ChannelDefinition): Destination = var encoder= AbiEncoder.init() encoder.startTuple() encoder.write(channel.chainId) encoder.write(channel.participants) encoder.write(channel.nonce) encoder.finishTuple() - keccak256.digest(encoder.finish()).data + Destination(keccak256.digest(encoder.finish()).data) diff --git a/nitro/protocol/outcome.nim b/nitro/protocol/outcome.nim index c74558a..45d6b25 100644 --- a/nitro/protocol/outcome.nim +++ b/nitro/protocol/outcome.nim @@ -20,11 +20,11 @@ type guarantee*: Guarantee Allocation* = distinct seq[AllocationItem] AllocationItem* = object - destination*: array[32, byte] + destination*: Destination amount*: UInt256 Guarantee* = object - targetChannelId*: array[32, byte] - destinations*: seq[array[32, byte]] + targetChannelId*: Destination + destinations*: seq[Destination] proc encode*(encoder: var AbiEncoder, guarantee: Guarantee) = encoder.startTuple() diff --git a/tests/nitro/examples.nim b/tests/nitro/examples.nim index 1337afc..41c46da 100644 --- a/tests/nitro/examples.nim +++ b/tests/nitro/examples.nim @@ -27,6 +27,9 @@ proc example*(_: type UInt128): UInt128 = proc example*(_: type EthAddress): EthAddress = EthAddress(array[20, byte].example) +proc example*(_: type Destination): Destination = + Destination(array[32, byte].example) + proc example*(_: type ChannelDefinition): ChannelDefinition = ChannelDefinition( nonce: UInt48.example, @@ -36,14 +39,14 @@ proc example*(_: type ChannelDefinition): ChannelDefinition = proc example*(_: type AllocationItem): AllocationItem = AllocationItem( - destination: array[32, byte].example, + destination: Destination.example, amount: UInt256.example ) proc example*(_: type Guarantee): Guarantee = Guarantee( - targetChannelId: array[32, byte].example, - destinations: seq[array[32, byte]].example + targetChannelId: Destination.example, + destinations: seq[Destination].example ) proc example*(_: type Allocation): Allocation = diff --git a/tests/nitro/protocol/testChannel.nim b/tests/nitro/protocol/testChannel.nim index 0a7afd0..d65d41c 100644 --- a/tests/nitro/protocol/testChannel.nim +++ b/tests/nitro/protocol/testChannel.nim @@ -16,7 +16,7 @@ suite "channel definition": encoder.finishTuple() let encoded = encoder.finish() let hashed = keccak256.digest(encoded).data - check getChannelId(channel) == hashed + check getChannelId(channel) == Destination(hashed) test "produces same id as javascript implementation": let channel = ChannelDefinition( @@ -26,7 +26,7 @@ suite "channel definition": EthAddress.fromHex("24b905Dcc8A11C0FE57C2592f3D25f0447402C10").get() ] ) - let expected = array[32, byte].fromHex( + let expected = Destination.parse( "4f8cce57e9fe88edaab05234972eaf0c2d183e4f6b175aff293375fbe4d5d7cc" - ) + ).get() check getChannelId(channel) == expected diff --git a/tests/nitro/protocol/testOutcome.nim b/tests/nitro/protocol/testOutcome.nim index 71bb70a..ea0b9ad 100644 --- a/tests/nitro/protocol/testOutcome.nim +++ b/tests/nitro/protocol/testOutcome.nim @@ -96,9 +96,9 @@ suite "outcome": ).get(), allocation: Allocation(@[ AllocationItem( - destination: array[32, byte].fromHex( + destination: Destination.parse( "f1918e8562236eb17adc8502332f4c9c82bc14e19bfc0aa10ab674ff75b3d2f3" - ), + ).get(), amount: 0x05.u256 ) ]) @@ -109,13 +109,13 @@ suite "outcome": "1E90B49563da16D2537CA1Ddd9b1285279103D93" ).get(), guarantee: Guarantee( - targetChannelId: array[32, byte].fromHex( + targetChannelId: Destination.parse( "cac1bb71f0a97c8ac94ca9546b43178a9ad254c7b757ac07433aa6df35cd8089" - ), + ).get(), destinations: @[ - array[32, byte].fromHex( + Destination.parse( "f1918e8562236eb17adc8502332f4c9c82bc14e19bfc0aa10ab674ff75b3d2f3" - ) + ).get() ] ) )