Implement JSDescription creation (minus proof)

This commit is contained in:
Jack Grigg 2017-06-02 14:45:30 +12:00
parent e823108984
commit 74cb490dfa
No known key found for this signature in database
GPG Key ID: 665DBCD284F7DAFF
9 changed files with 804 additions and 0 deletions

View File

@ -1,10 +1,33 @@
'use strict'
var blake2b = require('./blake2b')
var bufferutils = require('./bufferutils')
var prf = require('./prf')
var typeforce = require('typeforce')
var types = require('./types')
var util = require('./util')
var zconst = require('./const')
var JSProofWitness = require('./proof_witness')
var NotePlaintext = require('./note_plaintext')
var ZCNoteEncryption = require('./note_encryption')
var ZCProof = require('./proof')
function hSig (randomSeed, nullifiers, pubKeyHash) {
typeforce(types.tuple(
types.Buffer256bit,
types.arrayOf(types.Buffer256bit),
types.Buffer256bit
), arguments)
return Buffer.from(blake2b.crypto_generichash_blake2b_salt_personal(
32,
Buffer.concat([randomSeed].concat(nullifiers).concat([pubKeyHash])),
undefined, // No key.
undefined, // No salt.
'ZcashComputehSig'))
}
function JSDescription () {
this.nullifiers = []
this.commitments = []
@ -152,4 +175,119 @@ JSDescription.prototype.toHex = function () {
return this.toBuffer().toString('hex')
}
JSDescription.prototype.h_sig = function (joinSplitPubKey) {
return hSig(this.randomSeed, this.nullifiers, joinSplitPubKey)
}
JSDescription.withWitness = function (inputs, outputs, pubKeyHash, vpubOld, vpubNew, rt) {
typeforce(types.tuple(
types.arrayOf(types.JSInput),
types.arrayOf(types.JSOutput),
types.Buffer256bit,
types.Zatoshi,
types.Zatoshi,
types.Buffer256bit
), arguments)
if (inputs.length !== zconst.ZC_NUM_JS_INPUTS) {
throw new Error(`invalid number of inputs (found ${inputs.length}, expected ${zconst.ZC_NUM_JS_INPUTS}`)
}
if (outputs.length !== zconst.ZC_NUM_JS_OUTPUTS) {
throw new Error(`invalid number of inputs (found ${outputs.length}, expected ${zconst.ZC_NUM_JS_OUTPUTS}`)
}
var jsdesc = new JSDescription()
jsdesc.vpub_old = vpubOld
jsdesc.vpub_new = vpubNew
jsdesc.anchor = rt
var lhsValue = vpubOld
var rhsValue = vpubNew
inputs.forEach(function (input) {
// Sanity checks of input
// If note has nonzero value
if (input.note.value !== 0) {
// The witness root must equal the input root.
if (input.witness.root() !== rt) {
throw new Error('joinsplit not anchored to the correct root')
}
// The tree must witness the correct element
if (input.note.cm() !== input.witness.element()) {
throw new Error('witness of wrong element for joinsplit input')
}
}
// Ensure we have the key to this note.
if (input.note.a_pk.toString('hex') !== input.key.address().a_pk.toString('hex')) {
throw new Error('input note not authorized to spend with given key')
}
// Balance must be sensical
typeforce(types.Zatoshi, input.note.value)
lhsValue += input.note.value
typeforce(types.Zatoshi, lhsValue)
// Compute nullifier of input
jsdesc.nullifiers.push(input.nullifier())
})
// Sample randomSeed
jsdesc.randomSeed = util.random_uint256()
// Compute h_sig
var hSig = jsdesc.h_sig(pubKeyHash)
// Sample phi
var phi = util.random_uint252()
// Compute notes for outputs
var notes = []
outputs.forEach(function (output, i) {
// Sanity checks of output
typeforce(types.Zatoshi, output.value)
rhsValue += output.value
typeforce(types.Zatoshi, rhsValue)
// Sample r
var r = util.random_uint256()
notes.push(output.note(phi, r, i, hSig))
})
if (lhsValue !== rhsValue) {
throw new Error('invalid joinsplit balance')
}
// Compute the output commitments
notes.forEach(function (note) {
jsdesc.commitments.push(note.cm())
})
// Encrypt the ciphertexts containing the note
// plaintexts to the recipients of the value.
var encryptor = new ZCNoteEncryption(hSig)
notes.forEach(function (note, i) {
var pt = new NotePlaintext(note, outputs[i].memo)
jsdesc.ciphertexts.push(pt.encrypt(encryptor, outputs[i].addr.pk_enc))
})
jsdesc.ephemeralKey = encryptor.epk
// Authenticate hSig with each of the input
// spending keys, producing macs which protect
// against malleability.
inputs.forEach(function (input, i) {
jsdesc.macs.push(prf.PRF_pk(inputs[i].key.a_sk, i, hSig))
})
jsdesc.witness = new JSProofWitness(phi, rt, hSig, inputs, notes, vpubOld, vpubNew)
return jsdesc
}
module.exports = JSDescription

87
src/jsinput.js Normal file
View File

@ -0,0 +1,87 @@
'use strict'
var typeforce = require('typeforce')
var types = require('./types')
var zaddr = require('./address')
var Note = require('./note')
var ZCIncrementalMerkleTree = require('./incremental_merkle_tree')
var ZCIncrementalWitness = require('./incremental_witness')
function JSInput (witness, note, key) {
typeforce(types.tuple(
types.ZCIncrementalWitness,
types.Note,
types.SpendingKey
), arguments)
this.witness = witness
this.note = note
this.key = key
}
JSInput.dummy = function () {
var key = zaddr.SpendingKey.random()
var note = Note.dummy(key.address().a_pk)
var dummyTree = new ZCIncrementalMerkleTree()
dummyTree.append(note.cm())
return new JSInput(ZCIncrementalWitness.fromTree(dummyTree), note, key)
}
JSInput.fromBuffer = function (buffer) {
var offset = 0
function readZCIncrementalWitness () {
var witness = ZCIncrementalWitness.fromBuffer(buffer.slice(offset), true)
offset += witness.byteLength()
return witness
}
function readNote () {
var proof = Note.fromBuffer(buffer.slice(offset), true)
offset += proof.byteLength()
return proof
}
function readSpendingKey () {
var sk = zaddr.SpendingKey.fromBuffer(buffer.slice(offset), true)
offset += sk.byteLength()
return sk
}
var witness = readZCIncrementalWitness()
var note = readNote()
var key = readSpendingKey()
var input = new JSInput(witness, note, key)
return input
}
JSInput.prototype.byteLength = function () {
return (
this.witness.byteLength() +
this.note.byteLength() +
this.key.byteLength()
)
}
JSInput.prototype.toBuffer = function () {
var buffer = Buffer.alloc(this.byteLength())
var offset = 0
function writeSlice (slice) {
slice.copy(buffer, offset)
offset += slice.length
}
writeSlice(this.witness.toBuffer())
writeSlice(this.note.toBuffer())
writeSlice(this.key.toBuffer())
return buffer
}
JSInput.prototype.nullifier = function () {
return this.note.nullifier(this.key)
}
module.exports = JSInput

95
src/jsoutput.js Normal file
View File

@ -0,0 +1,95 @@
'use strict'
var bufferutils = require('./bufferutils')
var prf = require('./prf')
var typeforce = require('typeforce')
var types = require('./types')
var zaddr = require('./address')
var zconst = require('./const')
var Note = require('./note')
function JSOutput (addr, value, memo) {
typeforce(types.tuple(
types.PaymentAddress,
types.Zatoshi,
types.maybe(types.Buffer)
), arguments)
if (!memo) {
memo = Buffer.alloc(zconst.ZC_MEMO_SIZE)
memo.fill(0)
memo[0] = 0xF6 // 0xF6 is invalid UTF8 as per spec
}
this.addr = addr
this.value = value
this.memo = memo
}
JSOutput.dummy = function () {
var aSk = zaddr.SpendingKey.random()
return new JSOutput(aSk.address(), 0)
}
JSOutput.fromBuffer = function (buffer) {
var offset = 0
function readSlice (n) {
offset += n
return buffer.slice(offset - n, offset)
}
function readUInt64 () {
var i = bufferutils.readUInt64LE(buffer, offset)
offset += 8
return i
}
function readPaymentAddress () {
var addr = zaddr.PaymentAddress.fromBuffer(buffer.slice(offset), true)
offset += addr.byteLength()
return addr
}
var addr = readPaymentAddress()
var value = readUInt64()
var memo = readSlice(zconst.ZC_MEMO_SIZE)
var output = new JSOutput(addr, value, memo)
return output
}
JSOutput.prototype.toBuffer = function () {
var buffer = Buffer.alloc(this.byteLength())
var offset = 0
function writeSlice (slice) {
slice.copy(buffer, offset)
offset += slice.length
}
function writeUInt64 (i) {
bufferutils.writeUInt64LE(buffer, i, offset)
offset += 8
}
writeSlice(this.addr.toBuffer())
writeUInt64(this.value)
writeSlice(this.memo)
return buffer
}
JSOutput.prototype.note = function (phi, r, i, hSig) {
typeforce(types.tuple(
types.Buffer252bit,
types.Buffer256bit,
types.Number,
types.Buffer256bit
), arguments)
var rho = prf.PRF_rho(phi, i, hSig)
return new Note(this.addr.a_pk, this.value, rho, r)
}
module.exports = JSOutput

128
src/proof_witness.js Normal file
View File

@ -0,0 +1,128 @@
'use strict'
var bufferutils = require('./bufferutils')
var typeforce = require('typeforce')
var types = require('./types')
var zconst = require('./const')
var JSInput = require('./jsinput')
var Note = require('./note')
function JSProofWitness (phi, rt, hSig, inputs, notes, vpubOld, vpubNew) {
typeforce(types.tuple(
types.Buffer252bit,
types.Buffer256bit,
types.Buffer256bit,
[types.JSInput],
[types.Note],
types.Zatoshi,
types.Zatoshi
), arguments)
this.phi = phi
this.rt = rt
this.hSig = hSig
this.inputs = inputs
this.notes = notes
this.vpub_old = vpubOld
this.vpub_new = vpubNew
}
JSProofWitness.fromBuffer = function (buffer, __noStrict) {
var offset = 0
function readSlice (n) {
offset += n
return buffer.slice(offset - n, offset)
}
function readUInt64 () {
var i = bufferutils.readUInt64LE(buffer, offset)
offset += 8
return i
}
function readJSInput () {
var input = JSInput.fromBuffer(buffer.slice(offset), true)
offset += input.byteLength()
return input
}
function readNote () {
var proof = Note.fromBuffer(buffer.slice(offset), true)
offset += proof.byteLength()
return proof
}
var phi = readSlice(32)
var rt = readSlice(32)
var hSig = readSlice(32)
var inputs = []
for (var i = 0; i < zconst.ZC_NUM_JS_INPUTS; ++i) {
inputs.push(readJSInput())
}
var notes = []
for (i = 0; i < zconst.ZC_NUM_JS_OUTPUTS; ++i) {
notes.push(readNote())
}
var vpubOld = readUInt64()
var vpubNew = readUInt64()
var witness = new JSProofWitness(phi, rt, hSig, inputs, notes, vpubOld, vpubNew)
if (__noStrict) return witness
if (offset !== buffer.length) throw new Error('JSProofWitness has unexpected data')
return witness
}
JSProofWitness.fromHex = function (hex) {
return JSProofWitness.fromBuffer(Buffer.from(hex, 'hex'))
}
JSProofWitness.prototype.byteLength = function () {
return (
112 +
this.inputs.reduce(function (sum, input) { return sum + input.byteLength() }, 0) +
this.notes.reduce(function (sum, note) { return sum + note.byteLength() }, 0)
)
}
JSProofWitness.prototype.toBuffer = function () {
var buffer = Buffer.alloc(this.byteLength())
var offset = 0
function writeSlice (slice) {
slice.copy(buffer, offset)
offset += slice.length
}
function writeUInt64 (i) {
bufferutils.writeUInt64LE(buffer, i, offset)
offset += 8
}
writeSlice(this.phi)
writeSlice(this.rt)
writeSlice(this.hSig)
this.inputs.forEach(function (input) {
writeSlice(input.toBuffer())
})
this.notes.forEach(function (note) {
writeSlice(note.toBuffer())
})
writeUInt64(this.vpub_old)
writeUInt64(this.vpub_new)
return buffer
}
JSProofWitness.prototype.toHex = function () {
return this.toBuffer().toString('hex')
}
module.exports = JSProofWitness

View File

@ -29,15 +29,38 @@ var PaymentAddress = typeforce.compile({
var SpendingKey = typeforce.compile({
a_sk: Buffer252bit
})
var ZCIncrementalMerkleTree = typeforce.compile({
left: typeforce.maybe(typeforce.BufferN(32)),
right: typeforce.maybe(typeforce.BufferN(32)),
parents: [typeforce.maybe(typeforce.BufferN(32))]
})
var ZCIncrementalWitness = typeforce.compile({
tree: ZCIncrementalMerkleTree,
filled: [typeforce.BufferN(32)],
cursor: typeforce.maybe(ZCIncrementalMerkleTree)
})
var JSInput = typeforce.compile({
witness: ZCIncrementalWitness,
note: Note,
key: SpendingKey
})
var JSOutput = typeforce.compile({
addr: PaymentAddress,
value: Zatoshi,
memo: typeforce.Buffer
})
// extend typeforce types with ours
var types = {
BoolNum: BoolNum,
Buffer252bit: Buffer252bit,
Buffer256bit: typeforce.BufferN(32),
JSInput: JSInput,
JSOutput: JSOutput,
Note: Note,
PaymentAddress: PaymentAddress,
SpendingKey: SpendingKey,
ZCIncrementalWitness: ZCIncrementalWitness,
Zatoshi: Zatoshi
}

40
test/fixtures/hsig.json vendored Normal file
View File

@ -0,0 +1,40 @@
{
"valid": [
{
"randomSeed": "6161616161616161616161616161616161616161616161616161616161616161",
"nullifiers": [
"6262626262626262626262626262626262626262626262626262626262626262",
"6363636363636363636363636363636363636363636363636363636363636363"
],
"pubKeyHash": "6464646464646464646464646464646464646464646464646464646464646464",
"hex": "a8cba69f1fa329c055756b4af900f8a00b61e44f4cb8a1824ceb58b90a5b8113"
},
{
"randomSeed": "0000000000000000000000000000000000000000000000000000000000000000",
"nullifiers": [
"0000000000000000000000000000000000000000000000000000000000000000",
"0000000000000000000000000000000000000000000000000000000000000000"
],
"pubKeyHash": "0000000000000000000000000000000000000000000000000000000000000000",
"hex": "697322276b5dd93b12fb1fcbd2144b2960f24c73aac6c6a0811447be1e7f1e19"
},
{
"randomSeed": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"nullifiers": [
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
],
"pubKeyHash": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"hex": "4961048919f0ca79d49c9378c36a91a8767060001f4212fe6f7d426f3ccf9f32"
},
{
"randomSeed": "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100",
"nullifiers": [
"1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100",
"1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100"
],
"pubKeyHash": "1f1e1d1c1b1a191817161514131211100f0e0d0c0b0a09080706050403020100",
"hex": "b61110ec162693bc3d9ca7fb0eec3afd2e278e2f41394b3ff11d7cb761ad4b27"
}
]
}

242
test/fixtures/proof_witness.json vendored Normal file
View File

@ -0,0 +1,242 @@
{
"valid": [
{
"raw": {
"phi": "0821a4b79971d66f5c32aaee4862c0e7dbf02349d94e0c1399b75a13b4dd198a",
"anchor": "d7c612c817793191a1e68652121876d6b3bde40f4fa52bc314145ce6e5cdd259",
"hSig": "4f63be3f04e86555ce0903be8bf3b6ab3979b54fba42e23cb9c74b495fe043b5",
"inputs": [
{
"witness": "01c6afccb8d6ddfd6944ee34fd4f313bb6dc5d6ae36968bdf024d21cbbd29d32b900000000",
"note": {
"a_pk": "7d85863f30b911fc308a4ae6b184327996fddd3fed3ce8b3c23b7b4ae3cbe377",
"value": 0,
"rho": "6f77d89f12b6ead91cfc2d810650e5a0d61be88018ddad9119cdd34336e21fc9",
"r": "986bafaa8e6af7a3da6c364307ffed45b2210d6c3cc4d05192622a34949d1504"
},
"key": "0b5852ae184f4e6b29bb0c72c3af6c2f9424690361a0a05ae0860f0c069cafa2"
},
{
"witness": "0164d931c08f715ec3073cbc1178a3ba93c8099212537bc67f8acadd0e1419641400000000",
"note": {
"a_pk": "a3544b9d81c005c895bf9c466a5a764702fe9011889418de0e5895c3f834052c",
"value": 0,
"rho": "53b1526f62991b34cf3414344cdd3463247f75a094efb6fdf2545aa1d772c15e",
"r": "d13c9048ed6f5d93c69f2670e33541c47e7a6773bae09dad6030e304eb5cd4c4"
},
"key": "021fb709e13f91ccf72365dfc93c39c2c16c0aac513a18f5a717dd4e798f238c"
}
],
"notes": [
{
"a_pk": "20d3ee586bccfa649b780f60b278505f2305c87a6f92083dfeca07cd7d924464",
"value": 0,
"rho": "c0184fb4bd55fed5b1d9f4eb238816a192bd724437d8a2a79d357ff25ceec824",
"r": "4cb7c8af6c342e3ccb543f54b835e050d01b4ee3dcd2696af619c5d37ac5618a"
},
{
"a_pk": "53115f3ed4b61487d17a53aff200524eafd81557eaf67a482bf29adb730e88c4",
"value": 0,
"rho": "20c50c50b6817652cdaf68df5d50bc6d94e3aaf73c272c39297909ce0feaad30",
"r": "5755ca435d9ecab5241a3c397bb2a6d9da5ce7c29f0baa4022be2096225c1de4"
}
],
"vpub_old": 0,
"vpub_new": 0
},
"hex": "0821a4b79971d66f5c32aaee4862c0e7dbf02349d94e0c1399b75a13b4dd198ad7c612c817793191a1e68652121876d6b3bde40f4fa52bc314145ce6e5cdd2594f63be3f04e86555ce0903be8bf3b6ab3979b54fba42e23cb9c74b495fe043b501c6afccb8d6ddfd6944ee34fd4f313bb6dc5d6ae36968bdf024d21cbbd29d32b9000000007d85863f30b911fc308a4ae6b184327996fddd3fed3ce8b3c23b7b4ae3cbe37700000000000000006f77d89f12b6ead91cfc2d810650e5a0d61be88018ddad9119cdd34336e21fc9986bafaa8e6af7a3da6c364307ffed45b2210d6c3cc4d05192622a34949d15040b5852ae184f4e6b29bb0c72c3af6c2f9424690361a0a05ae0860f0c069cafa20164d931c08f715ec3073cbc1178a3ba93c8099212537bc67f8acadd0e1419641400000000a3544b9d81c005c895bf9c466a5a764702fe9011889418de0e5895c3f834052c000000000000000053b1526f62991b34cf3414344cdd3463247f75a094efb6fdf2545aa1d772c15ed13c9048ed6f5d93c69f2670e33541c47e7a6773bae09dad6030e304eb5cd4c4021fb709e13f91ccf72365dfc93c39c2c16c0aac513a18f5a717dd4e798f238c20d3ee586bccfa649b780f60b278505f2305c87a6f92083dfeca07cd7d9244640000000000000000c0184fb4bd55fed5b1d9f4eb238816a192bd724437d8a2a79d357ff25ceec8244cb7c8af6c342e3ccb543f54b835e050d01b4ee3dcd2696af619c5d37ac5618a53115f3ed4b61487d17a53aff200524eafd81557eaf67a482bf29adb730e88c4000000000000000020c50c50b6817652cdaf68df5d50bc6d94e3aaf73c272c39297909ce0feaad305755ca435d9ecab5241a3c397bb2a6d9da5ce7c29f0baa4022be2096225c1de400000000000000000000000000000000"
},
{
"raw": {
"phi": "0c7dbe4dd2322b25ad0d769a30de42b6052b2e2491c1ab382d0a250cd93afc99",
"anchor": "d7c612c817793191a1e68652121876d6b3bde40f4fa52bc314145ce6e5cdd259",
"hSig": "4ad816325cfb94107e2f20a277494c783b427f8997b5c91045367faf7a0b0da9",
"inputs": [
{
"witness": "012b9768625c18122019a8aeaffddb2bb02623ad42bae0cbb48a636d2be3b1a73600000000",
"note": {
"a_pk": "142ccf78aebda099da086d21fb843d80fa18f6d3043da17f575172fdacfd67a1",
"value": 0,
"rho": "94f9c34e6668836609175c0c3d105571af4aea96976d9c5395278a2921c8d145",
"r": "d6d17f637820197b071ece0b3f91f7c9c290cc515b09055fdb1fef84d0a8c0bf"
},
"key": "00a60d314131af1d3a4a2febe8a330e7b72f0ba61a9cb6032638fbb43277ce8a"
},
{
"witness": "013af4e746a45de1e00458abd7a3eebd870c03eeff62284bba5d0d21ff41d8491e00000000",
"note": {
"a_pk": "079979d18dcf2a3ac587ff0c4dfc5b1267db6e705e53d929902ed5a4bb376736",
"value": 0,
"rho": "ddafb4091f65a38ebb58bb640a4e861fb66d43431b321370827ab5cd57c1aa23",
"r": "b97a433b48c4780a20a86d17d59ff9625d206ef450da1e1d9ab9536bd941e203"
},
"key": "0c6e376d6d417c76d0c38bf7bdf5a44feebe004bf8d1682b17cafd9d3d838497"
}
],
"notes": [
{
"a_pk": "fc3ced2e6a13649987bc4e34e2666b4a61bdb4845eb1c8c95792f66d414a5eea",
"value": 0,
"rho": "f7a55cbb2c2a9906c7edd47add1808f2ab1de7e3cdad3fdd5671d7834a347259",
"r": "f6e9dd659ce7b004a964fa4ea95a0cd3c7b8a302de87e1e87ba041580b1bc204"
},
{
"a_pk": "69c8951057caa7b9190cbcce9d1898564ad015caceb3bc8b73170fedca80555a",
"value": 0,
"rho": "d1937d7d8380812fbc7bea791a1819364d7713bd3f929a3924a9515bc6b89465",
"r": "d4e4568a4552c884230865725a89748902c40bd5f5a67cbdba41363794de1315"
}
],
"vpub_old": 0,
"vpub_new": 0
},
"hex": "0c7dbe4dd2322b25ad0d769a30de42b6052b2e2491c1ab382d0a250cd93afc99d7c612c817793191a1e68652121876d6b3bde40f4fa52bc314145ce6e5cdd2594ad816325cfb94107e2f20a277494c783b427f8997b5c91045367faf7a0b0da9012b9768625c18122019a8aeaffddb2bb02623ad42bae0cbb48a636d2be3b1a73600000000142ccf78aebda099da086d21fb843d80fa18f6d3043da17f575172fdacfd67a1000000000000000094f9c34e6668836609175c0c3d105571af4aea96976d9c5395278a2921c8d145d6d17f637820197b071ece0b3f91f7c9c290cc515b09055fdb1fef84d0a8c0bf00a60d314131af1d3a4a2febe8a330e7b72f0ba61a9cb6032638fbb43277ce8a013af4e746a45de1e00458abd7a3eebd870c03eeff62284bba5d0d21ff41d8491e00000000079979d18dcf2a3ac587ff0c4dfc5b1267db6e705e53d929902ed5a4bb3767360000000000000000ddafb4091f65a38ebb58bb640a4e861fb66d43431b321370827ab5cd57c1aa23b97a433b48c4780a20a86d17d59ff9625d206ef450da1e1d9ab9536bd941e2030c6e376d6d417c76d0c38bf7bdf5a44feebe004bf8d1682b17cafd9d3d838497fc3ced2e6a13649987bc4e34e2666b4a61bdb4845eb1c8c95792f66d414a5eea0000000000000000f7a55cbb2c2a9906c7edd47add1808f2ab1de7e3cdad3fdd5671d7834a347259f6e9dd659ce7b004a964fa4ea95a0cd3c7b8a302de87e1e87ba041580b1bc20469c8951057caa7b9190cbcce9d1898564ad015caceb3bc8b73170fedca80555a0000000000000000d1937d7d8380812fbc7bea791a1819364d7713bd3f929a3924a9515bc6b89465d4e4568a4552c884230865725a89748902c40bd5f5a67cbdba41363794de131500000000000000000000000000000000"
},
{
"raw": {
"phi": "0d0a648ec7372355cdeb579208aed6e3bf7e0de63e2a8e1b46bf87f248baa8ea",
"anchor": "d7c612c817793191a1e68652121876d6b3bde40f4fa52bc314145ce6e5cdd259",
"hSig": "065d68e4eb0814b6e4a1a7e43ef5f1ff9c2541dad7c55fa6f20d20097e2fbc34",
"inputs": [
{
"witness": "01977f7070d292c39dd373213e8319034ae63e9bbcf5c5fd2fa229fbade2a2b50300000000",
"note": {
"a_pk": "6f0a02aefa6664ec54a2b10bca40f210e2d7e624d8c5e236ab1d95dfdb4daa42",
"value": 0,
"rho": "3a6cb835826834a31471fccd50059f2eac27e3c352eb496668da16b7dd471b1c",
"r": "cbfa04eb3adc72d9a4721064bce7f5e283aac4611134ba42e44baae07017833f"
},
"key": "00b0da3dd30a10486d84efe9c6795e1feb17834c1494ceb4bcf87405c5877600"
},
{
"witness": "01d392fae5e5f067751ae2f84e815a7ca1a62d3939160327707d18a2bb3705eb5700000000",
"note": {
"a_pk": "52d865a631df718d813b6afb88d2048061719adc5066ccde17c68d288adb15fa",
"value": 0,
"rho": "caec424837f2e7f4a78d4be9371b718a4fa2818ab58a5f892a9dd44151305119",
"r": "58c4ce71dea83d517d3a28026a3fc20e823594e90547e34e32d95b5c76b56d56"
},
"key": "00eb969b13fb570a5023c9f2f5a5426263f5cda3180450dd247e164b7582abf5"
}
],
"notes": [
{
"a_pk": "585874b0f1d7bd6fa417c63e98f49971cba3d38c49c2f634d9f1d9ebf99cfd6e",
"value": 0,
"rho": "392a8d6758abc23e4105b77453758a95a13c28279cb34ad2a6ced686a1f05816",
"r": "e28498fa9986e3842d8faebe5cd2bdbf714b91c16e716c54d1a3810342de0b19"
},
{
"a_pk": "4d1e027a3a8b2599f706135fba9478a6edcbe7a1fd8a09b4599af2326af36d21",
"value": 0,
"rho": "7e91e4e6aa67f889375ebc2e473307e7ff0c337f02ae8f5af621f4634b772214",
"r": "dbc4f86c6aa86df023bf70d86660631d7dc24fdec68d45dd640add55f121b17b"
}
],
"vpub_old": 0,
"vpub_new": 0
},
"hex": "0d0a648ec7372355cdeb579208aed6e3bf7e0de63e2a8e1b46bf87f248baa8ead7c612c817793191a1e68652121876d6b3bde40f4fa52bc314145ce6e5cdd259065d68e4eb0814b6e4a1a7e43ef5f1ff9c2541dad7c55fa6f20d20097e2fbc3401977f7070d292c39dd373213e8319034ae63e9bbcf5c5fd2fa229fbade2a2b503000000006f0a02aefa6664ec54a2b10bca40f210e2d7e624d8c5e236ab1d95dfdb4daa4200000000000000003a6cb835826834a31471fccd50059f2eac27e3c352eb496668da16b7dd471b1ccbfa04eb3adc72d9a4721064bce7f5e283aac4611134ba42e44baae07017833f00b0da3dd30a10486d84efe9c6795e1feb17834c1494ceb4bcf87405c587760001d392fae5e5f067751ae2f84e815a7ca1a62d3939160327707d18a2bb3705eb570000000052d865a631df718d813b6afb88d2048061719adc5066ccde17c68d288adb15fa0000000000000000caec424837f2e7f4a78d4be9371b718a4fa2818ab58a5f892a9dd4415130511958c4ce71dea83d517d3a28026a3fc20e823594e90547e34e32d95b5c76b56d5600eb969b13fb570a5023c9f2f5a5426263f5cda3180450dd247e164b7582abf5585874b0f1d7bd6fa417c63e98f49971cba3d38c49c2f634d9f1d9ebf99cfd6e0000000000000000392a8d6758abc23e4105b77453758a95a13c28279cb34ad2a6ced686a1f05816e28498fa9986e3842d8faebe5cd2bdbf714b91c16e716c54d1a3810342de0b194d1e027a3a8b2599f706135fba9478a6edcbe7a1fd8a09b4599af2326af36d2100000000000000007e91e4e6aa67f889375ebc2e473307e7ff0c337f02ae8f5af621f4634b772214dbc4f86c6aa86df023bf70d86660631d7dc24fdec68d45dd640add55f121b17b00000000000000000000000000000000"
},
{
"raw": {
"phi": "01f4e3dfd4e35a5a597bb68e1d4659aa40cdf7e9b4d6bce299bcb6efaa2afeea",
"anchor": "d7c612c817793191a1e68652121876d6b3bde40f4fa52bc314145ce6e5cdd259",
"hSig": "a6ea90e941a1a2583d3207dcda9adf41ce7de6019b49a40ef0472de4e34ad881",
"inputs": [
{
"witness": "01381e8b11a0611c7c28bdf0ed30d5383a94fe30ce38c6ef8dd23a1d85216fbfb700000000",
"note": {
"a_pk": "12db749049f760203a770fddf6e80729e7736d263613438cde9764fb660972c3",
"value": 0,
"rho": "5edcc18ec561878cea4e68b97c67f2ae3203b18d96838264e8ce217f5d6610fa",
"r": "3d0ad949feb5a75f24ba6d58d8716a4d406ebcdd2349f0d057a1d309bf4f0a2b"
},
"key": "010f16110d9a93f4e987033f7cb85715c7719dc5d53c572f4f67cd9d5e1fe847"
},
{
"witness": "011b9dbce37a1f6a90f710a6c71ee718a0d9043e422214a536e832987e235ba60c00000000",
"note": {
"a_pk": "b7c799b08b6afceb7bc397142146fcc443bc3e6733cf09c7aaa9caf35e103ea3",
"value": 0,
"rho": "5afbb0cc79687c6eb6912931e4fd4e22b51d9f9847207b7800c07ab6f0be9dd4",
"r": "e59634d762c2145f4787ba2dadff938fb5905c8f1c0514f56db274e620d1a5e7"
},
"key": "0ffe822d661c5bedccd12a0fd4c16dfdaaf67cd4a21a1b04deadd41181b82bbb"
}
],
"notes": [
{
"a_pk": "8b83998109b346fa45a5a735465888402d5c9bed982cb9bf95af11e365e256ac",
"value": 0,
"rho": "a17d9e69852133a097f7a9800ab1e172993aae96e85ef7a774e05d006c5401a3",
"r": "b9cd93580296cce5210cbaa903cfa4523f9a487376630ca4f14a90faffc33734"
},
{
"a_pk": "532f776a85a176947724d9e0cec7d34a71f3bf394c24033a4acda49adab4ffc7",
"value": 0,
"rho": "4893a0a21fbbd9d7a2ddb1c87de9d410c05657f18a77c18108e4cd8831257f56",
"r": "0778a5516340b11118dfd61d53d6dca72a828b4716781ca9687a60b1dcd40405"
}
],
"vpub_old": 0,
"vpub_new": 0
},
"hex": "01f4e3dfd4e35a5a597bb68e1d4659aa40cdf7e9b4d6bce299bcb6efaa2afeead7c612c817793191a1e68652121876d6b3bde40f4fa52bc314145ce6e5cdd259a6ea90e941a1a2583d3207dcda9adf41ce7de6019b49a40ef0472de4e34ad88101381e8b11a0611c7c28bdf0ed30d5383a94fe30ce38c6ef8dd23a1d85216fbfb70000000012db749049f760203a770fddf6e80729e7736d263613438cde9764fb660972c300000000000000005edcc18ec561878cea4e68b97c67f2ae3203b18d96838264e8ce217f5d6610fa3d0ad949feb5a75f24ba6d58d8716a4d406ebcdd2349f0d057a1d309bf4f0a2b010f16110d9a93f4e987033f7cb85715c7719dc5d53c572f4f67cd9d5e1fe847011b9dbce37a1f6a90f710a6c71ee718a0d9043e422214a536e832987e235ba60c00000000b7c799b08b6afceb7bc397142146fcc443bc3e6733cf09c7aaa9caf35e103ea300000000000000005afbb0cc79687c6eb6912931e4fd4e22b51d9f9847207b7800c07ab6f0be9dd4e59634d762c2145f4787ba2dadff938fb5905c8f1c0514f56db274e620d1a5e70ffe822d661c5bedccd12a0fd4c16dfdaaf67cd4a21a1b04deadd41181b82bbb8b83998109b346fa45a5a735465888402d5c9bed982cb9bf95af11e365e256ac0000000000000000a17d9e69852133a097f7a9800ab1e172993aae96e85ef7a774e05d006c5401a3b9cd93580296cce5210cbaa903cfa4523f9a487376630ca4f14a90faffc33734532f776a85a176947724d9e0cec7d34a71f3bf394c24033a4acda49adab4ffc700000000000000004893a0a21fbbd9d7a2ddb1c87de9d410c05657f18a77c18108e4cd8831257f560778a5516340b11118dfd61d53d6dca72a828b4716781ca9687a60b1dcd4040500000000000000000000000000000000"
},
{
"raw": {
"phi": "03fb6a5ca0679f5cf070364f46277ffdef3ba1c31ee837ae6a7b395a15269890",
"anchor": "d7c612c817793191a1e68652121876d6b3bde40f4fa52bc314145ce6e5cdd259",
"hSig": "0e11db074d3af0aca06bf4bc7875f8f849f344cf72f7fe34fdf6ae5742d83f83",
"inputs": [
{
"witness": "01ed6ce7fb34bd756cfe27d2ff4e45a8d85db47795347ec1a2116573eeccdcc38800000000",
"note": {
"a_pk": "9733afbfb6b7d56da19b43af4ef1ef0c9b0766a8d0d7574a4a477bf6aa301b7b",
"value": 0,
"rho": "f2a506f9f5f49f7878f14f4bd9b9e45e50500f9b7445fcb0100d030acb59d4f7",
"r": "5cdf75c862c1cc01d5a60f8f1008387feeecc81e6f02b90d8ed6bf1e22dc7007"
},
"key": "0bd24836f1d6d562cf3f1415f9d6cee17023d4dbb9e784f2ab5521f5727782fc"
},
{
"witness": "016ab05aece4c6c121d4581f892a8fcb93edf7b85886fae4251004be66e7c7e0ed00000000",
"note": {
"a_pk": "336683d7b004676f7d0e5a6867eddc325589d1dd45e2bf5c3461313b07662090",
"value": 0,
"rho": "26bfc3ef01683121f9eb6d7fcf52d2028022bc6d018f22c4cb2d8390333eb19a",
"r": "43a26361212959f787b91a95b072826c5bd70bcb9fb52f86dcf9aad0addadc87"
},
"key": "0452a218d5b15bcac5905133ae714325482f9fbe4b7da7c5fd70c7aa06bde952"
}
],
"notes": [
{
"a_pk": "63ef5198f2827ba4036d49beee6d7fb4007a74f2b5fc4b49dbf6917d4bd16395",
"value": 0,
"rho": "e1b20c36b7aa72a3e8fb8e0122208594df8224ea2169d03e0718c62d6467e398",
"r": "a6024f9d2adf3f623a8e2a5e7887d24ba4631037f2a7c0d5a6ed457c9b151538"
},
{
"a_pk": "361f300cf3f45065a623f178415dda857c0ab344913753f8469517d040597313",
"value": 0,
"rho": "bfedc03329eb135c58fceb445c3b4b0f23944d1f418ba6475e7fdc5261ab9ba1",
"r": "06e661811e4ab6e8846a6e07ef4f0a64134691de2d0d4429e01ae6a225f90b50"
}
],
"vpub_old": 0,
"vpub_new": 0
},
"hex": "03fb6a5ca0679f5cf070364f46277ffdef3ba1c31ee837ae6a7b395a15269890d7c612c817793191a1e68652121876d6b3bde40f4fa52bc314145ce6e5cdd2590e11db074d3af0aca06bf4bc7875f8f849f344cf72f7fe34fdf6ae5742d83f8301ed6ce7fb34bd756cfe27d2ff4e45a8d85db47795347ec1a2116573eeccdcc388000000009733afbfb6b7d56da19b43af4ef1ef0c9b0766a8d0d7574a4a477bf6aa301b7b0000000000000000f2a506f9f5f49f7878f14f4bd9b9e45e50500f9b7445fcb0100d030acb59d4f75cdf75c862c1cc01d5a60f8f1008387feeecc81e6f02b90d8ed6bf1e22dc70070bd24836f1d6d562cf3f1415f9d6cee17023d4dbb9e784f2ab5521f5727782fc016ab05aece4c6c121d4581f892a8fcb93edf7b85886fae4251004be66e7c7e0ed00000000336683d7b004676f7d0e5a6867eddc325589d1dd45e2bf5c3461313b07662090000000000000000026bfc3ef01683121f9eb6d7fcf52d2028022bc6d018f22c4cb2d8390333eb19a43a26361212959f787b91a95b072826c5bd70bcb9fb52f86dcf9aad0addadc870452a218d5b15bcac5905133ae714325482f9fbe4b7da7c5fd70c7aa06bde95263ef5198f2827ba4036d49beee6d7fb4007a74f2b5fc4b49dbf6917d4bd163950000000000000000e1b20c36b7aa72a3e8fb8e0122208594df8224ea2169d03e0718c62d6467e398a6024f9d2adf3f623a8e2a5e7887d24ba4631037f2a7c0d5a6ed457c9b151538361f300cf3f45065a623f178415dda857c0ab344913753f8469517d0405973130000000000000000bfedc03329eb135c58fceb445c3b4b0f23944d1f418ba6475e7fdc5261ab9ba106e661811e4ab6e8846a6e07ef4f0a64134691de2d0d4429e01ae6a225f90b5000000000000000000000000000000000"
}
],
"invalid": {
"fromBufferStrict": [
{
"exception": "JSProofWitness has unexpected data",
"hex": "0821a4b79971d66f5c32aaee4862c0e7dbf02349d94e0c1399b75a13b4dd198ad7c612c817793191a1e68652121876d6b3bde40f4fa52bc314145ce6e5cdd2594f63be3f04e86555ce0903be8bf3b6ab3979b54fba42e23cb9c74b495fe043b501c6afccb8d6ddfd6944ee34fd4f313bb6dc5d6ae36968bdf024d21cbbd29d32b9000000007d85863f30b911fc308a4ae6b184327996fddd3fed3ce8b3c23b7b4ae3cbe37700000000000000006f77d89f12b6ead91cfc2d810650e5a0d61be88018ddad9119cdd34336e21fc9986bafaa8e6af7a3da6c364307ffed45b2210d6c3cc4d05192622a34949d15040b5852ae184f4e6b29bb0c72c3af6c2f9424690361a0a05ae0860f0c069cafa20164d931c08f715ec3073cbc1178a3ba93c8099212537bc67f8acadd0e1419641400000000a3544b9d81c005c895bf9c466a5a764702fe9011889418de0e5895c3f834052c000000000000000053b1526f62991b34cf3414344cdd3463247f75a094efb6fdf2545aa1d772c15ed13c9048ed6f5d93c69f2670e33541c47e7a6773bae09dad6030e304eb5cd4c4021fb709e13f91ccf72365dfc93c39c2c16c0aac513a18f5a717dd4e798f238c20d3ee586bccfa649b780f60b278505f2305c87a6f92083dfeca07cd7d9244640000000000000000c0184fb4bd55fed5b1d9f4eb238816a192bd724437d8a2a79d357ff25ceec8244cb7c8af6c342e3ccb543f54b835e050d01b4ee3dcd2696af619c5d37ac5618a53115f3ed4b61487d17a53aff200524eafd81557eaf67a482bf29adb730e88c4000000000000000020c50c50b6817652cdaf68df5d50bc6d94e3aaf73c272c39297909ce0feaad305755ca435d9ecab5241a3c397bb2a6d9da5ce7c29f0baa4022be2096225c1de400000000000000000000000000000000ffffffff"
}
]
}
}

View File

@ -6,6 +6,7 @@ var JSDescription = require('../src/jsdescription')
var ZCProof = require('../src/proof')
var fixtures = require('./fixtures/jsdescription')
var hSigFixtures = require('./fixtures/hsig')
describe('JSDescription', function () {
function fromRaw (raw) {
@ -90,4 +91,20 @@ describe('JSDescription', function () {
})
})
})
describe('hSig', function () {
hSigFixtures.valid.forEach(function (f) {
it('equals ' + f.hex, function () {
var jsdesc = new JSDescription()
jsdesc.randomSeed = [].reverse.call(Buffer.from(f.randomSeed, 'hex'))
f.nullifiers.forEach(function (nullifier) {
jsdesc.nullifiers.push([].reverse.call(Buffer.from(nullifier, 'hex')))
})
var actual = jsdesc.h_sig([].reverse.call(Buffer.from(f.pubKeyHash, 'hex')))
var expected = [].reverse.call(Buffer.from(f.hex, 'hex'))
assert.strictEqual(Buffer.from(actual).toString('hex'), expected.toString('hex'))
})
})
})
})

34
test/proof_witness.js Normal file
View File

@ -0,0 +1,34 @@
/* global describe, it */
'use strict'
var assert = require('assert')
var JSProofWitness = require('../src/proof_witness')
var fixtures = require('./fixtures/proof_witness')
describe('JSProofWitness', function () {
describe('fromBuffer/fromHex', function () {
fixtures.valid.forEach(function (f, i) {
it('imports random proof witness ' + i, function () {
var actual = JSProofWitness.fromHex(f.hex)
assert.strictEqual(actual.toHex(), f.hex, actual.toHex())
})
})
fixtures.invalid.fromBufferStrict.forEach(function (f) {
it('throws on ' + f.exception, function () {
assert.throws(function () {
JSProofWitness.fromHex(f.hex)
}, new RegExp(f.exception))
})
it('passes with __noStrict = true on ' + f.exception, function () {
assert.doesNotThrow(function () {
JSProofWitness.fromBuffer(Buffer.from(f.hex, 'hex'), true)
}, new RegExp(f.exception))
})
})
})
})