Example #1
0
    def recv_headers(self, payload):
        count, payload = read_var_int(payload)
        assert count <= 2000

        headers = []
        for i in range(count):
            hdr, payload = read_bytes(payload, Constants.BLOCKHEADER_SIZE,
                                      bytes, 'big')
            headers.append(hdr)
            tx_count, payload = read_var_int(payload)
            assert tx_count == 0

        self.network.received_headers(self, headers)
Example #2
0
    def recv_inv(self, payload):
        count, payload = read_var_int(payload)

        for i in range(count):
            data, payload = read_bytes(payload, 36, bytes, 'big')
            inv = InventoryVector.from_serialized(data)
            # TODO get data if we need it
            #   invs.append( inv )
            # self.send_getdata( invs )
            print(inv)
Example #3
0
    def recv_reject(self, payload):
        length_msg, payload = read_var_int(payload)
        raw_msg, payload = read_bytes(payload, length_msg, bytes, 'big')
        msg = raw_msg.decode('ascii')
        ccode, payload = read_bytes(payload, 1, int, 'little')
        length_reason, payload = read_var_int(payload)
        raw_reason, payload = read_bytes(payload, length_reason, bytes, 'big')
        reason = raw_reason.decode('utf-8')
        data = payload.hex()

        print("{} reject {}: {}, {} {}".format(
            self.address['host'], msg, {
                Constants.REJECT_MALFORMED: "malformed",
                Constants.REJECT_INVALID: "invalid",
                Constants.REJECT_OBSOLETE: "obsolete",
                Constants.REJECT_DUPLICATE: "duplicate",
                Constants.REJECT_NONSTANDARD: "non standard",
                Constants.REJECT_DUST: "dust",
                Constants.REJECT_INSUFFICIENTFEE: "insufficient fee",
                Constants.REJECT_CHECKPOINT: "checkpoint"
            }[ccode], reason, data))
Example #4
0
    def recv_getdata(self, payload):
        count, payload = read_var_int(payload)

        for i in range(count):
            data, payload = read_bytes(payload, 36, bytes, 'big')
            inv = InventoryVector.from_serialized(data)
            if inv in self.inventory:
                if inv.is_tx():
                    try:
                        tx = self.txdb[inv.get_id()]
                    except:
                        raise NetworkError("cannot retrieve transaction")
                    else:
                        self.send_tx(bytes.fromhex(tx))
Example #5
0
    def recv_addr(self, payload):
        count, payload = read_var_int(payload)

        for i in range(count):
            data, payload = read_bytes(payload, 30, bytes, 'big')
            address = deserialize_network_address(data, with_timestamp=True)

            if not any([
                    address['host'] == na['host']
                    for na in self.network.peer_list
            ]) & (address['host'] !=
                  "") & (address['port'] == Constants.DEFAULT_PORT) & (
                      len(self.network.peer_list) <
                      self.network.MAX_PEER_ADDRESSES):
                self.network.peer_list.append(address)
                print("New peer address: {}".format(address['host']))
        assert payload == bytes()
Example #6
0
    def recv_version(self, payload):
        if len(payload) < 20:
            self.state = 'dead'
            return

        try:
            self.version, payload = read_bytes(payload, 4, int, 'little')
            self.services, payload = read_bytes(payload, 8, int, 'little')
            self.time, payload = read_bytes(payload, 8, int, 'little')
            addr_recv, payload = read_bytes(payload, 26, bytes, 'big')
            my_network_address = deserialize_network_address(
                addr_recv, with_timestamp=False)
            addr_trans, payload = read_bytes(payload, 26, bytes, 'big')
            peer_network_address = deserialize_network_address(
                addr_trans, with_timestamp=False)
            nonce, payload = read_bytes(payload, 8, int, 'little')
            peer_user_agent_size, payload = read_var_int(payload)
            peer_user_agent, payload = read_bytes(payload,
                                                  peer_user_agent_size, bytes,
                                                  'big')
            self.block_height, payload = read_bytes(payload, 4, int, 'little')
            relay, payload = read_bytes(payload, 1, int, 'little')
            assert payload == bytes()
        except:
            self.state = 'dead'
            return

        print(" Peer address: {}\n Services: {:d}\n User Agent: {}".format(
            peer_network_address['host'], peer_network_address['services'],
            peer_user_agent.decode('ascii')))

        self.send_verack()
        self.peer_verack += 1

        if not self.sent_version:
            self.send_version()

        if self.peer_verack == 2:
            self.handshake_time = time.time()
            print("{} handshake done".format(self.address['host']))
Example #7
0
    def from_serialized(self, raw):
        assert isinstance(raw, bytes)
        self.raw = raw
        version, raw = read_bytes(raw, 4, int, 'little')

        input_count, raw = read_var_int(raw)
        txins = []
        for i in range(input_count):
            txin = {}
            txin['txid'], raw = read_bytes(raw, 32, hex, 'little')
            txin['index'], raw = read_bytes(raw, 4, int, 'little')
            scriptsize, raw = read_var_int(raw)
            unlockingScript, raw = read_bytes(raw, scriptsize, bytes, 'big')
            txin['unlocking_script'] = unlockingScript.hex()
            if (txin['txid'] == "00" * 32) & (txin['index'] == 0xffffffff):
                # Coinbase input
                txin['type'] = "coinbase"
            else:
                t, signatures, pubkeys, address, redeem_script = parse_unlocking_script(
                    unlockingScript)
                txin['type'] = t
                if t == "p2pk":
                    txin['signatures'] = [sig.hex() for sig in signatures]
                elif t == "p2pkh":
                    txin['signatures'] = [sig.hex() for sig in signatures]
                    txin['pubkeys'] = pubkeys
                    txin['address'] = address
                elif t == "p2sh":
                    # only p2sh-ms for the moment
                    txin['signatures'] = [sig.hex() for sig in signatures]
                    txin['pubkeys'] = pubkeys
                    txin['address'] = address
                    txin['redeem_script'] = redeem_script
                elif t == "p2ms":
                    raise TransactionError("we do not parse p2ms outputs")
                else:
                    raise TransactionError("cannot parse unlocking script")
                txin['nsigs'] = len(signatures)
            txin['sequence'], raw = read_bytes(raw, 4, int, 'little')
            txins.append(txin)

        output_count, raw = read_var_int(raw)
        txouts = []
        for i in range(output_count):
            txout = {}
            txout['value'], raw = read_bytes(raw, 8, int, 'little')
            scriptsize, raw = read_var_int(raw)
            lockingScript, raw = read_bytes(raw, scriptsize, bytes, 'big')
            txout['locking_script'] = lockingScript.hex()
            t, address, data = parse_locking_script(lockingScript)
            txout['type'] = t
            if t in ("p2pkh", "p2sh"):
                txout['address'] = address
            elif t == "p2pk":
                txout['address'] = address
            elif t == "nulldata":
                txout['data'] = data
            elif t == "p2ms":
                raise TransactionError("we do not parse p2pk and p2ms outputs")
            else:
                raise TransactionError("cannot parse unlocking script")
            txouts.append(txout)

        locktime, raw = read_bytes(raw, 4, int, 'little')

        return self(version, txins, txouts, locktime)