Transactions

This commit is contained in:
Mark Spanbroek 2021-06-28 15:04:50 +02:00
parent 2fbf826655
commit 5661469aee
4 changed files with 101 additions and 0 deletions

View File

@ -6,4 +6,5 @@ license = "MIT"
requires "questionable >= 0.10.0 & < 0.11.0" requires "questionable >= 0.10.0 & < 0.11.0"
requires "https://github.com/markspanbroek/nim-blscurve#fix-nimble" requires "https://github.com/markspanbroek/nim-blscurve#fix-nimble"
requires "nimcrypto" requires "nimcrypto"
requires "stint"
requires "stew" requires "stew"

52
abc/transactions.nim Normal file
View File

@ -0,0 +1,52 @@
import pkg/nimcrypto
import pkg/stint
import ./keys
export stint
export keys
type
Transaction* = object
inputs: seq[TxInput]
outputs: seq[TxOutput]
signature: Signature
TxInput* = tuple
txHash: TxHash
owner: PublicKey
TxOutput* = tuple
owner: PublicKey
amount: UInt256
TxHash* = distinct MDigest[256]
func `==`*(a, b: TxHash): bool {.borrow.}
func init*(_: type Transaction,
inputs: openArray[TxInput],
outputs: openArray[TxOutput]): Transaction =
Transaction(inputs: @inputs, outputs: @outputs)
func init*(_: type Transaction,
outputs: openArray[TxOutput]): Transaction =
Transaction.init([], outputs)
func inputs*(transaction: Transaction): seq[TxInput] =
transaction.inputs
func outputs*(transaction: Transaction): seq[TxOutput] =
transaction.outputs
func toBytes*(hash: TxHash): array[32, byte] =
MDigest[256](hash).data
func toBytes*(transaction: Transaction): seq[byte] =
result.add(transaction.inputs.len.uint8)
for (txHash, owner) in transaction.inputs:
result.add(txHash.toBytes)
result.add(owner.toBytes)
result.add(transaction.outputs.len.uint8)
for (owner, amount) in transaction.outputs:
result.add(owner.toBytes)
result.add(amount.toBytes)
func hash*(transaction: Transaction): TxHash =
TxHash(sha256.digest(transaction.toBytes))

View File

@ -1,7 +1,13 @@
import abc/keys import abc/keys
import abc/transactions
proc example*(_: type PrivateKey): PrivateKey = proc example*(_: type PrivateKey): PrivateKey =
PrivateKey.random PrivateKey.random
proc example*(_: type PublicKey): PublicKey = proc example*(_: type PublicKey): PublicKey =
PrivateKey.example.toPublicKey PrivateKey.example.toPublicKey
proc example*(_: type Transaction): Transaction =
let alice, bob = PublicKey.example
let genesis = Transaction.init({alice: 32.u256, bob: 10.u256})
Transaction.init({genesis.hash: alice}, {alice: 2.u256, bob: 30.u256})

View File

@ -0,0 +1,42 @@
import std/unittest
import abc/transactions
import ./examples
suite "Transactions":
let alice, bob = PublicKey.example
test "a genesis transaction can be made":
let genesis = Transaction.init({alice: 32.u256, bob: 10.u256})
test "a transaction has a hash":
let transaction1, transaction2 = Transaction.example
check transaction1.hash == transaction1.hash
check transaction2.hash == transaction2.hash
check transaction1.hash != transaction2.hash
test "a transaction references outputs from other transactions":
let genesis = Transaction.init({alice: 32.u256, bob: 10.u256})
let transaction = Transaction.init(
{genesis.hash: alice},
{alice: 2.u256, bob: 30.u256}
)
check transaction.inputs.len == 1
check transaction.outputs.len == 2
test "a transaction can be converted to bytes":
let genesis = Transaction.init({alice: 32.u256, bob: 10.u256})
let transaction = Transaction.init(
{genesis.hash: alice},
{alice: 2.u256, bob: 30.u256}
)
var expected: seq[byte]
expected.add(1) # amount of inputs
expected.add(genesis.hash.toBytes)
expected.add(alice.toBytes)
expected.add(2) # amount of outputs
expected.add(alice.toBytes)
expected.add(2.u256.toBytes)
expected.add(bob.toBytes)
expected.add(30.u256.toBytes)
check transaction.toBytes == expected