Esempio n. 1
0
 def serialize_segwit(self):
     '''Returns the byte serialization of the transaction'''
     # serialize version (4 bytes, little endian)
     result = int_to_little_endian(self.version, 4)
     # segwit marker '0001'
     result += b'\x00\x01'
     # encode_varint on the number of inputs
     result += encode_varint(len(self.tx_ins))
     # iterate inputs
     for tx_in in self.tx_ins:
         # serialize each input
         result += tx_in.serialize()
     # encode_varint on the number of inputs
     result += encode_varint(len(self.tx_outs))
     # iterate outputs
     for tx_out in self.tx_outs:
         # serialize each output
         result += tx_out.serialize()
     # add the witness data
     for tx_in in self.tx_ins:
         result += tx_in.witness_program
     # serialize locktime (4 bytes, little endian)
     result += int_to_little_endian(self.locktime, 4)
     return result
Esempio n. 2
0
 def test_exercise_3(self):
     hex_tx = '0100000001868278ed6ddfb6c1ed3ad5f8181eb0c7a385aa0836f01d5e4789e6bd304d87221a000000db00483045022100dc92655fe37036f47756db8102e0d7d5e28b3beb83a8fef4f5dc0559bddfb94e02205a36d4e4e6c7fcd16658c50783e00c341609977aed3ad00937bf4ee942a8993701483045022100da6bee3c93766232079a01639d07fa869598749729ae323eab8eef53577d611b02207bef15429dcadce2121ea07f233115c6f09034c0be68db99980b9a6c5e75402201475221022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152aeffffffff04d3b11400000000001976a914904a49878c0adfc3aa05de7afad2cc15f483a56a88ac7f400900000000001976a914418327e3f3dda4cf5b9089325a4b95abdfa0334088ac722c0c00000000001976a914ba35042cfe9fc66fd35ac2224eebdafd1028ad2788acdc4ace020000000017a91474d691da1574e6b3c192ecfb52cc8984ee7b6c568700000000'
     hex_sec = '03b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb71'
     hex_der = '3045022100da6bee3c93766232079a01639d07fa869598749729ae323eab8eef53577d611b02207bef15429dcadce2121ea07f233115c6f09034c0be68db99980b9a6c5e754022'
     hex_redeem_script = '475221022626e955ea6ea6d98850c994f9107b036b1334f18ca8830bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4bb7152ae'
     sec = bytes.fromhex(hex_sec)
     der = bytes.fromhex(hex_der)
     redeem_script = Script.parse(BytesIO(bytes.fromhex(hex_redeem_script)))
     stream = BytesIO(bytes.fromhex(hex_tx))
     tx_obj = Tx.parse(stream)
     s = int_to_little_endian(tx_obj.version, 4)
     s += encode_varint(len(tx_obj.tx_ins))
     i = tx_obj.tx_ins[0]
     s += TxIn(i.prev_tx, i.prev_index, redeem_script,
               i.sequence).serialize()
     s += encode_varint(len(tx_obj.tx_outs))
     for tx_out in tx_obj.tx_outs:
         s += tx_out.serialize()
     s += int_to_little_endian(tx_obj.locktime, 4)
     s += int_to_little_endian(SIGHASH_ALL, 4)
     z = int.from_bytes(hash256(s), 'big')
     point = S256Point.parse(sec)
     sig = Signature.parse(der)
     self.assertTrue(point.verify(z, sig))
Esempio n. 3
0
 def filterload(self, flag=1):
     '''Return the filterload message'''
     # start the payload with the size of the filter in bytes
     payload = encode_varint(self.size)
     # next add the bit field using self.filter_bytes()
     payload += self.filter_bytes()
     # function count is 4 bytes little endian
     payload += int_to_little_endian(self.function_count, 4)
     # tweak is 4 bytes little endian
     payload += int_to_little_endian(self.tweak, 4)
     # flag is 1 byte little endian
     payload += int_to_little_endian(flag, 1)
     # return a GenericMessage whose command is b'filterload'
     # and payload is what we've calculated
     return GenericMessage(b'filterload', payload)
Esempio n. 4
0
File: Tx.py Progetto: aroff/bitchain
 def sig_hash(self, input_index):
     s = int_to_little_endian(self.version, 4)
     s += encode_varint(len(self.tx_ins))
     for i, tx_in in enumerate(self.tx_ins):
         if i == input_index:
             s += TxIn(
                 prev_tx=tx_in.prev_tx,
                 prev_index=tx_in.prev_index,
                 script_sig=tx_in.script_pubkey(self.testnet),
                 sequence=tx_in.sequence,
             ).serialize()
         else:
             s += TxIn(
                 prev_tx=tx_in.prev_tx,
                 prev_index=tx_in.prev_index,
                 sequence=tx_in.sequence,
             ).serialize()
     s += encode_varint(len(self.tx_outs))
     for tx_out in self.tx_outs:
         s += tx_out.serialize()
     s += int_to_little_endian(self.locktime, 4)
     s += int_to_little_endian(SIGHASH_ALL, 4)
     h256 = hash256(s)
     return int.from_bytes(h256, 'big')
Esempio n. 5
0
 def sig_hash(self, input_index):
     '''Returns the integer representation of the hash that needs to get
     signed for index input_index'''
     # start the serialization with version
     # use int_to_little_endian in 4 bytes
     s = int_to_little_endian(self.version, 4)
     # add how many inputs there are using encode_varint
     s += encode_varint(len(self.tx_ins))
     # loop through each input using enumerate, so we have the input index
     # if the input index is the one we're signing
     # the previous tx's ScriptPubkey is the ScriptSig
     # Otherwise, the ScriptSig is empty
     # add the serialization of the input with the ScriptSig we want
     for i, tx_in in enumerate(self.tx_ins):
         if i == input_index:
             s += TxIn(prev_tx=tx_in.prev_tx,
                       prev_index=tx_in.prev_index,
                       script_sig=tx_in.script_pubkey(self.testnet),
                       sequence=tx_in.sequence).serialize()
         else:
             s += TxIn(prev_tx=tx_in.prev_tx,
                       prev_index=tx_in.prev_index,
                       sequence=tx_in.sequence).serialize()
     # add how many outputs there are using encode_varint
     s += encode_varint(len(self.tx_outs))
     # add the serialization of each output
     for tx_out in self.tx_outs:
         s += tx_out.serialize()
     # add the locktime using int_to_little_endian in 4 bytes
     s += int_to_little_endian(self.locktime, 4)
     # add SIGHASH_ALL using int_to_little_endian in 4 bytes
     s += int_to_little_endian(SIGHASH_ALL, 4)
     # hash256 the serialization
     h256 = hash256(s)
     # convert the result to an integer using int.from_bytes(x, 'big')
     return int.from_bytes(h256, 'big')
Esempio n. 6
0
 def test_varint(self):
     tests = [
         (0x01, unhexlify('01')),
         (0xfd, unhexlify('fdfd00')),
         (0xfe, unhexlify('fdfe00')),
         (0xff, unhexlify('fdff00')),
         (0x1234, unhexlify('fd3412')),
         (0x123456, unhexlify('fe56341200')),
         (0x123456789a01, unhexlify('ff019a785634120000')),
     ]
     for num, encoded in tests:
         self.assertEqual(encode_varint(num), encoded)
         s = BytesIO(encoded)
         self.assertEqual(read_varint(s), num)
     self.assertRaises(ValueError, encode_varint, 2**65)
Esempio n. 7
0
 def serialize(self):
     '''Returns the byte serialization of the transaction input'''
     # serialize prev_tx, little endian
     result = self.prev_tx[::-1]
     # serialize prev_index, 4 bytes, little endian
     result += int_to_little_endian(self.prev_index, 4)
     # get the scriptSig ready (use self.script_sig.serialize())
     raw_script_sig = self.script_sig.serialize()
     # encode_varint on the length of the scriptSig
     result += encode_varint(len(raw_script_sig))
     # add the scriptSig
     result += raw_script_sig
     # serialize sequence, 4 bytes, little endian
     result += int_to_little_endian(self.sequence, 4)
     return result
Esempio n. 8
0
 def script_pubkey(self, testnet=False):
     '''Get the ScriptPubKey by looking up the tx hash
     Returns a Script object
     '''
     # use self.fetch_tx to get the transaction
     #tx = self.fetch_tx(testnet=testnet)#ORIGINAL
     # get the output at self.prev_index
     # return the script_pubkey property
     #return tx.tx_outs[self.prev_index].script_pubkey
     if testnet: coin_sym = "btc-testnet"
     else: coin_sym = "btc"
     pretx = get_transaction_details(self.prev_tx.hex(),coin_symbol=coin_sym)
     ser_script = pretx["outputs"][self.prev_index]["script"]
     length = hex(int.from_bytes(encode_varint(len(ser_script)//2),"big"))[2:]
     script_pubkey =  Script.parse(BytesIO(bytes.fromhex(length+ser_script)))
     return script_pubkey
Esempio n. 9
0
 def serialize(self):
     '''Returns the byte serialization of the transaction input'''
     # serialize prev_tx, little endian
     result = self.prev_tx[::-1]
     # serialize prev_index, 4 bytes, little endian
     result += int_to_little_endian(self.prev_index, 4)
     # serialize the script_sig
     if self.script_sig is None:
         result += b'\x00'
     else:
         #result += self.script_sig.serialize()
         result += encode_varint(len(self.script_sig))
         result += self.script_sig
     # serialize sequence, 4 bytes, little endian
     result += int_to_little_endian(self.sequence, 4)
     return result
Esempio n. 10
0
 def sign_input(self, input_index, private_key):
     # added for signing p2sh script
     tx_in = self.tx_ins[input_index]
     script_lock = tx_in.get_script_lock(testnet=self.testnet)
     if script_lock.is_p2sh_script_pubkey():
         cmd = tx_in.script_sig.cmds[
             -1]  # last element in script_sig of p2sh is redeem script
         redeem_for_parsing = encode_varint(len(cmd)) + cmd  # for parsing
         redeem_script = script.parse(BytesIO(redeem_for_parsing))
     else:
         redeem_script = None
     z = self.sig_hash(input_index, redeem_script)
     der = private_key.sign(z).der()
     sig = der + SIGHASH_ALL.to_bytes(1, 'big')
     sec = private_key.pubPoint.sec()
     script_sig = Script([sig, sec])
     self.tx_ins[input_index].script_sig = script_sig
     return self.verify_input(input_index)
Esempio n. 11
0
 def serialize(self):
     s = int_to_little_endian(self.version, 4)
     s += int_to_little_endian(self.services, 8)
     s += int_to_little_endian(self.timestamp, 8)
     s += int_to_little_endian(self.receiver_services, 8)
     s += (b'\x00' * 10) + (b'\xff' * 2) + self.receiver_ip
     s += int_to_little_endian(self.receiver_port, 2)
     s += int_to_little_endian(self.sender_services, 8)
     s += (b'\x00' * 10) + (b'\xff' * 2) + self.sender_ip
     s += int_to_little_endian(self.sender_port, 2)
     s += self.nonce
     s += encode_varint(len(self.user_agent))
     s += self.user_agent
     s += int_to_little_endian(self.latest_block, 4)
     if self.relay:
         s += b'\x01'
     else:
         s += b'\x00'
     return s
Esempio n. 12
0
 def serialize(self):
     result = int_to_little_endian(self.version, 4)
     result += int_to_little_endian(self.services, 8)
     result += int_to_little_endian(self.timestamp, 8)
     result += int_to_little_endian(self.receiver_services, 8)
     result += b'\x00' * 10 + b'\xff\xff' + self.receiver_ip
     result += self.receiver_port.to_bytes(2, 'big')
     result += int_to_little_endian(self.sender_services, 8)
     result += b'\x00' * 10 + b'\xff\xff' + self.sender_ip
     result += self.sender_port.to_bytes(2, 'big')
     result += self.nonce
     result += encode_varint(len(self.user_agent))
     result += self.user_agent
     result += int_to_little_endian(self.latest_block, 4)
     if self.relay:
         result += b'\x01'
     else:
         result += b'\x00'
     return result
Esempio n. 13
0
 async def process_queue(self):
     print("start processing")
     start = time.time()
     while self.keep_looping:
         envelope = await self.q.get()
         command = envelope.command.strip(b'\x00').decode('ascii')
         if command == 'version':
             self.send(b'verack', b'')
         elif command == 'sendheaders':
             self.send(b'headers', encode_varint(0))
         elif command == 'ping':
             self.send(b'pong', envelope.payload)
             if not self._sent:
                 # tell them we have a tx
                 self.send(b'inv', self.inv_payload)
             elif not self._accepted:
                 self.send(b'tx', self.raw_tx)
             self.send(b'mempool', b'')
         elif command == 'getdata':
             if envelope.payload == self.inv_payload:
                 self.send(b'tx', self.raw_tx)
                 self._sent = True
             elif self._sent:
                 print('TX rejected')
                 self.keep_looping = False
         elif command == 'feefilter':
             minimum = little_endian_to_int(envelope.payload)
             print('TX requires fee: {} minimum'.format(minimum))
         elif command == 'inv':
             stream = BytesIO(envelope.payload)
             num_inv = read_varint(stream)
             for _ in range(num_inv):
                 inv_type = little_endian_to_int(stream.read(4))
                 inv_hash = stream.read(32)
                 if inv_type == 1 and inv_hash == self.tx_hash:
                     print('TX successfully sent')
                     self.keep_looping = False
             self.send(b'inv', self.inv_payload)
         else:
             print(envelope)
         if time.time() - start < self.timeout:
             self.keep_looping = False
Esempio n. 14
0
        def encode_address(_script_pubkey, testnet=True):
            address = ""
            addr_type = ""
            length = encode_varint(len(_script_pubkey))
            stream = BytesIO(length + _script_pubkey)
            #stream = BytesIO(_script_pubkey)
            try:
                script_pubkey = Script.parse(stream)
                if script_pubkey.is_p2pkh_script_pubkey():
                    address = h160_to_p2pkh_address(script_pubkey.cmds[2],
                                                    testnet)
                    addr_type = "P2PKH"
                elif script_pubkey.is_p2sh_script_pubkey():
                    address = h160_to_p2sh_address(script_pubkey.cmds[1],
                                                   testnet)
                    addr_type = "P2SH"
                elif script_pubkey.is_p2wpkh_script_pubkey(
                ) or script_pubkey.is_p2wsh_script_pubkey():
                    if testnet:
                        address = segwit_addr.encode("tb", 0,
                                                     script_pubkey.cmds[1])
                    else:
                        address = segwit_addr.encode("bc", 0,
                                                     script_pubkey.cmds[1])
                    if script_pubkey.is_p2wpkh_script_pubkey():
                        addr_type = "P2WPKH"
                    else:
                        addr_type = "P2WSH"
                elif len(script_pubkey.cmds
                         ) == 2 and script_pubkey.cmds[1] == 0xac:
                    try:
                        address = script_pubkey.cmds[0].hex()
                        addr_type = "P2PK"
                    except:
                        app_log.info(
                            f"P2PK failed {script_pubkey.cmds[0]} from tx: {output['t.id']}"
                        )

            except:
                app_log.info(f"script parsing failed.")

            return address, addr_type
Esempio n. 15
0
 def save(self):
     store_height = self.store_height()
     if exists(self.filename):
         with open(self.filename, 'rb') as f:
             file_height = read_varint(f)
             if store_height == file_height:
                 # no need to save as we're synced
                 return
             rest = f.read()
     else:
         file_height = -1
         rest = b''
     with open(self.filename, 'wb') as f:
         f.write(encode_varint(store_height))
         for height in range(store_height, file_height, -1):
             h = self.header_by_height(height)
             f.write(h.serialize())
             f.write(h.cfheader)
             f.write(h.cfhash)
         f.write(rest)
Esempio n. 16
0
 def serialize(self):
     '''Serialize this message to send over the network'''
     result = int_to_little_endian(self.version, 4)
     result += int_to_little_endian(self.services, 8)
     result += int_to_little_endian(self.timestamp, 8)
     result += int_to_little_endian(self.receiver_services, 8)
     result += 10 * b'\x00' + 2 * b'\xff' + self.receiver_ip
     result += self.receiver_port.to_bytes(2, byteorder='big')
     result += int_to_little_endian(self.sender_services, 8)
     result += 10 * b'\x01' + 2 * b'\xff' + self.sender_ip
     result += self.sender_port.to_bytes(2, byteorder='big')
     result += self.nonce
     result += encode_varint(len(self.user_agent))
     result += self.user_agent
     result += int_to_little_endian(self.latest_block, 4)
     if self.relay:
         result += b'\x01'
     else:
         result += b'\x00'
     return result
Esempio n. 17
0
 def serialize(self):
     # initialize what we'll send back
     result = b''
     # go through each item
     for item in self.items:
         # if the item is an integer, it's an op code
         if type(item) == int:
             # turn the item into a single byte integer using int_to_little_endian
             result += int_to_little_endian(item, 1)
         else:
             # otherwise, this is an element
             # get the length in bytes
             length = len(item)
             # turn the length into a single byte integer using int_to_little_endian
             prefix = int_to_little_endian(length, 1)
             # append to the result both the length and the item
             result += prefix + item
     # get the length of the whole thing
     total = len(result)
     # encode_varint the total length of the result and prepend
     return encode_varint(total) + result
Esempio n. 18
0
    def serialize(self):
        '''Serialize this message to send over the network'''
        # version is 4 bytes little endian
        s = int_to_little_endian(self.version, 4)
        # services is 8 bytes little endian
        s += int_to_little_endian(self.services, 8)
        # timestamp is 8 bytes little endian
        s += int_to_little_endian(self.timestamp, 8)
        # receiver services is 8 bytes little endian
        s += int_to_little_endian(self.receiver_services, 8)
        # IPV4 is 10 00 bytes and 2 ff bytes then receiver ip
        if len(self.receiver_ip) == 4:
            s += b'\x00' * 10 + b'\xff' * 2 + self.receiver_ip
        else:
            s += self.receiver_ip
        # receiver port is 2 bytes, big endian
        s += self.receiver_port.to_bytes(2, 'big')
        # sender services is 8 bytes little endian
        s += int_to_little_endian(self.sender_services, 8)
        # IPV4 is 10 00 bytes and 2 ff bytes then sender ip
        if len(self.sender_ip) == 4:
            s += b'\x00' * 10 + b'\xff' * 2 + self.sender_ip
        else:
            s += self.sender_ip
        # sender port is 2 bytes, big endian
        s += self.sender_port.to_bytes(2, 'big')
        # nonce should be 8 bytes
        s += self.nonce
        # useragent is a variable string, so varint first
        s += encode_varint(len(self.user_agent))
        s += self.user_agent
        # latest block is 4 bytes little endian
        s += int_to_little_endian(self.latest_block, 4)
        # relay is 00 if false, 01 if true
        if self.relay:
            s += b'\x01'
        else:
            s += b'\x00'

        return s
Esempio n. 19
0
 def save(self):
     with open(self.filename, 'wb') as f:
         f.write(self.encrypted_private.serialize())
         f.write(self.public.serialize())
         f.write(encode_varint(self.next_external))
         f.write(encode_varint(self.next_internal))
         f.write(encode_varint(self.creation_height))
         f.write(encode_varint(self.sync_height))
         utxos = [u for u in self.utxo_lookup.values()]
         f.write(encode_varint(len(utxos)))
         for utxo in utxos:
             f.write(utxo.serialize())
         stxos = [s for s in self.stxo_lookup.values()]
         f.write(encode_varint(len(stxos)))
         for stxo in stxos:
             f.write(stxo.serialize())
Esempio n. 20
0
    def serialize(self):
        '''Serialize this message to send over the network'''

        result = b''
        result += self.version.to_bytes(4, byteorder='little')
        result += self.services.to_bytes(8, byteorder='little')
        result += self.timestamp.to_bytes(8, byteorder='little')
        result += self.receiver_services.to_bytes(8, byteorder='little')
        result += bytes.fromhex('00000000000000000000ffff')
        result += self.receiver_ip
        result += self.receiver_port.to_bytes(2, byteorder='big')
        result += self.sender_services.to_bytes(8, byteorder='little')
        result += bytes.fromhex('00000000000000000000ffff')
        result += self.sender_ip
        result += self.sender_port.to_bytes(2, byteorder='big')
        result += self.nonce
        result += encode_varint(len(self.user_agent))
        result += self.user_agent
        result += int_to_little_endian(self.latest_block, 4)
        if self.relay:
            result += b'\x01'
        else:
            result += b'\x00'
        return result
Esempio n. 21
0
def verify_input(self, input_index):
    # get the relevant input
    tx_in = self.tx_ins[input_index]
    # grab the previous ScriptPubKey
    script_pubkey = tx_in.script_pubkey(testnet=self.testnet)
    # check to see if the ScriptPubkey is a p2sh using
    # Script.is_p2sh_script_pubkey()
    if script_pubkey.is_p2sh_script_pubkey():
        # the last cmd in a p2sh is the RedeemScript
        cmd = tx_in.script_sig.cmds[-1]
        # prepend the length of the RedeemScript using encode_varint
        raw_redeem = encode_varint(len(cmd)) + cmd
        # parse the RedeemScript
        redeem_script = Script.parse(BytesIO(raw_redeem))
    # otherwise RedeemScript is None
    else:
        redeem_script = None
    # get the signature hash (z)
    # pass the RedeemScript to the sig_hash method
    z = self.sig_hash(input_index, redeem_script)
    # combine the current ScriptSig and the previous ScriptPubKey
    combined = tx_in.script_sig + script_pubkey
    # evaluate the combined script
    return combined.evaluate(z)
Esempio n. 22
0
 def serialize(self):
     result = encode_varint(len(self.data))
     for data_type, identifier in self.data:
         result += int_to_little_endian(data_type, 4)
         result += identifier[::-1]
     return result
Esempio n. 23
0
 def serialize(self):
     result = int_to_little_endian(self.version, 4)
     result += encode_varint(self.num_hashes)
     result += self.start_block[::-1]
     result += self.end_block[::-1]
     return result
 def evaluate(self, z, witness):
     # create a copy as we may need to add to this list if we have a
     # RedeemScript
     cmds = self.cmds[:]
     stack = []
     altstack = []
     while len(cmds) > 0:
         cmd = cmds.pop(0)
         if type(cmd) == int:
             # do what the opcode says
             operation = OP_CODE_FUNCTIONS[cmd]
             if cmd in (99, 100):
                 # op_if/op_notif require the cmds array
                 if not operation(stack, cmds):
                     LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd]))
                     return False
             elif cmd in (107, 108):
                 # op_toaltstack/op_fromaltstack require the altstack
                 if not operation(stack, altstack):
                     LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd]))
                     return False
             elif cmd in (172, 173, 174, 175):
                 # these are signing operations, they need a sig_hash
                 # to check against
                 if not operation(stack, z):
                     LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd]))
                     return False
             else:
                 if not operation(stack):
                     LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd]))
                     return False
         else:
             # add the cmd to the stack
             stack.append(cmd)
             # p2sh rule. if the next three cmds are:
             # OP_HASH160 <20 byte hash> OP_EQUAL this is the RedeemScript
             # OP_HASH160 == 0xa9 and OP_EQUAL == 0x87
             if len(cmds) == 3 and cmds[0] == 0xa9 \
                 and type(cmds[1]) == bytes and len(cmds[1]) == 20 \
                 and cmds[2] == 0x87:
                 redeem_script = encode_varint(len(cmd)) + cmd
                 # we execute the next three opcodes
                 cmds.pop()
                 h160 = cmds.pop()
                 cmds.pop()
                 if not op_hash160(stack):
                     return False
                 stack.append(h160)
                 if not op_equal(stack):
                     return False
                 # final result should be a 1
                 if not op_verify(stack):
                     LOGGER.info('bad p2sh h160')
                     return False
                 # hashes match! now add the RedeemScript
                 redeem_script = encode_varint(len(cmd)) + cmd
                 stream = BytesIO(redeem_script)
                 cmds.extend(Script.parse(stream).cmds)
             # witness program version 0 rule. if stack cmds are:
             # 0 <20 byte hash> this is p2wpkh
             # tag::source3[]
             if len(stack) == 2 and stack[0] == b'' and len(stack[1]) == 20:  # <1>
                 h160 = stack.pop()
                 stack.pop()
                 cmds.extend(witness)
                 cmds.extend(p2pkh_script(h160).cmds)
             # end::source3[]
             # witness program version 0 rule. if stack cmds are:
             # 0 <32 byte hash> this is p2wsh
             # tag::source6[]
             if len(stack) == 2 and stack[0] == b'' and len(stack[1]) == 32:
                 s256 = stack.pop()  # <1>
                 stack.pop()  # <2>
                 cmds.extend(witness[:-1])  # <3>
                 witness_script = witness[-1]  # <4>
                 if s256 != sha256(witness_script):  # <5>
                     print('bad sha256 {} vs {}'.format
                         (s256.hex(), sha256(witness_script).hex()))
                     return False
                 stream = BytesIO(encode_varint(len(witness_script)) 
                     + witness_script)
                 witness_script_cmds = Script.parse(stream).cmds  # <6>
                 cmds.extend(witness_script_cmds)
             # end::source6[]
     if len(stack) == 0:
         return False
     if stack.pop() == b'':
         return False
     return True
Esempio n. 25
0
 def evaluate(self, z, witness):
     # create a copy as we may need to add to this list if we have a
     # RedeemScript
     instructions = self.instructions[:]
     stack = []
     altstack = []
     while len(instructions) > 0:
         instruction = instructions.pop(0)
         if type(instruction) == int:
             # do what the opcode says
             operation = OP_CODE_FUNCTIONS[instruction]
             if instruction in (99, 100):
                 # op_if/op_notif require the instructions array
                 if not operation(stack, instructions):
                     LOGGER.info('bad op: {}'.format(
                         OP_CODE_NAMES[instruction]))
                     return False
             elif instruction in (107, 108):
                 # op_toaltstack/op_fromaltstack require the altstack
                 if not operation(stack, altstack):
                     LOGGER.info('bad op: {}'.format(
                         OP_CODE_NAMES[instruction]))
                     return False
             elif instruction in (172, 173, 174, 175):
                 # these are signing operations, they need a sig_hash
                 # to check against
                 if not operation(stack, z):
                     LOGGER.info('bad op: {}'.format(
                         OP_CODE_NAMES[instruction]))
                     return False
             else:
                 if not operation(stack):
                     LOGGER.info('bad op: {}'.format(
                         OP_CODE_NAMES[instruction]))
                     return False
         else:
             # add the instruction to the stack
             stack.append(instruction)
             # p2sh rule. if the next three instructions are:
             # OP_HASH160 <20 byte hash> OP_EQUAL this is the RedeemScript
             # OP_HASH160 == 0xa9 and OP_EQUAL == 0x87
             if len(instructions) == 3 and instructions[0] == 0xa9 \
                 and type(instructions[1]) == bytes and len(instructions[1]) == 20 \
                 and instructions[2] == 0x87:
                 redeem_script = encode_varint(
                     len(instruction)) + instruction
                 # we execute the next three opcodes
                 instructions.pop()
                 h160 = instructions.pop()
                 instructions.pop()
                 if not op_hash160(stack):
                     return False
                 stack.append(h160)
                 if not op_equal(stack):
                     return False
                 # final result should be a 1
                 if not op_verify(stack):
                     LOGGER.info('bad p2sh h160')
                     return False
                 # hashes match! now add the RedeemScript
                 redeem_script = encode_varint(
                     len(instruction)) + instruction
                 stream = BytesIO(redeem_script)
                 instructions.extend(Script.parse(stream).instructions)
             # witness program version 0 rule. if stack instructions are:
             # 0 <20 byte hash> this is p2wpkh
             if len(stack) == 2 and stack[0] == b'' and len(stack[1]) == 20:
                 h160 = stack.pop()
                 stack.pop()
                 instructions.extend(witness)
                 instructions.extend(p2pkh_script(h160).instructions)
             # witness program version 0 rule. if stack instructions are:
             # 0 <32 byte hash> this is p2wsh
             if len(stack) == 2 and stack[0] == b'' and len(stack[1]) == 32:
                 h256 = stack.pop()
                 stack.pop()
                 instructions.extend(witness[:-1])
                 witness_script = witness[-1]
                 if h256 != sha256(witness_script):
                     LOGGER.info('bad sha256 {} vs {}'.format(
                         h256.hex(),
                         sha256(witness_script).hex()))
                     return False
                 # hashes match! now add the Witness Script
                 stream = BytesIO(
                     encode_varint(len(witness_script)) + witness_script)
                 witness_script_instructions = Script.parse(
                     stream).instructions
                 instructions.extend(witness_script_instructions)
     if len(stack) == 0:
         return False
     if stack.pop() == b'':
         return False
     return True
Esempio n. 26
0
    def _create_addresses(tx, batch, testnet=True):
        """
        testnet is TRUE always. Change this for mainnet later.
        """
        batch_size = 5
        app_log.info(
            f" batch size {batch_size}. Represents the amount of blocks whose outputs are being encoded to addresses."
        )
        for height in range(batch * batch_size, batch_size * (batch + 1)):

            result = tx.run(
                "MATCH (b:block {height:$height}) "
                "MATCH (x)<-[:CREATES]-(t:transaction)<-[:CONTAINS]-(b) "
                "RETURN x.script_pubkey, x.index, t.id",
                height=height)

            addresses = []
            for output in result.data():
                address = None
                addr_type = None
                raw_script_pubkey = output["x.script_pubkey"]
                b_sp = bytes.fromhex(raw_script_pubkey)
                length = encode_varint(len(b_sp))
                stream = BytesIO(length + b_sp)

                try:
                    script_pubkey = Script.parse(stream)

                    if script_pubkey.is_p2pkh_script_pubkey():
                        address = h160_to_p2pkh_address(
                            script_pubkey.cmds[2], testnet)
                        addr_type = "P2PKH"
                    elif script_pubkey.is_p2sh_script_pubkey():
                        address = h160_to_p2sh_address(script_pubkey.cmds[1],
                                                       testnet)
                        addr_type = "P2SH"
                    elif script_pubkey.is_p2wpkh_script_pubkey(
                    ) or script_pubkey.is_p2wsh_script_pubkey():
                        if testnet:
                            address = segwit_addr.encode(
                                "tb", 0, script_pubkey.cmds[1])
                        else:
                            address = segwit_addr.encode(
                                "bc", 0, script_pubkey.cmds[1])
                        if script_pubkey.is_p2wpkh_script_pubkey():
                            addr_type = "P2WPKH"
                        else:
                            addr_type = "P2WSH"
                    elif len(script_pubkey.cmds
                             ) == 2 and script_pubkey.cmds[1] == 0xac:
                        try:
                            address = script_pubkey.cmds[0].hex()
                            addr_type = "P2PK"
                        except:
                            app_log.info(
                                f"P2PK failed {script_pubkey.cmds[0]} from tx: {output['t.id']}"
                            )

                except:
                    app_log.info(
                        f"script parsing failed in tx {output['t.id']} index {output['x.index']} "
                    )

                if address is not None:
                    address_dict = {
                        "address": address,
                        "type": addr_type,
                        "tx_id": output["t.id"],
                        "index": output["x.index"]
                    }
                    addresses.append(address_dict)

            if len(addresses) > 0:
                result = tx.run(
                    "FOREACH (address in $addresses | \n"
                    "MERGE (o:output {index:address.index})<-[:CREATES]-(:transaction {id:address.tx_id}) \n"
                    "MERGE (a:address {address:address.address}) SET a.type=address.type \n"
                    "MERGE (a)-[:HAS]->(o) )",
                    addresses=addresses)

        return
Esempio n. 27
0
 def evaluate(self, z):
     # create a copy as we may need to add to this list if we have a
     # RedeemScript
     cmds = self.cmds[:]
     stack = []
     altstack = []
     while len(cmds) > 0:
         cmd = cmds.pop(0)
         if type(cmd) == int:
             # do what the opcode says
             operation = OP_CODE_FUNCTIONS[cmd]
             if cmd in (99, 100):
                 # op_if/op_notif require the cmds array
                 if not operation(stack, cmds):
                     LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd]))
                     return False
             elif cmd in (107, 108):
                 # op_toaltstack/op_fromaltstack require the altstack
                 if not operation(stack, altstack):
                     LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd]))
                     return False
             elif cmd in (172, 173, 174, 175):
                 # these are signing operations, they need a sig_hash
                 # to check against
                 if not operation(stack, z):
                     LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd]))
                     return False
             else:
                 if not operation(stack):
                     LOGGER.info('bad op: {}'.format(OP_CODE_NAMES[cmd]))
                     return False
         # tag::source1[]
         else:
             #리딤 스크립트를 스택에 올린다.
             stack.append(cmd)
             #그리고 다음명령이 op_hash160, 리딤스크립트의 hash값, op_euqal이면,
             if len(cmds) == 3 and cmds[0] == 0xa9 \
                 and type(cmds[1]) == bytes and len(cmds[1]) == 20 \
                 and cmds[2] == 0x87:  # <1>
                 cmds.pop()  # <2>
                 h160 = cmds.pop()
                 cmds.pop()
                 #리딤 스크립트를 해시
                 if not op_hash160(stack):  # <3>
                     return False
                 #리딤 스크립트의 해시 값을 추가
                 stack.append(h160)
                 #두 값이 같은지 비교
                 if not op_equal(stack):
                     return False
                 if not op_verify(stack):  # <4>
                     LOGGER.info('bad p2sh h160')
                     return False
                 #리딤 스크립트의 길이를 구해 리딤 스크립트의 앞에 위치시킨다.
                 redeem_script = encode_varint(len(cmd)) + cmd  # <5>
                 stream = BytesIO(redeem_script)
                 #리딤 스크립트를 파싱해서 명령어 집합에 추가
                 cmds.extend(Script.parse(stream).cmds)  # <6>
                 # end::source1[]
     if len(stack) == 0:
         return False
     if stack.pop() == b'':
         return False
     return True
Esempio n. 28
0
1574e6b3c192ecfb52cc8984ee7b6c568700000000'

hex_sec = '03b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7fbdbd4b\
b71'

hex_der = '3045022100da6bee3c93766232079a01639d07fa869598749729ae323eab8ee\
f53577d611b02207bef15429dcadce2121ea07f233115c6f09034c0be68db99980b9a6c5e75402\
2'

hex_redeem_script = '475221022626e955ea6ea6d98850c994f9107b036b1334f18ca88\
30bfff1295d21cfdb702103b287eaf122eea69030a0e9feed096bed8045c8b98bec453e1ffac7f\
bdbd4bb7152ae'

sec = bytes.fromhex(hex_sec)
der = bytes.fromhex(hex_der)
redeem_script = Script.parse(BytesIO(bytes.fromhex(hex_redeem_script)))
stream = BytesIO(bytes.fromhex(hex_tx))
tx_obj = Tx.parse(stream)
s = int_to_little_endian(tx_obj.version, 4)
s += encode_varint(len(tx_obj.tx_ins))
i = tx_obj.tx_ins[0]
s += TxIn(i.prev_tx, i.prev_index, redeem_script, i.sequence).serialize()
s += encode_varint(len(tx_obj.tx_outs))
for tx_out in tx_obj.tx_outs:
    s += tx_out.serialize()
s += int_to_little_endian(tx_obj.locktime, 4)
s += int_to_little_endian(SIGHASH_ALL, 4)
z = int.from_bytes(hash256(s), 'big')
point = S256Point.parse(sec)
sig = Signature.parse(der)
print(point.verify(z, sig))
Esempio n. 29
0
	def serialize_pair(key, value):
		kv_bytes = encode_varint(len(key)) + key
		kv_bytes += encode_varint(len(value)) + value
		return kv_bytes
Esempio n. 30
0
 def evaluate(self, z):
     # create a copy as we may need to add to this list if we have a
     # RedeemScript
     instructions = self.instructions[:]
     stack = []
     altstack = []
     while len(instructions) > 0:
         instruction = instructions.pop(0)
         if type(instruction) == int:
             # do what the opcode says
             operation = OP_CODE_FUNCTIONS[instruction]
             if instruction in (99, 100):
                 # op_if/op_notif require the instructions array
                 if not operation(stack, instructions):
                     LOGGER.info('bad op: {}'.format(
                         OP_CODE_NAMES[instruction]))
                     return False
             elif instruction in (107, 108):
                 # op_toaltstack/op_fromaltstack require the altstack
                 if not operation(stack, altstack):
                     LOGGER.info('bad op: {}'.format(
                         OP_CODE_NAMES[instruction]))
                     return False
             elif instruction in (172, 173, 174, 175):
                 # these are signing operations, they need a sig_hash
                 # to check against
                 if not operation(stack, z):
                     LOGGER.info('bad op: {}'.format(
                         OP_CODE_NAMES[instruction]))
                     return False
             else:
                 if not operation(stack):
                     LOGGER.info('bad op: {}'.format(
                         OP_CODE_NAMES[instruction]))
                     return False
         else:
             # add the instruction to the stack
             stack.append(instruction)
             if len(instructions) == 3 and instructions[0] == 0xa9 \
                 and type(instructions[1]) == bytes and len(instructions[1]) == 20 \
                 and instructions[2] == 0x87:
                 # we execute the next three opcodes
                 instructions.pop()
                 h160 = instructions.pop()
                 instructions.pop()
                 if not op_hash160(stack):
                     return False
                 stack.append(h160)
                 if not op_equal(stack):
                     return False
                 # final result should be a 1
                 if not op_verify(stack):
                     LOGGER.info('bad p2sh h160')
                     return False
                 # hashes match! now add the RedeemScript
                 redeem_script = encode_varint(
                     len(instruction)) + instruction
                 stream = BytesIO(redeem_script)
                 instructions.extend(Script.parse(stream).instructions)
     if len(stack) == 0:
         return False
     if stack.pop() == b'':
         return False
     return True