Beispiel #1
0
class TxIn(object):
    OUTPOINT_FMT = fmt_w_size('<32sI')

    def __init__(self, previous_output, signature_script, sequence):
        self.previous_output = previous_output
        self.signature_script = signature_script
        self.sequence = sequence

    @classmethod
    def parse(cls, bytes):
        (previous_output, bytes) = parse(bytes, cls.OUTPOINT_FMT)
        (script_len, bytes) = parse_varint(bytes)
        (signature_script, bytes) = splitn(bytes, script_len)
        ((sequence, ), bytes) = parse(bytes, UINT32_FMT)
        return (cls(previous_output, signature_script, sequence), bytes)

    @property
    def bytes(self):
        return ''.join([
            struct.pack(self.OUTPOINT_FMT[0], *self.previous_output),
            encode_varint(len(self.signature_script)), self.signature_script,
            struct.pack(UINT32_FMT[0], self.sequence)
        ])

    def __eq__(self, b):
        return (self.previous_output == b.previous_output
                and self.signature_script == b.signature_script
                and self.sequence == b.sequence)

    def __repr__(self):
        return 'TxIn((%s, %r), %s, %r)' % (
            binascii.hexlify(self.previous_output[0]), self.previous_output[1],
            binascii.hexlify(self.signature_script), self.sequence)
Beispiel #2
0
class MessageHeader(object):
    HEADER_FMT = fmt_w_size('<4s12sI4s')

    def __init__(self, command=None, payload_length=None, checksum=None):
        self.magic = MAGIC
        self.command = command
        self.payload_length = payload_length
        self.checksum = checksum

    @property
    def bytes(self):
        return struct.pack(self.HEADER_FMT[0], self.magic, self.command,
                           self.payload_length, self.checksum)

    @classmethod
    def parse(cls, bytes):
        ((magic, command, payload_length, checksum),
         bytes) = parse(bytes, cls.HEADER_FMT)
        if magic != MAGIC:
            raise ParseError('Magic does not match: %r' % (magic, ))
        command = command.rstrip('\x00')
        return (cls(command, payload_length, checksum), bytes)

    def __repr__(self):
        return 'MessageHeader(%s, %s, %r, %s)' % (util.visual(
            self.magic), self.command, self.payload_length,
                                                  util.visual(self.checksum))
Beispiel #3
0
class InventoryVector(Message):
    HASH_FMT = fmt_w_size('<I32s')
    ERROR = 0
    MSG_TX = 1
    MSG_BLOCK = 2
    HASH_TYPES = {0: 'ERROR', 1: 'MSG_TX', 2: 'MSG_BLOCK'}

    def __init__(self, hashes=None, header=None):
        super(InventoryVector, self).__init__(header=header)
        self.hashes = hashes if hashes is not None else []

    @property
    def payload(self):
        return ''.join(
            [encode_varint(len(self.hashes))] +
            [struct.pack(self.HASH_FMT[0], *item) for item in self.hashes])

    @classmethod
    def parse(cls, bytes, header=None):
        if header is None:
            (header, bytes) = MessageHeader.parse(bytes)
        (count, bytes) = parse_varint(bytes)
        hashes = []
        for _ in xrange(count):
            (item, bytes) = parse(bytes, cls.HASH_FMT)
            hashes.append(item)
        return (cls(hashes, header), bytes)

    def __repr__(self):
        return 'Inventory([%s])' % (', '.join(
            '(%s, %s)' %
            (self.HASH_TYPES.get(i[0], '<UNKNOWN>'), binascii.hexlify(i[1]))
            for i in self.hashes), )
Beispiel #4
0
class Version(Message):
    COMMAND = 'version'
    BITS = [fmt_w_size(f) for f in ['<iQq', '<Q', '<i?']]

    def __init__(self,
                 version,
                 addr_recv,
                 addr_from,
                 nonce,
                 user_agent,
                 start_height,
                 relay,
                 services=0x01,
                 timestamp=None,
                 header=None):
        super(Version, self).__init__(header=header)
        self.version = version
        self.services = services
        self.timestamp = timestamp if timestamp is not None else long(
            time.time())
        self.addr_recv = addr_recv
        self.addr_from = addr_from
        self.nonce = nonce
        self.user_agent = user_agent
        self.start_height = start_height
        self.relay = relay

    @property
    def payload(self):
        return ''.join([
            struct.pack(self.BITS[0][0], self.version, self.services,
                        self.timestamp),
            encode_addr_bare(self.addr_recv),
            encode_addr_bare(self.addr_from),
            struct.pack(self.BITS[1][0], self.nonce),
            encode_varstr(self.user_agent),
            struct.pack(self.BITS[2][0], self.start_height, self.relay)
        ])

    @classmethod
    def parse(cls, bytes, header=None):
        if header is None:
            (header, bytes) = MessageHeader.parse(bytes)
        ((version, services, timestamp), bytes) = parse(bytes, cls.BITS[0])
        (addr_recv, bytes) = parse_addr_bare(bytes)
        (addr_from, bytes) = parse_addr_bare(bytes)
        ((nonce, ), bytes) = parse(bytes, cls.BITS[1])
        (user_agent, bytes) = parse_varstr(bytes)
        ((start_height, relay), bytes) = parse(bytes, cls.BITS[2])
        return (cls(version, addr_recv, addr_from, nonce, user_agent,
                    start_height, relay, services, timestamp, header), bytes)

    def __repr__(self):
        return 'Version(%r, %r, %r, %r, %r, %r, %r, %r, %r, %r)' % (
            self.header, self.version, self.services, self.timestamp,
            self.addr_recv, self.addr_from, self.nonce, self.user_agent,
            self.start_height, self.relay)
Beispiel #5
0
class GetBlocks(Message):
    COMMAND = 'getblocks'
    HASH_FMT = fmt_w_size('<32s')

    def __init__(self, version, hashes, hash_stop, header=None):
        super(GetBlocks, self).__init__(header=header)
        self.version = version
        self.hashes = hashes
        self.hash_stop = hash_stop

    @property
    def payload(self):
        return ''.join([
            struct.pack(UINT32_FMT[0], self.version),
            encode_varint(len(self.hashes)),
            ''.join(
                struct.pack(self.HASH_FMT[0], hash) for hash in self.hashes),
            struct.pack(self.HASH_FMT[0], self.hash_stop),
        ])

    @classmethod
    def parse(cls, bytes, header=None):
        if header is None:
            (header, bytes) = MessageHeader.parse(bytes)
        ((version, ), bytes) = parse(bytes, UINT32_FMT)
        (num_hashes, bytes) = parse_varint(bytes)
        hashes = []
        for _ in xrange(num_hashes):
            ((hash, ), bytes) = parse(bytes, cls.HASH_FMT)
            hashes.append(hash)
        ((hash_stop, ), bytes) = parse(bytes, cls.HASH_FMT)
        return (cls(version, hashes, hash_stop, header=header), bytes)

    def __eq__(self, b):
        return (self.version == b.version and self.hashes == b.hashes
                and self.hash_stop == b.hash_stop)

    def __repr__(self):
        return 'GetBlocks(%r, %r, %s, %s)' % (
            self.header, self.version, '[%s]' %
            (', '.join(binascii.hexlify(hash) for hash in self.hashes)),
            binascii.hexlify(self.hash_stop))
Beispiel #6
0
class PingPong(Message):
    PAYLOAD = fmt_w_size('<Q')

    def __init__(self, nonce=None, header=None):
        super(PingPong, self).__init__(header=header)
        if nonce is None:
            nonce = random.randint(0, 0xFFFFFFFFFFFFFFFF)
        self.nonce = nonce

    @property
    def payload(self):
        return struct.pack(self.PAYLOAD[0], self.nonce)

    @classmethod
    def parse(cls, bytes, header=None):
        if header is None:
            (header, bytes) = MessageHeader.parse(bytes)
        ((nonce, ), bytes) = parse(bytes, cls.PAYLOAD)
        return (cls(nonce, header), bytes)

    def __repr__(self):
        return '%s(%r, %r)' % (self.__class__.__name__, self.header,
                               self.nonce)
Beispiel #7
0
class Block(Message):
    COMMAND = 'block'

    HDR_FMT = fmt_w_size('<I32s32sIII')

    def __init__(self,
                 version,
                 prev_block_hash,
                 merkle_root,
                 timestamp,
                 bits,
                 nonce,
                 txns,
                 header=None):
        super(Block, self).__init__(header=header)
        self.version = version
        self.prev_block_hash = prev_block_hash
        self.merkle_root = merkle_root
        self.timestamp = timestamp
        self.bits = bits
        self.nonce = nonce
        self.txns = txns

    @property
    def block_header(self):
        return struct.pack(self.HDR_FMT[0], self.version, self.prev_block_hash,
                           self.merkle_root, self.timestamp, self.bits,
                           self.nonce)

    @property
    def block_hash(self):
        return sha256(sha256(self.block_header).digest()).digest()

    @property
    def payload(self):
        return ''.join([
            self.block_header,
            encode_varint(len(self.txns)),
            ''.join(tx.bytes for tx in self.txns)
        ])

    @classmethod
    def parse(cls, bytes, header=None):
        if header is None:
            (header, bytes) = MessageHeader.parse(bytes)
        ((version, prev_block_hash, merkle_root, timestamp, bits, nonce),
         bytes) = parse(bytes, cls.HDR_FMT)
        (num_tx, bytes) = parse_varint(bytes)
        txns = []
        for _ in xrange(num_tx):
            (tx, bytes) = Transaction.parse(bytes)
            txns.append(tx)
        return (cls(version, prev_block_hash, merkle_root, timestamp, bits,
                    nonce, txns), bytes)

    def __eq__(self, b):
        return (self.version == b.version
                and self.prev_block_hash == b.prev_block_hash
                and self.merkle_root == b.merkle_root
                and self.timestamp == b.timestamp and self.bits == b.bits
                and self.nonce == b.nonce and self.txns == b.txns)

    def __repr__(self):
        txins = 0
        txouts = 0
        for tx in self.txns:
            txins += len(tx.tx_in)
            txouts += len(tx.tx_out)
        return 'Block(%u txns, %u txins, %u txouts, %r, %s, %s, %r, %r, %r, %r)' % (
            len(self.txns), txins, txouts, self.version,
            binascii.hexlify(
                self.prev_block_hash), binascii.hexlify(self.merkle_root),
            self.timestamp, self.bits, self.nonce, self.txns)
Beispiel #8
0
from hashlib import sha256
import logging
import random
import struct
import time

from pybitcoin import util, key, byte_util
from pybitcoin.byte_util import Error, ParseError, fmt_w_size, splitn, parse

log = logging.getLogger(__name__)

PROTOCOL_VERSION = 70011

MAGIC = struct.pack('<I', 0xD9B4BEF9)

UINT32_FMT = fmt_w_size('<I')
INT64_FMT = fmt_w_size('<q')


def encode_varint(i):
    if i < 0xfd:
        return struct.pack('<B', i)
    elif i <= 0xffff:
        return struct.pack('<BH', 0xfd, i)
    elif i <= 0xffffffff:
        return struct.pack('<BI', 0xfe, i)
    elif i <= 0xffffffffffffffff:
        return struct.pack('<BQ', 0xff, i)
    else:
        raise Error('int too big for varint: %r' % (i, ))
Beispiel #9
0
import random
import struct
import time

from pybitcoin import util, key, byte_util
from pybitcoin.byte_util import Error, ParseError, fmt_w_size, splitn, parse


log = logging.getLogger(__name__)


PROTOCOL_VERSION = 70011

MAGIC = struct.pack('<I', 0xD9B4BEF9)

UINT32_FMT = fmt_w_size('<I')
INT64_FMT = fmt_w_size('<q')


def encode_varint(i):
    if i < 0xfd:
        return struct.pack('<B', i)
    elif i <= 0xffff:
        return struct.pack('<BH', 0xfd, i)
    elif i <= 0xffffffff:
        return struct.pack('<BI', 0xfe, i)
    elif i <= 0xffffffffffffffff:
        return struct.pack('<BQ', 0xff, i)
    else:
        raise Error('int too big for varint: %r' % (i,))