예제 #1
0
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
예제 #2
0
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')
예제 #3
0
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
예제 #4
0
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')
예제 #5
0
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:]
예제 #6
0
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