diff --git a/integration_tests/helpers/baseNodeProcess.js b/integration_tests/helpers/baseNodeProcess.js index f10b2f5cd3..059dd81b14 100644 --- a/integration_tests/helpers/baseNodeProcess.js +++ b/integration_tests/helpers/baseNodeProcess.js @@ -144,7 +144,6 @@ class BaseNodeProcess { } let overrides = this.excludeTestEnvars ? {} : this.getOverrides(); - console.error(overrides); // clear the .env file fs.writeFileSync(`${this.baseDir}/.overrides`, ""); diff --git a/integration_tests/helpers/domainHasher.js b/integration_tests/helpers/domainHasher.js new file mode 100644 index 0000000000..cb2d40ddb9 --- /dev/null +++ b/integration_tests/helpers/domainHasher.js @@ -0,0 +1,46 @@ +/* + * // Copyright 2022. The Tari Project + * // + * // Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + * // following conditions are met: + * // + * // 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following + * // disclaimer. + * // + * // 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the + * // following disclaimer in the documentation and/or other materials provided with the distribution. + * // + * // 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote + * // products derived from this software without specific prior written permission. + * // + * // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +const { blake2bInit, blake2bUpdate, blake2bFinal } = require("blakejs"); +const { toLittleEndian } = require("./util"); +class DomainHasher { + constructor(label, output_len = 32, key = null) { + this.hasher = blake2bInit(output_len, key); + this.chain(Buffer.from(label, "utf-8")); + } + + chain(value) { + let buf = Buffer.from(value); + let le = toLittleEndian(buf.length, 64); + blake2bUpdate(this.hasher, le); + blake2bUpdate(this.hasher, buf); + return this; + } + + finalize() { + return blake2bFinal(this.hasher); + } +} + +module.exports = DomainHasher; diff --git a/integration_tests/helpers/transactionBuilder.js b/integration_tests/helpers/transactionBuilder.js index 431afda319..7fb1f8f865 100644 --- a/integration_tests/helpers/transactionBuilder.js +++ b/integration_tests/helpers/transactionBuilder.js @@ -1,13 +1,14 @@ // Copyright 2022 The Tari Project // SPDX-License-Identifier: BSD-3-Clause -var tari_crypto = require("tari_crypto"); -var { blake2bInit, blake2bUpdate, blake2bFinal } = require("blakejs"); +const tari_crypto = require("tari_crypto"); +const { blake2bInit, blake2bUpdate, blake2bFinal } = require("blakejs"); const { toLittleEndian, littleEndianHexStringToBigEndianHexString, combineTwoTariKeys, } = require("../helpers/util"); +const DomainHasher = require("../helpers/domainHasher"); const { OutputType } = require("./types"); class TransactionBuilder { @@ -78,6 +79,9 @@ class TransactionBuilder { } toLengthEncoded(buf) { + if (buf.length > 127) { + throw new Error("toLengthEncoded: Buffer too long"); + } // TODO: varint encoding, this is only valid up to len=127 return Buffer.concat([Buffer.from([buf.length]), buf]); } @@ -91,23 +95,24 @@ class TransactionBuilder { covenant, encryptedValue ) { - const KEY = null; // optional key - const OUTPUT_LENGTH = 32; // bytes - const context = blake2bInit(OUTPUT_LENGTH, KEY); const buf_nonce = Buffer.from(publicNonce, "hex"); const script_offset_public_key = Buffer.from(scriptOffsetPublicKey, "hex"); const features_buffer = this.featuresToConsensusBytes(features); // base_layer/core/src/transactions/transaction/transaction_output.rs - blake2bUpdate(context, buf_nonce); - blake2bUpdate(context, this.toLengthEncoded(script)); - blake2bUpdate(context, features_buffer); - blake2bUpdate(context, script_offset_public_key); - blake2bUpdate(context, commitment); - blake2bUpdate(context, this.toLengthEncoded(covenant)); - blake2bUpdate(context, encryptedValue); - const final = blake2bFinal(context); - return Buffer.from(final).toString("hex"); + let hash = new DomainHasher( + "com.tari.base_layer.core.transactions.v0.metadata_signature" + ) + .chain(buf_nonce) + .chain(this.toLengthEncoded(script)) + .chain(features_buffer) + .chain(script_offset_public_key) + .chain(commitment) + .chain(this.toLengthEncoded(covenant)) + .chain(encryptedValue) + .finalize(); + + return Buffer.from(hash).toString("hex"); } buildScriptChallenge( @@ -117,18 +122,19 @@ class TransactionBuilder { public_key, commitment ) { - let KEY = null; // optional key - let OUTPUT_LENGTH = 32; // bytes - let context = blake2bInit(OUTPUT_LENGTH, KEY); let buff_publicNonce = Buffer.from(publicNonce, "hex"); let buff_public_key = Buffer.from(public_key, "hex"); - blake2bUpdate(context, buff_publicNonce); - blake2bUpdate(context, this.toLengthEncoded(script)); - blake2bUpdate(context, this.toLengthEncoded(input_data)); - blake2bUpdate(context, buff_public_key); - blake2bUpdate(context, commitment); - let final = blake2bFinal(context); - return Buffer.from(final).toString("hex"); + let hash = new DomainHasher( + "com.tari.base_layer.core.transactions.v0.script_challenge" + ) + .chain(buff_publicNonce) + .chain(this.toLengthEncoded(script)) + .chain(this.toLengthEncoded(input_data)) + .chain(buff_public_key) + .chain(commitment) + .finalize(); + + return Buffer.from(hash).toString("hex"); } hashOutput(features, commitment, script, sender_offset_public_key) { diff --git a/integration_tests/helpers/util.js b/integration_tests/helpers/util.js index 46605eed6b..17a58dfada 100644 --- a/integration_tests/helpers/util.js +++ b/integration_tests/helpers/util.js @@ -176,6 +176,11 @@ function toLittleEndian(n, numBits) { buf.writeUInt32LE(n); return buf; } + case 64: { + let buf = Buffer.alloc(numBits / 8); + buf.writeUInt64LE(n); + return buf; + } default: { const s = toLittleEndianInner(n);