script: remove mast.
This commit is contained in:
parent
163e89fc29
commit
9b269dd1f0
@ -766,15 +766,6 @@ class Address {
|
|||||||
return this.version === 0 && this.hash.length === 32;
|
return this.version === 0 && this.hash.length === 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether the address is witness masthash.
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
isWitnessMasthash() {
|
|
||||||
return this.version === 1 && this.hash.length === 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the address is a witness program.
|
* Test whether the address is a witness program.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
|
|||||||
@ -346,8 +346,7 @@ exports.flags = {
|
|||||||
VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM: 1 << 12,
|
VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM: 1 << 12,
|
||||||
VERIFY_MINIMALIF: 1 << 13,
|
VERIFY_MINIMALIF: 1 << 13,
|
||||||
VERIFY_NULLFAIL: 1 << 14,
|
VERIFY_NULLFAIL: 1 << 14,
|
||||||
VERIFY_WITNESS_PUBKEYTYPE: 1 << 15,
|
VERIFY_WITNESS_PUBKEYTYPE: 1 << 15
|
||||||
VERIFY_MAST: 1 << 16
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -448,8 +447,7 @@ exports.types = {
|
|||||||
NULLDATA: 5,
|
NULLDATA: 5,
|
||||||
WITNESSMALFORMED: 0x80,
|
WITNESSMALFORMED: 0x80,
|
||||||
WITNESSSCRIPTHASH: 0x81,
|
WITNESSSCRIPTHASH: 0x81,
|
||||||
WITNESSPUBKEYHASH: 0x82,
|
WITNESSPUBKEYHASH: 0x82
|
||||||
WITNESSMASTHASH: 0x83
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -466,8 +464,7 @@ exports.typesByVal = {
|
|||||||
5: 'NULLDATA',
|
5: 'NULLDATA',
|
||||||
0x80: 'WITNESSMALFORMED',
|
0x80: 'WITNESSMALFORMED',
|
||||||
0x81: 'WITNESSSCRIPTHASH',
|
0x81: 'WITNESSSCRIPTHASH',
|
||||||
0x82: 'WITNESSPUBKEYHASH',
|
0x82: 'WITNESSPUBKEYHASH'
|
||||||
0x83: 'WITNESSMASTHASH'
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -54,14 +54,6 @@ class Program {
|
|||||||
return scriptTypes.WITNESSMALFORMED;
|
return scriptTypes.WITNESSMALFORMED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.version === 1) {
|
|
||||||
if (this.data.length === 32)
|
|
||||||
return scriptTypes.WITNESSMASTHASH;
|
|
||||||
|
|
||||||
// Fail on bad version=1
|
|
||||||
return scriptTypes.WITNESSMALFORMED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No interpretation of script (anyone can spend)
|
// No interpretation of script (anyone can spend)
|
||||||
return scriptTypes.NONSTANDARD;
|
return scriptTypes.NONSTANDARD;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1724,9 +1724,6 @@ class Script {
|
|||||||
if (this.isWitnessScripthash())
|
if (this.isWitnessScripthash())
|
||||||
return scriptTypes.WITNESSSCRIPTHASH;
|
return scriptTypes.WITNESSSCRIPTHASH;
|
||||||
|
|
||||||
if (this.isWitnessMasthash())
|
|
||||||
return scriptTypes.WITNESSMASTHASH;
|
|
||||||
|
|
||||||
if (this.isMultisig())
|
if (this.isMultisig())
|
||||||
return scriptTypes.MULTISIG;
|
return scriptTypes.MULTISIG;
|
||||||
|
|
||||||
@ -2187,30 +2184,6 @@ class Script {
|
|||||||
return this.getData(1);
|
return this.getData(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether the output script
|
|
||||||
* is a pay-to-mast program.
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
isWitnessMasthash() {
|
|
||||||
return this.raw.length === 34
|
|
||||||
&& this.raw[0] === opcodes.OP_1
|
|
||||||
&& this.raw[1] === 0x20;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get P2WMH hash if present.
|
|
||||||
* @returns {Buffer|null}
|
|
||||||
*/
|
|
||||||
|
|
||||||
getWitnessMasthash() {
|
|
||||||
if (!this.isWitnessMasthash())
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return this.getData(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the output script is unspendable.
|
* Test whether the output script is unspendable.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
@ -3256,9 +3229,6 @@ class Script {
|
|||||||
// Failure on version=0 (bad program data length).
|
// Failure on version=0 (bad program data length).
|
||||||
throw new ScriptError('WITNESS_PROGRAM_WRONG_LENGTH');
|
throw new ScriptError('WITNESS_PROGRAM_WRONG_LENGTH');
|
||||||
}
|
}
|
||||||
} else if ((flags & Script.flags.VERIFY_MAST) && program.version === 1) {
|
|
||||||
Script.verifyMast(program, stack, output, flags, tx, index);
|
|
||||||
return;
|
|
||||||
} else {
|
} else {
|
||||||
// Anyone can spend (we can return true here
|
// Anyone can spend (we can return true here
|
||||||
// if we want to always relay these transactions).
|
// if we want to always relay these transactions).
|
||||||
@ -3286,138 +3256,6 @@ class Script {
|
|||||||
throw new ScriptError('EVAL_FALSE');
|
throw new ScriptError('EVAL_FALSE');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Verify a MAST witness program.
|
|
||||||
* @param {Program} program
|
|
||||||
* @param {Stack} stack
|
|
||||||
* @param {Script} output
|
|
||||||
* @param {VerifyFlags} flags
|
|
||||||
* @param {TX} tx
|
|
||||||
* @param {Number} index
|
|
||||||
* @param {Amount} value
|
|
||||||
* @throws {ScriptError}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static verifyMast(program, stack, output, flags, tx, index, value) {
|
|
||||||
assert(program.version === 1);
|
|
||||||
assert((flags & Script.flags.VERIFY_MAST) !== 0);
|
|
||||||
|
|
||||||
if (stack.length < 4)
|
|
||||||
throw new ScriptError('INVALID_MAST_STACK');
|
|
||||||
|
|
||||||
const metadata = stack.get(-1);
|
|
||||||
if (metadata.length < 1 || metadata.length > 5)
|
|
||||||
throw new ScriptError('INVALID_MAST_STACK');
|
|
||||||
|
|
||||||
const subscripts = metadata[0];
|
|
||||||
if (subscripts === 0 || stack.length < subscripts + 3)
|
|
||||||
throw new ScriptError('INVALID_MAST_STACK');
|
|
||||||
|
|
||||||
let ops = subscripts;
|
|
||||||
let scriptRoot = bio.write();
|
|
||||||
scriptRoot.writeU8(subscripts);
|
|
||||||
|
|
||||||
if (metadata[metadata.length - 1] === 0x00)
|
|
||||||
throw new ScriptError('INVALID_MAST_STACK');
|
|
||||||
|
|
||||||
let version = 0;
|
|
||||||
|
|
||||||
for (let j = 1; j < metadata.length; j++)
|
|
||||||
version |= metadata[j] << 8 * (j - 1);
|
|
||||||
|
|
||||||
if (version < 0)
|
|
||||||
version += 0x100000000;
|
|
||||||
|
|
||||||
if (version > 0) {
|
|
||||||
if (flags & Script.flags.DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)
|
|
||||||
throw new ScriptError('DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM');
|
|
||||||
}
|
|
||||||
|
|
||||||
let mastRoot = bio.write();
|
|
||||||
mastRoot.writeU32(version);
|
|
||||||
|
|
||||||
const pathdata = stack.get(-2);
|
|
||||||
|
|
||||||
if (pathdata.length & 0x1f)
|
|
||||||
throw new ScriptError('INVALID_MAST_STACK');
|
|
||||||
|
|
||||||
const depth = pathdata.length >>> 5;
|
|
||||||
|
|
||||||
if (depth > 32)
|
|
||||||
throw new ScriptError('INVALID_MAST_STACK');
|
|
||||||
|
|
||||||
ops += depth;
|
|
||||||
if (version === 0) {
|
|
||||||
if (ops > consensus.MAX_SCRIPT_OPS)
|
|
||||||
throw new ScriptError('OP_COUNT');
|
|
||||||
}
|
|
||||||
|
|
||||||
const path = [];
|
|
||||||
|
|
||||||
for (let j = 0; j < depth; j++)
|
|
||||||
path.push(pathdata.slice(j * 32, j * 32 + 32));
|
|
||||||
|
|
||||||
const posdata = stack.get(-3);
|
|
||||||
|
|
||||||
if (posdata.length > 4)
|
|
||||||
throw new ScriptError('INVALID_MAST_STACK');
|
|
||||||
|
|
||||||
let pos = 0;
|
|
||||||
if (posdata.length > 0) {
|
|
||||||
if (posdata[posdata.length - 1] === 0x00)
|
|
||||||
throw new ScriptError('INVALID_MAST_STACK');
|
|
||||||
|
|
||||||
for (let j = 0; j < posdata.length; j++)
|
|
||||||
pos |= posdata[j] << 8 * j;
|
|
||||||
|
|
||||||
if (pos < 0)
|
|
||||||
pos += 0x100000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depth < 32) {
|
|
||||||
if (pos >= ((1 << depth) >>> 0))
|
|
||||||
throw new ScriptError('INVALID_MAST_STACK');
|
|
||||||
}
|
|
||||||
|
|
||||||
let scripts = bio.write();
|
|
||||||
scripts.writeBytes(output.raw);
|
|
||||||
|
|
||||||
for (let j = 0; j < subscripts; j++) {
|
|
||||||
const script = stack.get(-(4 + j));
|
|
||||||
if (version === 0) {
|
|
||||||
if ((scripts.offset + script.length) > consensus.MAX_SCRIPT_SIZE)
|
|
||||||
throw new ScriptError('SCRIPT_SIZE');
|
|
||||||
}
|
|
||||||
scriptRoot.writeBytes(hash256.digest(script));
|
|
||||||
scripts.writeBytes(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptRoot = hash256.digest(scriptRoot.render());
|
|
||||||
scriptRoot = merkle.verifyBranch(scriptRoot, path, pos);
|
|
||||||
|
|
||||||
mastRoot.writeBytes(scriptRoot);
|
|
||||||
mastRoot = hash256.digest(mastRoot.render());
|
|
||||||
|
|
||||||
if (!mastRoot.equals(program.data))
|
|
||||||
throw new ScriptError('WITNESS_PROGRAM_MISMATCH');
|
|
||||||
|
|
||||||
if (version === 0) {
|
|
||||||
stack.length -= 3 + subscripts;
|
|
||||||
|
|
||||||
for (let j = 0; j < stack.length; j++) {
|
|
||||||
if (stack.get(j).length > consensus.MAX_SCRIPT_PUSH)
|
|
||||||
throw new ScriptError('PUSH_SIZE');
|
|
||||||
}
|
|
||||||
|
|
||||||
scripts = scripts.render();
|
|
||||||
output = Script.fromRaw(scripts);
|
|
||||||
output.execute(stack, flags, tx, index, value, 1);
|
|
||||||
|
|
||||||
if (stack.length !== 0)
|
|
||||||
throw new ScriptError('EVAL_FALSE');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from buffer reader.
|
* Inject properties from buffer reader.
|
||||||
* @private
|
* @private
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user