Fix transaction signing

This commit is contained in:
Sky Young 2019-07-19 11:44:37 -06:00
parent 5a300e785f
commit 84aabe20a9
3 changed files with 21 additions and 36 deletions

View File

@ -439,10 +439,11 @@ class TX {
* @param {Amount} value - Previous output value. * @param {Amount} value - Previous output value.
* @param {SighashType} type - Sighash type. * @param {SighashType} type - Sighash type.
* @param {Number} version - Sighash version (0=legacy, 1=segwit). * @param {Number} version - Sighash version (0=legacy, 1=segwit).
* @param {Boolean} [includeFloData=true] - Should floData be included in the signature Hash
* @returns {Buffer} Signature hash. * @returns {Buffer} Signature hash.
*/ */
signatureHash(index, prev, value, type, version) { signatureHash(index, prev, value, type, version, includeFloData = true) {
assert(index >= 0 && index < this.inputs.length); assert(index >= 0 && index < this.inputs.length);
assert(prev instanceof Script); assert(prev instanceof Script);
assert(typeof value === 'number'); assert(typeof value === 'number');
@ -450,11 +451,11 @@ class TX {
// Traditional sighashing // Traditional sighashing
if (version === 0) if (version === 0)
return this.signatureHashV0(index, prev, type); return this.signatureHashV0(index, prev, type, includeFloData);
// Segwit sighashing // Segwit sighashing
if (version === 1) if (version === 1)
return this.signatureHashV1(index, prev, value, type); return this.signatureHashV1(index, prev, value, type, includeFloData);
throw new Error('Unknown sighash version.'); throw new Error('Unknown sighash version.');
} }
@ -465,10 +466,11 @@ class TX {
* @param {Number} index * @param {Number} index
* @param {Script} prev * @param {Script} prev
* @param {SighashType} type * @param {SighashType} type
* @param {Boolean} [includeFloData=true] - Should floData be included in the signature Hash
* @returns {Buffer} * @returns {Buffer}
*/ */
signatureHashV0(index, prev, type) { signatureHashV0(index, prev, type, includeFloData = true) {
if ((type & 0x1f) === hashType.SINGLE) { if ((type & 0x1f) === hashType.SINGLE) {
// Bitcoind used to return 1 as an error code: // Bitcoind used to return 1 as an error code:
// it ended up being treated like a hash. // it ended up being treated like a hash.
@ -483,7 +485,7 @@ class TX {
prev = prev.removeSeparators(); prev = prev.removeSeparators();
// Calculate buffer size. // Calculate buffer size.
const size = this.hashSize(index, prev, type); const size = this.hashSize(index, prev, type, includeFloData);
const bw = bio.pool(size); const bw = bio.pool(size);
bw.writeU32(this.version); bw.writeU32(this.version);
@ -574,14 +576,10 @@ class TX {
bw.writeU32(this.locktime); bw.writeU32(this.locktime);
var fOmitTxComment = !!(type & hashType.OMIT_TX_COMMENT); if (this.version >= 2 && includeFloData) {
if (this.version >= 2 && !fOmitTxComment) {
bw.writeVarBytes(Buffer.from(this.strFloData)); bw.writeVarBytes(Buffer.from(this.strFloData));
} }
type &= ~hashType.OMIT_TX_COMMENT;
// Append the hash type. // Append the hash type.
bw.writeU32(type); bw.writeU32(type);
@ -597,7 +595,7 @@ class TX {
* @returns {Number} * @returns {Number}
*/ */
hashSize(index, prev, type) { hashSize(index, prev, type, includeFloData = true) {
let size = 0; let size = 0;
size += 4; size += 4;
@ -631,17 +629,11 @@ class TX {
break; break;
} }
var fOmitTxComment = !!(type & hashType.OMIT_TX_COMMENT); if (includeFloData){
if (!fOmitTxComment){
let bufferLength = Buffer.from(this.strFloData).length; let bufferLength = Buffer.from(this.strFloData).length;
if (this.strFloData.length > 0){ size += encoding.sizeVarint(bufferLength);
size += encoding.sizeVarint(bufferLength); size += bufferLength
size += bufferLength
} else {
size += encoding.sizeVarint(0);
}
} }
size += 8; size += 8;
@ -656,10 +648,11 @@ class TX {
* @param {Script} prev * @param {Script} prev
* @param {Amount} value * @param {Amount} value
* @param {SighashType} type * @param {SighashType} type
* @param {Boolean} [includeFloData=true] - Should floData be included in the signature Hash
* @returns {Buffer} * @returns {Buffer}
*/ */
signatureHashV1(index, prev, value, type) { signatureHashV1(index, prev, value, type, includeFloData = true) {
const input = this.inputs[index]; const input = this.inputs[index];
let prevouts = consensus.ZERO_HASH; let prevouts = consensus.ZERO_HASH;
let sequences = consensus.ZERO_HASH; let sequences = consensus.ZERO_HASH;
@ -741,13 +734,10 @@ class TX {
bw.writeU32(this.locktime); bw.writeU32(this.locktime);
// Add the FloData to the transaction // Add the FloData to the transaction
if (this.version >= 2 && !fOmitTxComment) { if (this.version >= 2 && includeFloData) {
bw.writeVarBytes(Buffer.from(this.strFloData)); bw.writeVarBytes(Buffer.from(this.strFloData));
} }
// Remove the OMIT_TX_COMMENT flag if included
type &= ~hashType.OMIT_TX_COMMENT;
bw.writeU32(type); bw.writeU32(type);
return hash256.digest(bw.render()); return hash256.digest(bw.render());
@ -770,15 +760,12 @@ class TX {
let type = sig[sig.length - 1]; let type = sig[sig.length - 1];
let signature = sig.slice(0, -1); let signature = sig.slice(0, -1);
let hash = this.signatureHash(index, prev, value, type, version); let hash = this.signatureHash(index, prev, value, type, version, true);
if (secp256k1.verifyDER(hash, signature, key)){ if (secp256k1.verifyDER(hash, signature, key)){
return true; return true;
} else { } else {
type ^= hashType.OMIT_TX_COMMENT; hash = this.signatureHash(index, prev, value, type, version, false);
hash = this.signatureHash(index, prev, value, type, version);
return secp256k1.verifyDER(hash, signature, key); return secp256k1.verifyDER(hash, signature, key);
} }
} }
@ -803,7 +790,7 @@ class TX {
if (version == null) if (version == null)
version = 0; version = 0;
const hash = this.signatureHash(index, prev, value, type, version); const hash = this.signatureHash(index, prev, value, type, version, true);
const sig = secp256k1.signDER(hash, key); const sig = secp256k1.signDER(hash, key);
const bw = bio.write(sig.length + 1); const bw = bio.write(sig.length + 1);

View File

@ -1135,19 +1135,17 @@ class Script {
let hash; let hash;
try { try {
hash = tx.signatureHash(index, subscript, value, type, version); hash = tx.signatureHash(index, subscript, value, type, version, true);
res = checksig(hash, sig, key); res = checksig(hash, sig, key);
} catch (e) { } catch (e) {
// Having issues with signatures? Log this error then! // Having issues with signatures? Log this error then!
} }
if (!res){ if (!res){
type ^= Script.hashType.OMIT_TX_COMMENT;
try { try {
hash = tx.signatureHash(index, subscript, value, type, version); hash = tx.signatureHash(index, subscript, value, type, version, false);
res = checksig(hash, sig, key); res = checksig(hash, sig, key);
} catch (e) { } catch (e) {
// Having issues with signatures? Log this error then!
throw new ScriptError('CHECKSIGVERIFY_ERROR', e) throw new ScriptError('CHECKSIGVERIFY_ERROR', e)
} }
} }

View File

@ -68,7 +68,7 @@ const errs = {
WALLET_ALREADY_UNLOCKED: -17 WALLET_ALREADY_UNLOCKED: -17
}; };
const MAGIC_STRING = 'Bitcoin Signed Message:\n'; const MAGIC_STRING = 'Florincoin Signed Message:\n';
/** /**
* Wallet RPC * Wallet RPC