def get_asm(scriptpubkey): try: asm = [] for op in scriptpubkey: if type(op) == bitcoinlib.core.script.CScriptOp: asm.append(str(op)) else: asm.append(op) except bitcoinlib.core.script.CScriptTruncatedPushDataError: raise exceptions.DecodeError('invalid pushdata due to truncation') if not asm: raise exceptions.DecodeError('empty output') return asm
def get_checksig(asm): if len(asm) == 5 and asm[0] == 'OP_DUP' and asm[1] == 'OP_HASH160' and asm[ 3] == 'OP_EQUALVERIFY' and asm[4] == 'OP_CHECKSIG': pubkeyhash = asm[2] if type(pubkeyhash) == bytes: return pubkeyhash raise exceptions.DecodeError('invalid OP_CHECKSIG')
def decode_p2sh_input(asm, p2sh_is_segwit=False): ''' Looks at the scriptSig for the input of the p2sh-encoded data transaction [signature] [data] [OP_HASH160 ... OP_EQUAL] ''' pubkey, source, redeem_script_is_valid, found_data = decode_data_redeem_script( asm[-1], p2sh_is_segwit) if redeem_script_is_valid: # this is a signed transaction, so we got {sig[,sig]} {datachunk} {redeemScript} datachunk = found_data redeemScript = asm[-1] #asm[-2:] else: #print('ASM:', len(asm)) pubkey, source, redeem_script_is_valid, found_data = decode_data_redeem_script( asm[-1], p2sh_is_segwit) if not redeem_script_is_valid or len(asm) != 3: return None, None, None # this is an unsigned transaction (last is outputScript), so we got [datachunk] [redeemScript] [temporaryOutputScript] datachunk, redeemScript, _substituteScript = asm data = datachunk if data[:len(config.PREFIX)] == config.PREFIX: data = data[len(config.PREFIX):] else: if data == b'': return source, None, None raise exceptions.DecodeError('unrecognised P2SH output') return source, None, data
def get_checkmultisig(asm): # N‐of‐2 if len(asm) == 5 and asm[3] == 2 and asm[4] == 'OP_CHECKMULTISIG': pubkeys, signatures_required = asm[1:3], asm[0] if all([type(pubkey) == bytes for pubkey in pubkeys]): return pubkeys, signatures_required # N‐of‐3 if len(asm) == 6 and asm[4] == 3 and asm[5] == 'OP_CHECKMULTISIG': pubkeys, signatures_required = asm[1:4], asm[0] if all([type(pubkey) == bytes for pubkey in pubkeys]): return pubkeys, signatures_required raise exceptions.DecodeError('invalid OP_CHECKMULTISIG')
def _decode_decodeLUT(data): (numAddresses, ) = struct.unpack('>H', data[0:2]) if numAddresses == 0: raise exceptions.DecodeError('address list can\'t be empty') p = 2 addressList = [] bytesPerAddress = 21 for i in range(0, numAddresses): addr_raw = data[p:p + bytesPerAddress] addressList.append(address.unpack(addr_raw)) p += bytesPerAddress lutNbits = math.ceil(math.log2(numAddresses)) return addressList, lutNbits, data[p:]
def get_asm(scriptpubkey): # TODO: When is an exception thrown here? Can this `try` block be tighter? Can it be replaced by a conditional? try: asm = [] # TODO: This should be `for element in scriptpubkey`. for op in scriptpubkey: if type(op) == bitcoinlib.core.script.CScriptOp: # TODO: `op = element` asm.append(str(op)) else: # TODO: `data = element` (?) asm.append(op) except bitcoinlib.core.script.CScriptTruncatedPushDataError: raise exceptions.PushDataDecodeError('invalid pushdata due to truncation') if not asm: raise exceptions.DecodeError('empty output') return asm