def check_defined_hashtype_signature(sig): # IsDefinedHashtypeSignature if len(sig) == 0: raise ScriptError("signature is length 0") hash_type = indexbytes(sig, -1) & (~SIGHASH_ANYONECANPAY) if hash_type < SIGHASH_ALL or hash_type > SIGHASH_SINGLE: raise ScriptError("bad hash type after signature", errno.SIG_HASHTYPE)
def eval_instruction(self): all_if_true = self.conditional_stack.all_if_true() # don't actually check for minimal data unless data will be pushed onto the stack verify_minimal_data = self.flags & VERIFY_MINIMALDATA and all_if_true opcode, data, pc, is_ok = self.ScriptStreamer.get_opcode( self.script, self.pc, verify_minimal_data=verify_minimal_data) if not is_ok: raise ScriptError("malformed data", errno.BAD_OPCODE) if data and len(data) > self.MAX_BLOB_LENGTH: raise ScriptError("pushing too much data onto stack", errno.PUSH_SIZE) if data is None: self.op_count += 1 self.check_stack_size() f = self.INSTRUCTION_LOOKUP[opcode] if self.traceback_f: f = self.traceback_f(opcode, data, pc, self) or f if data is not None and all_if_true: self.stack.append(data) self.pc = pc if all_if_true or getattr(f, "outside_conditional", False): f(self) if self.op_count > self.MAX_OP_COUNT: raise ScriptError("script contains too many operations", errno.OP_COUNT)
def _check_valid_signature_1(sig): ls = len(sig) if ls < 9 or ls > 73: raise ScriptError("bad signature size", errno.SIG_DER) if sig[0] != 0x30: raise ScriptError("bad signature byte 0", errno.SIG_DER) if sig[1] != ls - 3: raise ScriptError("signature size wrong", errno.SIG_DER) r_len = sig[3] if 5 + r_len >= ls: raise ScriptError("r length exceed signature size", errno.SIG_DER)
def f(vm): stack = vm.stack conditional_stack = vm.conditional_stack the_bool = False if conditional_stack.all_if_true(): if len(stack) < 1: raise ScriptError("IF with no condition", errno.UNBALANCED_CONDITIONAL) item = vm.pop() if vm.flags & VERIFY_MINIMALIF: if item not in (vm.VM_FALSE, vm.VM_TRUE): raise ScriptError("non-minimal IF", errno.MINIMALIF) the_bool = vm.bool_from_script_bytes(item) vm.conditional_stack.OP_IF(the_bool, reverse_bool=reverse_bool)
def _check_sequence_verify(sequence, tx_context_sequence): # this mask is applied to extract lock-time from the sequence field SEQUENCE_LOCKTIME_MASK = 0xffff mask = SEQUENCE_LOCKTIME_TYPE_FLAG | SEQUENCE_LOCKTIME_MASK sequence_masked = sequence & mask tx_sequence_masked = tx_context_sequence & mask if not (((tx_sequence_masked < SEQUENCE_LOCKTIME_TYPE_FLAG) and (sequence_masked < SEQUENCE_LOCKTIME_TYPE_FLAG)) or ((tx_sequence_masked >= SEQUENCE_LOCKTIME_TYPE_FLAG) and (sequence_masked >= SEQUENCE_LOCKTIME_TYPE_FLAG))): raise ScriptError("sequence numbers not comparable") if sequence_masked > tx_sequence_masked: raise ScriptError("sequence number too small")
def checksigs(vm, sig_blobs, public_pair_blobs): sig_blobs_remaining = list(sig_blobs) flags = vm.flags sighash_cache = {} verify_witness_pubkeytype = flags & VERIFY_WITNESS_PUBKEYTYPE verify_strict = not not (flags & VERIFY_STRICTENC) any_nonblank = (flags & VERIFY_NULLFAIL) and any(len(s) > 0 for s in sig_blobs) while len(sig_blobs_remaining) > 0: sig_blob = sig_blobs_remaining.pop() try: sig_pair, signature_type = parse_and_check_signature_blob(sig_blob, flags, vm) except (der.UnexpectedDER, ValueError): public_pair_blobs = [] while len(sig_blobs_remaining) < len(public_pair_blobs): pair_blob = public_pair_blobs.pop() if checksig(vm, sig_pair, signature_type, pair_blob, sig_blobs, sighash_cache, verify_witness_pubkeytype, verify_strict): break else: if any_nonblank: raise ScriptError("bad signature not NULL", errno.NULLFAIL) vm.append(vm.VM_FALSE) return vm.append(vm.VM_TRUE)
def decode_OP_PUSHDATA(script, pc): pc += 1 try: size = struct.unpack(struct_data, script[pc:pc + struct_size])[0] except Exception: raise ScriptError("unexpected end of data when size expected", errno.BAD_OPCODE) pc += struct_size return size, pc
def check_public_key_encoding(blob): lb = len(blob) if lb >= 33: fb = byte2int(blob) if fb == 4: if lb == 65: return elif fb in (2, 3): if lb == 33: return raise ScriptError("invalid public key blob", errno.PUBKEYTYPE)
def do_OP_CHECKSEQUENCEVERIFY(vm): if not (vm.flags & VERIFY_CHECKSEQUENCEVERIFY): if (vm.flags & VERIFY_DISCOURAGE_UPGRADABLE_NOPS): raise ScriptError("discouraging nops", errno.DISCOURAGE_UPGRADABLE_NOPS) return if len(vm.stack) < 1: raise ScriptError("empty stack on CHECKSEQUENCEVERIFY", errno.INVALID_STACK_OPERATION) if len(vm.stack[-1]) > 5: raise ScriptError("script number overflow", errno.INVALID_STACK_OPERATION + 1) sequence = vm.pop_int() vm.push_int(sequence) if sequence < 0: raise ScriptError("top stack item negative on CHECKSEQUENCEVERIFY", errno.NEGATIVE_LOCKTIME) if sequence & SEQUENCE_LOCKTIME_DISABLE_FLAG: return # do the actual check if vm.tx_context.version < 2: raise ScriptError("CHECKSEQUENCEVERIFY: bad tx version", errno.UNSATISFIED_LOCKTIME) if vm.tx_context.sequence & SEQUENCE_LOCKTIME_DISABLE_FLAG: raise ScriptError("CHECKSEQUENCEVERIFY: locktime disabled") _check_sequence_verify(sequence, vm.tx_context.sequence)
def do_OP_CHECKMULTISIG(vm): key_count = vm.pop_int() if key_count < 0 or key_count > 20: raise ScriptError("key_count not in range 0 to 20", errno.PUBKEY_COUNT) public_pair_blobs = [vm.pop() for _ in range(key_count)] public_pair_blobs.reverse() signature_count = vm.pop_int() if signature_count < 0 or signature_count > key_count: raise ScriptError( "invalid number of signatures: %d for %d keys" % (signature_count, key_count), errno.SIG_COUNT) sig_blobs = [vm.pop() for _ in range(signature_count)] sig_blobs.reverse() # check that we have the required hack 00 byte hack_byte = vm.pop() if vm.flags & VERIFY_NULLDUMMY and hack_byte != b'': raise ScriptError("bad dummy byte in checkmultisig", errno.SIG_NULLDUMMY) checksigs(vm, sig_blobs, public_pair_blobs) vm.op_count += key_count
def eval_script(self): if len(self.script) > self.MAX_SCRIPT_LENGTH: raise ScriptError("script too long", errno.SCRIPT_SIZE) f = getattr(self.traceback_f, "prelaunch", None) if f: f(self) while self.pc < len(self.script): self.eval_instruction() f = getattr(self.traceback_f, "postscript", None) if f: f(self) self.post_script_check() return self.stack
def _check_valid_signature_2(sig): ls = len(sig) r_len = sig[3] s_len = sig[5 + r_len] if r_len + s_len + 7 != ls: raise ScriptError("r and s size exceed signature size", errno.SIG_DER) if sig[2] != 2: raise ScriptError("R value region does not start with 0x02", errno.SIG_DER) if r_len == 0: raise ScriptError("zero-length R value", errno.SIG_DER) if sig[4] & 0x80: raise ScriptError("sig R value not allowed to be negative", errno.SIG_DER) if r_len > 1 and sig[4] == 0 and not (sig[5] & 0x80): raise ScriptError( "R value can't have leading 0 byte unless doing so would make it negative", errno.SIG_DER) if sig[r_len + 4] != 2: raise ScriptError("S value region does not start with 0x02", errno.SIG_DER) if s_len == 0: raise ScriptError("zero-length S value", errno.SIG_DER) if sig[r_len + 6] & 0x80: raise ScriptError("negative S values not allowed", errno.SIG_DER) if s_len > 1 and sig[r_len + 6] == 0 and not (sig[r_len + 7] & 0x80): raise ScriptError( "S value can't have leading 0 byte unless doing so would make it negative", errno.SIG_DER)
def int_from_script_bytes(class_, s, require_minimal=False): if len(s) == 0: return 0 s = bytearray(s) s.reverse() i = s[0] v = i & 0x7f if require_minimal: if v == 0: if len(s) <= 1 or ((s[1] & 0x80) == 0): raise ScriptError("non-minimally encoded", errno.UNKNOWN_ERROR) is_negative = ((i & 0x80) > 0) for b in s[1:]: v <<= 8 v += b if is_negative: v = -v return v
def checksig(vm, sig_pair, signature_type, pair_blob, blobs_to_delete, sighash_cache, verify_witness_pubkeytype, verify_strict): generator = vm.generator_for_signature_type(signature_type) if verify_strict: check_public_key_encoding(pair_blob) if verify_witness_pubkeytype: if byte2int(pair_blob) not in (2, 3) or len(pair_blob) != 33: raise ScriptError("uncompressed key in witness", errno.WITNESS_PUBKEYTYPE) try: public_pair = sec_to_public_pair(pair_blob, generator, strict=verify_strict) except (ValueError, EncodingError): return False if signature_type not in sighash_cache: sighash_cache[signature_type] = vm.signature_for_hash_type_f(signature_type, blobs_to_delete, vm) try: if generator.verify(public_pair, sighash_cache[signature_type], sig_pair): return True except ValueError: pass return False
def do_OP_CHECKLOCKTIMEVERIFY(vm): if not (vm.flags & VERIFY_CHECKLOCKTIMEVERIFY): if (vm.flags & VERIFY_DISCOURAGE_UPGRADABLE_NOPS): raise ScriptError("discouraging nops", errno.DISCOURAGE_UPGRADABLE_NOPS) return if vm.tx_context.sequence == 0xffffffff: raise ScriptError("nSequence equal to 0xffffffff") if len(vm.stack) < 1: raise ScriptError("empty stack on CHECKLOCKTIMEVERIFY") if len(vm.stack[-1]) > 5: raise ScriptError("script number overflow") max_lock_time = vm.pop_int() vm.push_int(max_lock_time) if max_lock_time < 0: raise ScriptError("top stack item negative on CHECKLOCKTIMEVERIFY") era_max = (max_lock_time >= 500000000) era_lock_time = (vm.tx_context.lock_time >= 500000000) if era_max != era_lock_time: raise ScriptError("eras differ in CHECKLOCKTIMEVERIFY") if max_lock_time > vm.tx_context.lock_time: raise ScriptError("nLockTime too soon")
def discourage_nops(vm): if (vm.flags & VERIFY_DISCOURAGE_UPGRADABLE_NOPS): raise ScriptError("discouraging nops", errno.DISCOURAGE_UPGRADABLE_NOPS)
def do_OP_FROMALTSTACK(vm): if len(vm.altstack) < 1: raise ScriptError("alt stack empty", errno.INVALID_ALTSTACK_OPERATION) vm.append(vm.altstack.pop())
def do_OP_RESERVED(vm): if vm.conditional_stack.all_if_true(): raise ScriptError("OP_RESERVED encountered", errno.BAD_OPCODE) vm.op_count -= 1
def bad_opcode(vm): raise ScriptError("invalid opcode %s at %d" % (opcode, vm.pc - 1), err)
def do_OP_VER(stack): raise ScriptError("OP_VER encountered", errno.BAD_OPCODE)
def non_minimal_f(msg): raise ScriptError(msg, errno.MINIMALDATA)
def do_OP_VERIFY(vm): v = vm.bool_from_script_bytes(vm.pop()) if not v: raise ScriptError("VERIFY failed", errno.VERIFY)
def pop_check_bounds(vm): if len(vm[-1]) > 4: raise ScriptError("overflow in binop", errno.UNKNOWN_ERROR) return vm.pop_int()
def do_OP_RETURN(stack): raise ScriptError("OP_RETURN encountered", errno.OP_RETURN)
def check_low_der_signature(sig_pair, generator): # IsLowDERSignature r, s = sig_pair hi_s = generator.p() - s if hi_s < s: raise ScriptError("signature has high S value", errno.SIG_HIGH_S)
def end_of_data_f(msg): raise ScriptError(msg, errno.BAD_OPCODE)
def do_OP_CHECKMULTISIGVERIFY(vm): do_OP_CHECKMULTISIG(vm) v = vm.bool_from_script_bytes(vm.pop()) if not v: raise ScriptError("VERIFY failed", errno.VERIFY)
def pop_nonnegative(self): v = self.pop_int() if v < 0: raise ScriptError("unexpectedly got negative value", errno.INVALID_STACK_OPERATION) return v
def bool_from_script_bytes(class_, v, require_minimal=False): v = class_.IntStreamer.int_from_script_bytes(v, require_minimal=require_minimal) if require_minimal: if v not in (class_.VM_FALSE, class_.VM_TRUE): raise ScriptError("non-minimally encoded", errno.UNKNOWN_ERROR) return bool(v)
def do_OP_RESERVED2(stack): raise ScriptError("OP_RESERVED2 encountered", errno.BAD_OPCODE)