Ejemplo n.º 1
0
 def parse(cls, s):
     '''Takes a byte stream and parses the tx_input at the start
     return a TxIn object
     '''
     # reverse the prev tx hash (little endian to big endian)
     prev_tx = s.read(32)[::-1]
     prev_index = little_endian_to_int(s.read(4))
     script_sig = Script.parse(s)
     sequence = little_endian_to_int(s.read(4))
     return cls(prev_tx, prev_index, script_sig, sequence)
Ejemplo n.º 2
0
 def parse(cls, s):
     '''Takes a byte stream and parses the tx_output at the start
     return a TxOut object
     '''
     amount = little_endian_to_int(s.read(8))
     script_pub = Script.parse(s)
     return cls(amount, script_pub)
Ejemplo n.º 3
0
 def parse(cls, s):
     '''Takes a byte stream and parses a merkle block. Returns a Merkle Block object'''
     version = little_endian_to_int(s.read(4))
     prev_block = s.read(32)[::-1]
     merkle_root = s.read(32)[::-1]
     timestamp = little_endian_to_int(s.read(4))
     bits = s.read(4)
     nonce = s.read(4)
     total_tx_in_block = little_endian_to_int(s.read(4))
     tx_hashes_number = read_varint(s)
     hashes = []
     for i in range(tx_hashes_number):
         hashes.append(s.read(32)[::-1])
     flag_length = read_varint(s)
     flags = s.read(flag_length)
     return cls(version, prev_block, merkle_root, timestamp, bits, nonce,
                total_tx_in_block, hashes, flags)
Ejemplo n.º 4
0
 def check_pow(self):
     '''Returns whether this block satisfies proof of work'''
     # get the hash256 of the serialization of this block
     h256 = hash256(self.serialize())
     # interpret this hash as a little-endian number
     proof = little_endian_to_int(h256)
     # return whether this integer is less than the target
     return proof < self.target()
Ejemplo n.º 5
0
    def parse(cls, s):
        '''Takes a byte stream and parses a block. Returns a Block object'''

        # version - 4 bytes, little endian, interpret as int
        version: int = little_endian_to_int(s.read(4))
        # prev_block - 32 bytes, little endian (use [::-1] to reverse)
        prev_block: bytes = s.read(32)[::-1]
        # merkle_root - 32 bytes, little endian (use [::-1] to reverse)
        merkle_root: bytes = s.read(32)[::-1]
        # timestamp - 4 bytes, little endian, interpret as int
        timestamp: int = little_endian_to_int(s.read(4))
        # bits - 4 bytes
        bits: bytes = s.read(4)
        # nonce - 4 bytes
        nonce: bytes = s.read(4)

        return cls(version, prev_block, merkle_root, timestamp, bits, nonce)
Ejemplo n.º 6
0
    def parse(cls, s, testnet=False):
        '''Takes a byte stream and parses the transaction at the start
        return a Tx object
        '''

        version = little_endian_to_int(s.read(4))
        num_inputs = read_varint(s)
        inputs = []
        for _ in range(num_inputs):
            inputs.append(TxIn.parse(s))

        num_outputs = read_varint(s)
        outputs = []
        for _ in range(num_outputs):
            outputs.append(TxOut.parse(s))
        locktime = little_endian_to_int(s.read(4))

        return cls(version, inputs, outputs, locktime, testnet=testnet)
Ejemplo n.º 7
0
 def load_cache(cls, filename):
     disk_cache = json.loads(open(filename, 'r').read())
     for k, raw_hex in disk_cache.items():
         raw = bytes.fromhex(raw_hex)
         if raw[4] == 0:
             raw = raw[:4] + raw[6:]
             tx = Tx.parse(BytesIO(raw))
             tx.locktime = little_endian_to_int(raw[-4:])
         else:
             tx = Tx.parse(BytesIO(raw))
         cls.cache[k] = tx
Ejemplo n.º 8
0
 def parse(cls, s):
     # get the length of the entire field
     length = read_varint(s)
     # initialize the cmds array
     cmds = []
     # initialize the number of bytes we've read to 0
     count = 0
     # loop until we've read length bytes
     while count < length:
         # get the current byte
         current = s.read(1)
         # increment the bytes we've read
         count += 1
         # convert the current byte to an integer
         current_int = current[0]
         # if the current byte is between 1 and 75 inclusive
         if current_int >= 1 and current_int <= 75:
             # we have an cmd set n to be the current byte
             n = current_int
             # add the next n bytes as an cmd
             cmds.append(s.read(n))
             # increase the count by n
             count += n
         elif current_int == 76:
             # op_pushdata1
             data_length = little_endian_to_int(s.read(1))
             cmds.append(s.read(data_length))
             count += data_length + 1
         elif current_int == 77:
             # op_pushdata2
             data_length = little_endian_to_int(s.read(2))
             cmds.append(s.read(data_length))
             count += data_length + 2
         else:
             # we have an opcode. set the current byte to op_code
             op_code = current_int
             # add the op_code to the list of cmds
             cmds.append(op_code)
     if count != length:
         raise SyntaxError('parsing script failed')
     return cls(cmds)
Ejemplo n.º 9
0
 def fetch(cls, tx_id, testnet=False, fresh=False):
     if fresh or (tx_id not in cls.cache):
         url = '{}/tx/{}.hex'.format(cls.get_url(testnet), tx_id)
         response = requests.get(url)
         try:
             raw = bytes.fromhex(response.text.strip())
         except ValueError:
             raise ValueError('unexpected response: {}'.format(
                 response.text))
         # Todo: check this case. (segwit..?)
         if raw[4] == 0:
             raw = raw[:4] + raw[6:]
             tx = Tx.parse(BytesIO(raw), testnet=testnet)
             tx.locktime = little_endian_to_int(raw[-4:])
         else:
             tx = Tx.parse(BytesIO(raw), testnet=testnet)
         if tx.id() != tx_id:  # <1>
             raise ValueError('not the same id: {} vs {}'.format(
                 tx.id(), tx_id))
         cls.cache[tx_id] = tx
     cls.cache[tx_id].testnet = testnet
     return cls.cache[tx_id]
Ejemplo n.º 10
0
 def coinbase_height(self):
     if not self.is_coinbase():
         return None
     element = self.tx_ins[0].script_sig.cmds[0]
     return little_endian_to_int(element)