2018-08-10 12:49:26 +02:00
|
|
|
// Copyright BigchainDB GmbH and BigchainDB contributors
|
|
|
|
// SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
|
|
|
|
// Code is Apache-2.0 and docs are CC-BY-4.0
|
|
|
|
|
2021-03-10 13:36:00 +01:00
|
|
|
import { createHash } from 'crypto'
|
|
|
|
import { validateFulfillment } from 'crypto-conditions'
|
2017-06-16 11:12:56 +02:00
|
|
|
import test from 'ava'
|
2021-03-10 13:36:00 +01:00
|
|
|
import base58 from 'bs58'
|
2018-01-15 15:42:34 +01:00
|
|
|
import { Ed25519Keypair, Transaction, ccJsonLoad } from '../../src'
|
2020-12-10 12:54:00 +01:00
|
|
|
import { delegatedSignTransaction } from '../constants'
|
2018-03-01 12:22:36 +01:00
|
|
|
import sha256Hash from '../../src/sha256Hash'
|
2017-06-08 14:09:23 +02:00
|
|
|
|
2017-06-20 11:35:25 +02:00
|
|
|
test('Ed25519 condition encoding', t => {
|
2017-06-20 10:45:12 +02:00
|
|
|
const publicKey = '4zvwRjXUKGfvwnParsHAS3HuSVzV5cA4McphgmoCtajS'
|
|
|
|
const target = {
|
|
|
|
details: {
|
2017-06-20 11:35:25 +02:00
|
|
|
type: 'ed25519-sha-256',
|
2017-06-20 10:45:12 +02:00
|
|
|
public_key: publicKey,
|
|
|
|
},
|
|
|
|
uri: 'ni:///sha-256;uLdVX7FEjLWVDkAkfMAkEqPPwFqZj7qfiGE152t_x5c?fpt=ed25519-sha-256&cost=131072'
|
|
|
|
}
|
2017-06-20 11:35:25 +02:00
|
|
|
t.deepEqual(target, Transaction.makeEd25519Condition(publicKey))
|
|
|
|
})
|
|
|
|
|
2018-04-04 10:16:39 +02:00
|
|
|
test('Sha256Condition fulfillment', t => {
|
|
|
|
const preimage = 'secret'
|
|
|
|
const target = {
|
|
|
|
details: {
|
|
|
|
type_id: 0,
|
|
|
|
bitmask: 3,
|
|
|
|
preimage,
|
|
|
|
type: 'fulfillment'
|
|
|
|
},
|
|
|
|
uri: 'ni:///sha-256;K7gNU3sdo-OL0wNhqoVWhr3g6s1xYv72ol_pe_Unols?fpt=preimage-sha-256&cost=6'
|
|
|
|
}
|
|
|
|
t.deepEqual(target, Transaction.makeSha256Condition(preimage))
|
|
|
|
})
|
|
|
|
|
2017-06-20 11:35:25 +02:00
|
|
|
test('Threshold condition encoding', t => {
|
|
|
|
const publicKey = '4zvwRjXUKGfvwnParsHAS3HuSVzV5cA4McphgmoCtajS'
|
2017-06-23 10:30:08 +02:00
|
|
|
const ed25519 = Transaction.makeEd25519Condition(publicKey, false)
|
2018-01-04 10:15:45 +01:00
|
|
|
const condition = Transaction.makeThresholdCondition(1, [ed25519, ed25519])
|
2017-06-23 10:24:23 +02:00
|
|
|
const output = Transaction.makeOutput(condition)
|
2017-06-20 11:35:25 +02:00
|
|
|
const target = {
|
2017-06-23 10:24:23 +02:00
|
|
|
condition: {
|
|
|
|
details: {
|
|
|
|
type: 'threshold-sha-256',
|
|
|
|
threshold: 1,
|
2017-06-28 01:25:07 +02:00
|
|
|
subconditions: [
|
2017-06-23 10:30:08 +02:00
|
|
|
{
|
|
|
|
type: 'ed25519-sha-256',
|
|
|
|
public_key: publicKey,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
type: 'ed25519-sha-256',
|
|
|
|
public_key: publicKey,
|
|
|
|
}
|
|
|
|
]
|
2017-06-23 10:24:23 +02:00
|
|
|
},
|
2017-06-23 10:30:08 +02:00
|
|
|
uri: 'ni:///sha-256;xTeBhQj7ae5Tym7cp83fwtkesQnhdwNwDEMIYwnf2g0?fpt=threshold-sha-256&cost=133120&subtypes=ed25519-sha-256',
|
2017-06-20 11:35:25 +02:00
|
|
|
},
|
2017-06-23 10:24:23 +02:00
|
|
|
amount: '1',
|
|
|
|
public_keys: [publicKey]
|
2017-06-20 11:35:25 +02:00
|
|
|
}
|
2017-06-23 10:24:23 +02:00
|
|
|
t.deepEqual(target, output)
|
2017-06-20 10:45:12 +02:00
|
|
|
})
|
2017-06-21 09:24:39 +02:00
|
|
|
|
|
|
|
test('Fulfillment correctly formed', t => {
|
|
|
|
const alice = new Ed25519Keypair()
|
|
|
|
const txCreate = Transaction.makeCreateTransaction(
|
|
|
|
{},
|
|
|
|
{},
|
|
|
|
[Transaction.makeOutput(Transaction.makeEd25519Condition(alice.publicKey))],
|
|
|
|
alice.publicKey
|
|
|
|
)
|
2018-03-01 12:22:36 +01:00
|
|
|
// Sign in order to get the tx id, needed for the unique fulfillment in the transfer transaction
|
|
|
|
const signCreateTransaction = Transaction.signTransaction(txCreate, alice.privateKey)
|
|
|
|
|
2017-06-21 09:24:39 +02:00
|
|
|
const txTransfer = Transaction.makeTransferTransaction(
|
2018-03-01 12:22:36 +01:00
|
|
|
[{ tx: signCreateTransaction, output_index: 0 }],
|
2017-06-21 09:24:39 +02:00
|
|
|
[Transaction.makeOutput(Transaction.makeEd25519Condition(alice.publicKey))],
|
2017-09-19 21:47:33 +02:00
|
|
|
{}
|
2017-06-21 09:24:39 +02:00
|
|
|
)
|
|
|
|
const txSigned = Transaction.signTransaction(txTransfer, alice.privateKey)
|
2018-03-01 12:22:36 +01:00
|
|
|
|
|
|
|
// Here reconstruct the fulfillment of the transfer transaction
|
|
|
|
// The tx is serialized, and extended with tx_id and output index, and then hashed into bytes
|
|
|
|
const msg = Transaction.serializeTransactionIntoCanonicalString(txTransfer)
|
|
|
|
const msgUniqueFulfillment = txTransfer.inputs[0].fulfills ? msg
|
|
|
|
.concat(txTransfer.inputs[0].fulfills.transaction_id)
|
|
|
|
.concat(txTransfer.inputs[0].fulfills.output_index) : msg
|
|
|
|
const msgHash = sha256Hash(msgUniqueFulfillment)
|
|
|
|
|
2021-03-10 13:36:00 +01:00
|
|
|
t.truthy(validateFulfillment(
|
2018-01-04 10:15:45 +01:00
|
|
|
txSigned.inputs[0].fulfillment, txCreate.outputs[0].condition.uri,
|
2018-03-01 12:22:36 +01:00
|
|
|
Buffer.from(msgHash, 'hex')
|
2018-01-04 10:15:45 +01:00
|
|
|
))
|
2017-06-21 09:24:39 +02:00
|
|
|
})
|
2017-07-05 15:09:33 +02:00
|
|
|
|
2020-12-10 12:54:00 +01:00
|
|
|
test('Delegated signature is correct', t => {
|
|
|
|
const alice = new Ed25519Keypair()
|
|
|
|
|
|
|
|
const txCreate = Transaction.makeCreateTransaction(
|
|
|
|
{},
|
|
|
|
{},
|
|
|
|
[Transaction.makeOutput(Transaction.makeEd25519Condition(alice.publicKey))],
|
|
|
|
alice.publicKey
|
|
|
|
)
|
|
|
|
|
|
|
|
const signCreateTransaction = Transaction.signTransaction(txCreate, alice.privateKey)
|
|
|
|
const delegatedSignCreateTransaction = Transaction.delegateSignTransaction(
|
|
|
|
txCreate,
|
|
|
|
delegatedSignTransaction(alice)
|
|
|
|
)
|
|
|
|
t.deepEqual(signCreateTransaction, delegatedSignCreateTransaction)
|
|
|
|
})
|
|
|
|
|
2021-03-11 13:04:17 +01:00
|
|
|
test('Delegated async signature is correct', async t => {
|
|
|
|
const alice = new Ed25519Keypair()
|
|
|
|
|
|
|
|
const txCreate = Transaction.makeCreateTransaction(
|
|
|
|
{},
|
|
|
|
{},
|
|
|
|
[Transaction.makeOutput(Transaction.makeEd25519Condition(alice.publicKey))],
|
|
|
|
alice.publicKey
|
|
|
|
)
|
|
|
|
|
|
|
|
const signCreateTransaction = Transaction.signTransaction(txCreate, alice.privateKey)
|
|
|
|
const delegatedSignCreateTransaction = await Transaction.delegateSignTransactionAsync(
|
|
|
|
txCreate,
|
|
|
|
delegatedSignTransaction(alice)
|
|
|
|
)
|
|
|
|
t.deepEqual(signCreateTransaction, delegatedSignCreateTransaction)
|
|
|
|
})
|
|
|
|
|
2017-07-05 15:09:33 +02:00
|
|
|
test('CryptoConditions JSON load', t => {
|
2021-03-10 13:36:00 +01:00
|
|
|
const publicKey = '4zvwRjXUKGfvwnParsHAS3HuSVzV5cA4McphgmoCtajS'
|
2018-01-15 15:42:34 +01:00
|
|
|
const cond = ccJsonLoad({
|
2017-07-05 15:09:33 +02:00
|
|
|
type: 'threshold-sha-256',
|
|
|
|
threshold: 1,
|
|
|
|
subconditions: [{
|
|
|
|
type: 'ed25519-sha-256',
|
2021-03-10 13:36:00 +01:00
|
|
|
public_key: publicKey
|
2017-07-05 15:39:47 +02:00
|
|
|
},
|
|
|
|
{
|
2021-03-10 13:36:00 +01:00
|
|
|
hash: base58.encode(createHash('sha256').update('a').digest())
|
2017-07-05 15:09:33 +02:00
|
|
|
}],
|
|
|
|
})
|
2017-07-05 15:39:47 +02:00
|
|
|
t.truthy(cond.subconditions.length === 2)
|
2017-07-05 15:09:33 +02:00
|
|
|
})
|