mirror of
https://github.com/bigchaindb/js-bigchaindb-driver.git
synced 2024-11-22 17:50:09 +01:00
unique-fulfillment and hash&sign
This commit is contained in:
parent
428edad6eb
commit
c3e1244e52
@ -18,7 +18,7 @@ before_install:
|
|||||||
-e BIGCHAINDB_KEYPAIR_PRIVATE=5C5Cknco7YxBRP9AgB1cbUVTL4FAcooxErLygw1DeG2D
|
-e BIGCHAINDB_KEYPAIR_PRIVATE=5C5Cknco7YxBRP9AgB1cbUVTL4FAcooxErLygw1DeG2D
|
||||||
-e BIGCHAINDB_DATABASE_BACKEND=mongodb
|
-e BIGCHAINDB_DATABASE_BACKEND=mongodb
|
||||||
-e BIGCHAINDB_DATABASE_HOST=172.17.0.1
|
-e BIGCHAINDB_DATABASE_HOST=172.17.0.1
|
||||||
bigchaindb/bigchaindb:1.3.0
|
bigchaindb/bigchaindb:1.4.0
|
||||||
start
|
start
|
||||||
- gem install cowsay
|
- gem install cowsay
|
||||||
- npm install -g codecov
|
- npm install -g codecov
|
||||||
|
@ -30,14 +30,6 @@ export default class Transaction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static hashTransaction(transaction) {
|
|
||||||
// Safely remove any tx id from the given transaction for hashing
|
|
||||||
const tx = { ...transaction }
|
|
||||||
delete tx.id
|
|
||||||
|
|
||||||
return sha256Hash(Transaction.serializeTransactionIntoCanonicalString(tx))
|
|
||||||
}
|
|
||||||
|
|
||||||
static makeTransactionTemplate() {
|
static makeTransactionTemplate() {
|
||||||
const txTemplate = {
|
const txTemplate = {
|
||||||
'id': null,
|
'id': null,
|
||||||
@ -58,8 +50,6 @@ export default class Transaction {
|
|||||||
tx.metadata = metadata
|
tx.metadata = metadata
|
||||||
tx.inputs = inputs
|
tx.inputs = inputs
|
||||||
tx.outputs = outputs
|
tx.outputs = outputs
|
||||||
|
|
||||||
tx.id = Transaction.hashTransaction(tx)
|
|
||||||
return tx
|
return tx
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,15 +236,23 @@ export default class Transaction {
|
|||||||
signedTx.inputs.forEach((input, index) => {
|
signedTx.inputs.forEach((input, index) => {
|
||||||
const privateKey = privateKeys[index]
|
const privateKey = privateKeys[index]
|
||||||
const privateKeyBuffer = Buffer.from(base58.decode(privateKey))
|
const privateKeyBuffer = Buffer.from(base58.decode(privateKey))
|
||||||
const serializedTransaction = Transaction
|
const serializedTransaction =
|
||||||
.serializeTransactionIntoCanonicalString(transaction)
|
Transaction.serializeTransactionIntoCanonicalString(transaction)
|
||||||
|
|
||||||
|
const transactionUniqueFulfillment = input.fulfills ? serializedTransaction
|
||||||
|
.concat(input.fulfills.transaction_id)
|
||||||
|
.concat(input.fulfills.output_index) : serializedTransaction
|
||||||
|
const transactionHash = sha256Hash(transactionUniqueFulfillment)
|
||||||
const ed25519Fulfillment = new cc.Ed25519Sha256()
|
const ed25519Fulfillment = new cc.Ed25519Sha256()
|
||||||
ed25519Fulfillment.sign(Buffer.from(serializedTransaction), privateKeyBuffer)
|
ed25519Fulfillment.sign(Buffer.from(transactionHash, 'hex'), privateKeyBuffer)
|
||||||
const fulfillmentUri = ed25519Fulfillment.serializeUri()
|
const fulfillmentUri = ed25519Fulfillment.serializeUri()
|
||||||
|
|
||||||
input.fulfillment = fulfillmentUri
|
input.fulfillment = fulfillmentUri
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const serializedTransaction =
|
||||||
|
Transaction.serializeTransactionIntoCanonicalString(signedTx)
|
||||||
|
signedTx.id = sha256Hash(serializedTransaction)
|
||||||
return signedTx
|
return signedTx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import test from 'ava'
|
import test from 'ava'
|
||||||
import cc from 'crypto-conditions'
|
import cc from 'crypto-conditions'
|
||||||
import { Ed25519Keypair, Transaction, ccJsonLoad } from '../../src'
|
import { Ed25519Keypair, Transaction, ccJsonLoad } from '../../src'
|
||||||
|
import sha256Hash from '../../src/sha256Hash'
|
||||||
|
|
||||||
test('Ed25519 condition encoding', t => {
|
test('Ed25519 condition encoding', t => {
|
||||||
const publicKey = '4zvwRjXUKGfvwnParsHAS3HuSVzV5cA4McphgmoCtajS'
|
const publicKey = '4zvwRjXUKGfvwnParsHAS3HuSVzV5cA4McphgmoCtajS'
|
||||||
@ -53,16 +54,27 @@ test('Fulfillment correctly formed', t => {
|
|||||||
[Transaction.makeOutput(Transaction.makeEd25519Condition(alice.publicKey))],
|
[Transaction.makeOutput(Transaction.makeEd25519Condition(alice.publicKey))],
|
||||||
alice.publicKey
|
alice.publicKey
|
||||||
)
|
)
|
||||||
|
// Sign in order to get the tx id, needed for the unique fulfillment in the transfer transaction
|
||||||
|
const signCreateTransaction = Transaction.signTransaction(txCreate, alice.privateKey)
|
||||||
|
|
||||||
const txTransfer = Transaction.makeTransferTransaction(
|
const txTransfer = Transaction.makeTransferTransaction(
|
||||||
[{ tx: txCreate, output_index: 0 }],
|
[{ tx: signCreateTransaction, output_index: 0 }],
|
||||||
[Transaction.makeOutput(Transaction.makeEd25519Condition(alice.publicKey))],
|
[Transaction.makeOutput(Transaction.makeEd25519Condition(alice.publicKey))],
|
||||||
{}
|
{}
|
||||||
)
|
)
|
||||||
const msg = Transaction.serializeTransactionIntoCanonicalString(txTransfer)
|
|
||||||
const txSigned = Transaction.signTransaction(txTransfer, alice.privateKey)
|
const txSigned = Transaction.signTransaction(txTransfer, alice.privateKey)
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
t.truthy(cc.validateFulfillment(
|
t.truthy(cc.validateFulfillment(
|
||||||
txSigned.inputs[0].fulfillment, txCreate.outputs[0].condition.uri,
|
txSigned.inputs[0].fulfillment, txCreate.outputs[0].condition.uri,
|
||||||
Buffer.from(msg)
|
Buffer.from(msgHash, 'hex')
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user