nim-abc/tests/abc/testHistory.nim

190 lines
6.4 KiB
Nim

import abc/txstore
import abc/history
import ./basics
import ./alicebob
func set[T](elements: varargs[T]): HashSet[T] =
elements.toHashSet
suite "Past transactions and acknowledgements":
let genesis = Transaction.genesis
let alice = PublicKey.alice
let bob = PublicKey.bob
let victor = PublicKey.victor
var store: TxStore
var tx1, tx2, tx3: Transaction
var ack1, ack2, ack3: Ack
setup:
store = TxStore.new(genesis)
tx1 = !Transaction.init({genesis.hash: alice}, {bob: 100.u256}, victor)
tx2 = !Transaction.init({genesis.hash: bob}, {alice: 100.u256}, victor)
tx3 = !Transaction.init(
{tx1.hash: bob, tx2.hash: alice},
{alice: 200.u256},
victor
)
ack1 = !Ack.init([tx1.hash], victor)
ack2 = !Ack.init([tx2.hash], victor)
ack3 = !Ack.init(ack1.hash, [tx2.hash, tx3.hash], victor)
PrivateKey.alice.sign(tx1)
PrivateKey.bob.sign(tx2)
PrivateKey.alice.sign(tx3)
PrivateKey.bob.sign(tx3)
PrivateKey.victor.sign(ack1)
PrivateKey.victor.sign(ack2)
PrivateKey.victor.sign(ack3)
test "finds all transactions that precede a transaction":
store.add(tx1, tx2, tx3)
check store.past(tx1.hash).transactions == set(genesis.hash)
check store.past(tx2.hash).transactions == set(genesis.hash)
check store.past(tx3.hash).transactions ==
set(genesis.hash, tx1.hash, tx2.hash)
test "past is empty when transaction cannot be found":
check store.past(tx1.hash).transactions == set[TxHash]()
test "finds all transactions that precede an acknowledgement":
store.add(tx1, tx2, tx3)
store.add(ack1, ack2, ack3)
check store.past(ack1.hash).transactions == set(genesis.hash, tx1.hash)
check store.past(ack2.hash).transactions == set(genesis.hash, tx2.hash)
check store.past(ack3.hash).transactions ==
set(genesis.hash, tx1.hash, tx2.hash, tx3.hash)
test "finds all transactions that precede a set of acknowledgements":
store.add(tx1, tx2, tx3)
store.add(ack1, ack2, ack3)
check store.past(ack1.hash, ack2.hash).transactions ==
set(genesis.hash, tx1.hash, tx2.hash)
test "past contains the genesis hash":
store.add(tx1, tx3)
store.add(ack3)
check store.past(tx1.hash).genesis == store.genesis
check store.past(tx3.hash).genesis == store.genesis
check store.past(ack3.hash).genesis == store.genesis
suite "Transaction validation":
let alice = PublicKey.alice
let bob = PublicKey.bob
let victor = PublicKey.victor
let genesis = Transaction.genesis
var store: TxStore
var tx1, tx2: Transaction
setup:
store = TxStore.new(genesis)
tx1 = !Transaction.init({genesis.hash: alice}, {bob: 100.u256}, victor)
tx2 = !Transaction.init({tx1.hash: bob}, {alice: 100.u256}, victor)
PrivateKey.alice.sign(tx1)
PrivateKey.bob.sign(tx2)
test "checks validity of transactions":
store.add(tx1, tx2)
check isValid store.past(genesis.hash)
check isValid store.past(tx1.hash)
check isValid store.past(tx2.hash)
test "checks that no input is missing":
store.add(tx2) # tx2 depends on tx1, which is missing
let past = store.past(tx2.hash)
check not isValid past
check past.missingTx == set(tx1.hash)
test "checks that inputs and outputs match":
var bad1 = !Transaction.init({genesis.hash: alice}, {bob: 999.u256}, victor)
var bad2 = !Transaction.init({bad1.hash: bob}, {alice: 999.u256}, victor)
PrivateKey.alice.sign(bad1)
PrivateKey.bob.sign(bad2)
store.add(bad1, bad2)
for transaction in [bad1, bad2]:
let past = store.past(transaction.hash)
check not isValid past
check past.invalidTx == set(bad1.hash)
test "checks that signatures match":
var bad1 = !Transaction.init({genesis.hash: alice}, {bob: 100.u256}, victor)
var bad2 = !Transaction.init({bad1.hash: bob}, {alice: 100.u256}, victor)
PrivateKey.bob.sign(bad1) # invalid signature, should be signed by alice
PrivateKey.bob.sign(bad2)
store.add(bad1, bad2)
for transaction in [bad1, bad2]:
let past = store.past(transaction.hash)
check not isValid past
check past.invalidTx == set(bad1.hash)
suite "Acknowledgement validation":
let alice = PublicKey.alice
let bob = PublicKey.bob
let victor = PublicKey.victor
let genesis = Transaction.genesis
var store: TxStore
var tx1, tx2: Transaction
var ack1, ack2: Ack
setup:
store = TxStore.new(genesis)
tx1 = !Transaction.init({genesis.hash: alice}, {bob: 100.u256}, victor)
tx2 = !Transaction.init({tx1.hash: bob}, {alice: 100.u256}, victor)
ack1 = !Ack.init([tx1.hash], victor)
ack2 = !Ack.init(ack1.hash, [tx2.hash], victor)
PrivateKey.alice.sign(tx1)
PrivateKey.bob.sign(tx2)
PrivateKey.victor.sign(ack1)
PrivateKey.victor.sign(ack2)
test "checks validity of acknowledgements":
store.add(tx1, tx2)
store.add(ack1, ack2)
check isValid store.past(ack1.hash)
check isValid store.past(ack2.hash)
test "checks that no previous acknowledgement is missing":
store.add(tx1, tx2)
store.add(ack2) # ack2 depends on ack1, which is missing
let past = store.past(ack2.hash)
check not isValid past
check past.missingAck == set(ack1.hash)
test "checks that no transaction is missing":
store.add(tx2) # tx2 depends on tx1, which is missing
store.add(ack1, ack2)
let past = store.past(ack2.hash)
check not isValid past
check past.missingTx == set(tx1.hash)
test "checks that no transaction is invalid":
var bad = !Transaction.init({genesis.hash: alice}, {bob: 999.u256}, victor)
var ack = !Ack.init([bad.hash], victor)
PrivateKey.alice.sign(bad)
PrivateKey.victor.sign(ack)
store.add(bad)
store.add(ack)
let past = store.past(ack.hash)
check not isValid past
check past.invalidTx == set(bad.hash)
test "checks that signatures match":
var bad1 = !Ack.init([tx1.hash], victor)
var bad2 = !Ack.init(bad1.hash, [tx2.hash], victor)
PrivateKey.bob.sign(bad1) # invalid signature, should be signed by victor
PrivateKey.victor.sign(bad2)
store.add(tx1, tx2)
store.add(bad1, bad2)
for ack in [bad1, bad2]:
let past = store.past(ack.hash)
check not isValid past
check past.invalidAck == set(bad1.hash)
test "checks validity of a set of acknowledgements":
store.add(tx1, tx2)
store.add(ack2)
check not isValid store.past(ack1.hash, ack2.hash)
store.add(ack1)
check isValid store.past(ack1.hash, ack2.hash)