From 3ea8aec0074ef04f197429d6b54a43a295b4e60f Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Sun, 11 Mar 2018 18:16:46 -0700 Subject: [PATCH] hsk: use blake2 for addr hashes. --- lib/node/rpc.js | 11 +++++++---- lib/primitives/address.js | 4 ++-- lib/primitives/keyring.js | 8 ++++---- lib/protocol/consensus.js | 12 ++++++------ lib/script/script.js | 16 ++++++++-------- lib/wallet/rpc.js | 3 +-- lib/wallet/wallet.js | 14 ++++++-------- scripts/gen.js | 2 -- test/chain-test.js | 4 ++-- test/tx-test.js | 6 +++--- 10 files changed, 39 insertions(+), 41 deletions(-) diff --git a/lib/node/rpc.js b/lib/node/rpc.js index 7cecd3d2..35cb741b 100644 --- a/lib/node/rpc.js +++ b/lib/node/rpc.js @@ -11,7 +11,6 @@ const bweb = require('bweb'); const {Lock} = require('bmutex'); const IP = require('binet'); const Validator = require('bval'); -const hash160 = require('bcrypto/lib/hash160'); const blake2b = require('bcrypto/lib/blake2b'); const ccmp = require('bcrypto/lib/ccmp'); const secp256k1 = require('bcrypto/lib/secp256k1'); @@ -1811,7 +1810,7 @@ class RPC extends RPCBase { if (data) script.fromRaw(data); - const addr = Address.fromScripthash(script.hash256()); + const addr = Address.fromScripthash(script.blake256()); const json = this.scriptToJSON(script); json.p2sh = addr.toString(this.network); @@ -2028,7 +2027,7 @@ class RPC extends RPCBase { 'Redeem script exceeds size limit.'); } - const addr = Address.fromScripthash(script.hash256()); + const addr = Address.fromScripthash(script.blake256()); return { address: addr.toString(this.network), @@ -2075,6 +2074,10 @@ class RPC extends RPCBase { throw new RPCError(errs.TYPE_ERROR, 'Invalid parameters.'); const addr = parseAddress(b58, this.network); + + if (addr.version !== 0 || addr.hash.length !== 20) + return false; + const msg = Buffer.from(MAGIC_STRING + str, 'utf8'); const hash = blake2b.digest(msg); @@ -2083,7 +2086,7 @@ class RPC extends RPCBase { if (!key) return false; - return ccmp(hash160.digest(key), addr.hash); + return ccmp(blake2b.digest(key, 20), addr.hash); } async signMessageWithPrivkey(args, help) { diff --git a/lib/primitives/address.js b/lib/primitives/address.js index af259973..d5510edd 100644 --- a/lib/primitives/address.js +++ b/lib/primitives/address.js @@ -9,7 +9,7 @@ const assert = require('assert'); const bio = require('bufio'); const {bech32} = require('bstring'); -const hash160 = require('bcrypto/lib/hash160'); +const blake2b = require('bcrypto/lib/blake2b'); const hash256 = require('bcrypto/lib/hash256'); const Network = require('../protocol/network'); const consensus = require('../protocol/consensus'); @@ -287,7 +287,7 @@ class Address { // We're pretty much screwed here // since we can't get the version. if (pk) { - this.hash = hash160.digest(pk); + this.hash = blake2b.digest(pk, 20); this.version = 0; return this; } diff --git a/lib/primitives/keyring.js b/lib/primitives/keyring.js index d5df581c..c6240b7e 100644 --- a/lib/primitives/keyring.js +++ b/lib/primitives/keyring.js @@ -9,7 +9,7 @@ const assert = require('assert'); const {base58} = require('bstring'); const bio = require('bufio'); -const hash160 = require('bcrypto/lib/hash160'); +const blake2b = require('bcrypto/lib/blake2b'); const hash256 = require('bcrypto/lib/hash256'); const Network = require('../protocol/network'); const Script = require('../script/script'); @@ -338,7 +338,7 @@ class KeyRing { } /** - * Get ripemd160 scripthash. + * Get scripthash. * @param {String?} enc - `"hex"` or `null`. * @returns {Buffer} */ @@ -348,7 +348,7 @@ class KeyRing { return null; if (!this._scriptHash) - this._scriptHash = this.script.hash256(); + this._scriptHash = this.script.blake256(); return enc === 'hex' ? this._scriptHash.toString('hex') @@ -385,7 +385,7 @@ class KeyRing { getKeyHash(enc) { if (!this._keyHash) - this._keyHash = hash160.digest(this.publicKey); + this._keyHash = blake2b.digest(this.publicKey, 20); return enc === 'hex' ? this._keyHash.toString('hex') diff --git a/lib/protocol/consensus.js b/lib/protocol/consensus.js index 5cba9489..2257307d 100644 --- a/lib/protocol/consensus.js +++ b/lib/protocol/consensus.js @@ -119,7 +119,7 @@ exports.GENESIS_REWARD = exports.BASE_REWARD + ((8.84 * exports.COIN) | 0); */ exports.INVESTORS_KEY = - Buffer.from('0000000000000000000000000000000000000000', 'hex'); + Buffer.from('f6a62ea45dbd8332cd6f1330cc63acb7027cb957', 'hex'); /** * Foundation key. @@ -127,7 +127,7 @@ exports.INVESTORS_KEY = */ exports.FOUNDATION_KEY = - Buffer.from('0000000000000000000000000000000000000000', 'hex'); + Buffer.from('07a2d3616e20d9eb807c2e0769fbc2719c5e5947', 'hex'); /** * Foundation hot key. @@ -135,7 +135,7 @@ exports.FOUNDATION_KEY = */ exports.FOUNDATION_HOT = - Buffer.from('0000000000000000000000000000000000000000', 'hex'); + Buffer.from('061f6309ddb5a2eba07b5b3100f990c89d01bd6c', 'hex'); /** * Creators key. @@ -143,7 +143,7 @@ exports.FOUNDATION_HOT = */ exports.CREATORS_KEY = - Buffer.from('0000000000000000000000000000000000000000', 'hex'); + Buffer.from('407543a192cf0cdebab29015d79920d27cac3c03', 'hex'); /** * Airdrop key. @@ -151,7 +151,7 @@ exports.CREATORS_KEY = */ exports.AIRDROP_KEY = - Buffer.from('0000000000000000000000000000000000000000', 'hex'); + Buffer.from('79dbb7e1336d3c2bd1bfc634e7f42ad1835759d2', 'hex'); /** * Genesis key. @@ -159,7 +159,7 @@ exports.AIRDROP_KEY = */ exports.GENESIS_KEY = - Buffer.from('197a438a75ceee7e58a03ebab3eabf9afd8080c2', 'hex'); + Buffer.from('f0237ae2e8f860f7d79124fc513f012e5aaa8d23', 'hex'); /** * Maximum block base size (consensus). diff --git a/lib/script/script.js b/lib/script/script.js index f8d7b9a0..9f029aca 100644 --- a/lib/script/script.js +++ b/lib/script/script.js @@ -1379,7 +1379,7 @@ class Script { this.raw = Buffer.allocUnsafe(25); this.raw[0] = opcodes.OP_DUP; - this.raw[1] = opcodes.OP_HASH160; + this.raw[1] = opcodes.OP_BLAKE160; this.raw[2] = 0x14; hash.copy(this.raw, 3); this.raw[23] = opcodes.OP_EQUALVERIFY; @@ -1389,7 +1389,7 @@ class Script { this.code.length = 0; this.code.push(Opcode.fromOp(opcodes.OP_DUP)); - this.code.push(Opcode.fromOp(opcodes.OP_HASH160)); + this.code.push(Opcode.fromOp(opcodes.OP_BLAKE160)); this.code.push(Opcode.fromPush(hash)); this.code.push(Opcode.fromOp(opcodes.OP_EQUALVERIFY)); this.code.push(Opcode.fromOp(opcodes.OP_CHECKSIG)); @@ -1519,13 +1519,13 @@ class Script { } /** - * Get the hash256 of the raw script. + * Get the blake2b of the raw script. * @param {String?} enc * @returns {Hash} */ - hash256(enc) { - let hash = hash256.digest(this.toRaw()); + blake256(enc) { + let hash = blake2b.digest(this.toRaw()); if (enc === 'hex') hash = hash.toString('hex'); return hash; @@ -1578,7 +1578,7 @@ class Script { if (minimal || this.raw.length === 25) { return this.raw.length === 25 && this.raw[0] === opcodes.OP_DUP - && this.raw[1] === opcodes.OP_HASH160 + && this.raw[1] === opcodes.OP_BLAKE160 && this.raw[2] === 0x14 && this.raw[23] === opcodes.OP_EQUALVERIFY && this.raw[24] === opcodes.OP_CHECKSIG; @@ -1588,7 +1588,7 @@ class Script { return false; return this.getOp(0) === opcodes.OP_DUP - && this.getOp(1) === opcodes.OP_HASH160 + && this.getOp(1) === opcodes.OP_BLAKE160 && this.getLength(2) === 20 && this.getOp(3) === opcodes.OP_EQUALVERIFY && this.getOp(4) === opcodes.OP_CHECKSIG; @@ -2291,7 +2291,7 @@ class Script { const witnessScript = stack.pop(); - if (!hash256.digest(witnessScript).equals(addr.hash)) + if (!blake2b.digest(witnessScript).equals(addr.hash)) throw new ScriptError('WITNESS_PROGRAM_MISMATCH'); redeem = Script.fromRaw(witnessScript); diff --git a/lib/wallet/rpc.js b/lib/wallet/rpc.js index e70533b8..2005e05d 100644 --- a/lib/wallet/rpc.js +++ b/lib/wallet/rpc.js @@ -796,9 +796,8 @@ class RPC extends RPCBase { throw new RPCError(errs.TYPE_ERROR, 'Invalid parameters.'); script = Script.fromRaw(script); - script = Script.fromScripthash(script.hash160()); - addr = script.getAddress(); + addr = Address.fromScripthash(script.blake256()); } else { addr = parseAddress(addr, this.network); } diff --git a/lib/wallet/wallet.js b/lib/wallet/wallet.js index 91aa4db8..bfe36c2e 100644 --- a/lib/wallet/wallet.js +++ b/lib/wallet/wallet.js @@ -11,8 +11,7 @@ const EventEmitter = require('events'); const {Lock} = require('bmutex'); const {base58} = require('bstring'); const bio = require('bufio'); -const hash160 = require('bcrypto/lib/hash160'); -const hash256 = require('bcrypto/lib/hash256'); +const blake2b = require('bcrypto/lib/blake2b'); const cleanse = require('bcrypto/lib/cleanse'); const random = require('bcrypto/lib/random'); const TXDB = require('./txdb'); @@ -494,7 +493,7 @@ class Wallet extends EventEmitter { /** * Generate the wallet ID if none was passed in. - * It is represented as HASH160(m/44->public|magic) + * It is represented as BLAKE2b(m/44->public|magic, 20) * converted to an "address" with a prefix * of `0x03be04` (`WLT` in base58). * @private @@ -510,21 +509,20 @@ class Wallet extends EventEmitter { bw.writeBytes(key.publicKey); bw.writeU32(this.network.magic); - const hash = hash160.digest(bw.render()); + const hash = blake2b.digest(bw.render(), 20); - const b58 = bio.write(27); + const b58 = bio.write(23); b58.writeU8(0x03); b58.writeU8(0xbe); b58.writeU8(0x04); b58.writeBytes(hash); - b58.writeChecksum(hash256.digest); return base58.encode(b58.render()); } /** * Generate the wallet api key if none was passed in. - * It is represented as HASH256(m/44'->private|nonce). + * It is represented as BLAKE2b(m/44'->private|nonce). * @private * @param {HDPrivateKey} master * @param {Number} nonce @@ -541,7 +539,7 @@ class Wallet extends EventEmitter { bw.writeBytes(key.privateKey); bw.writeU32(nonce); - return hash256.digest(bw.render()); + return blake2b.digest(bw.render()); } /** diff --git a/scripts/gen.js b/scripts/gen.js index 46a3b8c7..f17fc573 100644 --- a/scripts/gen.js +++ b/scripts/gen.js @@ -2,8 +2,6 @@ const fs = require('bfile'); const Path = require('path'); -const secp256k1 = require('bcrypto/lib/secp256k1'); -const hash160 = require('bcrypto/lib/hash160'); const consensus = require('../lib/protocol/consensus'); const Network = require('../lib/protocol/network'); const TX = require('../lib/primitives/tx'); diff --git a/test/chain-test.js b/test/chain-test.js index 0f824468..fec7e58d 100644 --- a/test/chain-test.js +++ b/test/chain-test.js @@ -853,7 +853,7 @@ describe('Chain', function() { redeem.compile(); - const script = Script.fromScripthash(redeem.hash160()); + const addr = Address.fromScripthash(redeem.blake256()); for (let i = 0; i < 111; i++) { const block = await cpu.mineBlock(); @@ -864,7 +864,7 @@ describe('Chain', function() { for (let j = 0; j < Math.min(100, val); j++) { const output = new Output(); - output.script = script.clone(); + output.address = addr; output.value = 1; cb.outputs.push(output); diff --git a/test/tx-test.js b/test/tx-test.js index 6fd2eb3a..19621072 100644 --- a/test/tx-test.js +++ b/test/tx-test.js @@ -644,7 +644,7 @@ describe('TX', function() { const pub = key.publicKey; const redeem = Script.fromMultisig(1, 2, [pub, pub]); - const output = Script.fromScripthash(redeem.hash160()); + const output = Address.fromScripthash(redeem.blake256()); const input = new Script([ Opcode.fromInt(0), @@ -727,7 +727,7 @@ describe('TX', function() { const pub = key.publicKey; const redeem = Script.fromMultisig(1, 2, [pub, pub]); - const output = Script.fromProgram(0, redeem.sha256()); + const output = Script.fromProgram(0, redeem.blake256()); const input = new Script(); @@ -751,7 +751,7 @@ describe('TX', function() { const pub = key.publicKey; const wscript = Script.fromMultisig(1, 2, [pub, pub]); - const redeem = Script.fromProgram(0, wscript.sha256()); + const redeem = Script.fromProgram(0, wscript.blake256()); const output = Script.fromScripthash(redeem.hash160()); const input = new Script([