示例#1
0
    def check(self, tracker, other_txs=None):
        from p2pool import p2p
        counts = None
        if self.share_data['previous_share_hash'] is not None:
            previous_share = tracker.items[self.share_data['previous_share_hash']]
            if tracker.get_height(self.share_data['previous_share_hash']) >= self.net.CHAIN_LENGTH:
                counts = get_desired_version_counts(tracker, tracker.get_nth_parent_hash(previous_share.hash, self.net.CHAIN_LENGTH*9//10), self.net.CHAIN_LENGTH//10)
                if type(self) is type(previous_share):
                    pass
                elif type(self) is type(previous_share).SUCCESSOR:
                    # switch only valid if 60% of hashes in [self.net.CHAIN_LENGTH*9//10, self.net.CHAIN_LENGTH] for new version
                    if counts.get(self.VERSION, 0) < sum(counts.itervalues())*60//100:
                        raise p2p.PeerMisbehavingError('switch without enough hash power upgraded')
                else:
                    raise p2p.PeerMisbehavingError('''%s can't follow %s''' % (type(self).__name__, type(previous_share).__name__))
            elif type(self) is type(previous_share).SUCCESSOR:
                raise p2p.PeerMisbehavingError('switch without enough history')
        
        other_tx_hashes = [tracker.items[tracker.get_nth_parent_hash(self.hash, share_count)].share_info['new_transaction_hashes'][tx_count] for share_count, tx_count in self.iter_transaction_hash_refs()]
        if other_txs is not None and not isinstance(other_txs, dict): other_txs = dict((bitcoin_data.hash256(bitcoin_data.tx_type.pack(tx)), tx) for tx in other_txs)
        
        share_info, gentx, other_tx_hashes2, get_share = self.generate_transaction(tracker, self.share_info['share_data'], self.header['bits'].target, self.share_info['timestamp'], self.share_info['bits'].target, self.contents['ref_merkle_link'], [(h, None) for h in other_tx_hashes], self.net,
            known_txs=other_txs, last_txout_nonce=self.contents['last_txout_nonce'], segwit_data=self.share_info.get('segwit_data', None))
        
        assert other_tx_hashes2 == other_tx_hashes
        if share_info != self.share_info:
            raise ValueError('share_info invalid')
        if bitcoin_data.get_txid(gentx) != self.gentx_hash:
            raise ValueError('''gentx doesn't match hash_link''')
        if bitcoin_data.calculate_merkle_link([None] + other_tx_hashes, 0) != self.merkle_link: # the other hash commitments are checked in the share_info assertion
            raise ValueError('merkle_link and other_tx_hashes do not match')
        
        update_min_protocol_version(counts, self)

        return gentx # only used by as_block
示例#2
0
 def check(self, tracker):
     from p2pool import p2p
     if self.share_data['previous_share_hash'] is not None:
         previous_share = tracker.items[self.share_data['previous_share_hash']]
         if type(self) is type(previous_share):
             pass
         elif type(self) is type(previous_share).SUCCESSOR:
             if tracker.get_height(previous_share.hash) < self.net.CHAIN_LENGTH:
                 from p2pool import p2p
                 raise p2p.PeerMisbehavingError('switch without enough history')
             
             # switch only valid if 85% of hashes in [self.net.CHAIN_LENGTH*9//10, self.net.CHAIN_LENGTH] for new version
             counts = get_desired_version_counts(tracker,
                 tracker.get_nth_parent_hash(previous_share.hash, self.net.CHAIN_LENGTH*9//10), self.net.CHAIN_LENGTH//10)
             if counts.get(self.VERSION, 0) < sum(counts.itervalues())*85//100:
                 raise p2p.PeerMisbehavingError('switch without enough hash power upgraded')
         else:
             raise p2p.PeerMisbehavingError('''%s can't follow %s''' % (type(self).__name__, type(previous_share).__name__))
     
     other_tx_hashes = [tracker.items[tracker.get_nth_parent_hash(self.hash, share_count)].share_info['new_transaction_hashes'][tx_count] for share_count, tx_count in self.iter_transaction_hash_refs()]
     
     share_info, gentx, other_tx_hashes2, get_share = self.generate_transaction(tracker, self.share_info['share_data'], self.header['bits'].target, self.share_info['timestamp'], self.share_info['bits'].target, self.contents['ref_merkle_link'], [(h, None) for h in other_tx_hashes], self.net, last_txout_nonce=self.contents['last_txout_nonce'])
     assert other_tx_hashes2 == other_tx_hashes
     if share_info != self.share_info:
         raise ValueError('share_info invalid')
     if bitcoin_data.hash256(bitcoin_data.tx_type.pack(gentx)) != self.gentx_hash:
         raise ValueError('''gentx doesn't match hash_link''')
     
     if bitcoin_data.calculate_merkle_link([None] + other_tx_hashes, 0) != self.merkle_link:
         raise ValueError('merkle_link and other_tx_hashes do not match')
     
     return gentx # only used by as_block
示例#3
0
 def __init__(self, net, peer_addr, contents):
     self.net = net
     self.peer_addr = peer_addr
     self.contents = contents
     
     self.min_header = contents['min_header']
     self.share_info = contents['share_info']
     self.hash_link = contents['hash_link']
     self.merkle_link = contents['merkle_link']
     
     if not (2 <= len(self.share_info['share_data']['coinbase']) <= 100):
         raise ValueError('''bad coinbase size! %i bytes''' % (len(self.share_info['share_data']['coinbase']),))
     
     if len(self.merkle_link['branch']) > 16:
         raise ValueError('merkle branch too long!')
     
     assert not self.hash_link['extra_data'], repr(self.hash_link['extra_data'])
     
     self.share_data = self.share_info['share_data']
     self.max_target = self.share_info['max_bits'].target
     self.target = self.share_info['bits'].target
     self.timestamp = self.share_info['timestamp']
     self.previous_hash = self.share_data['previous_share_hash']
     self.new_script = bitcoin_data.pubkey_hash_to_script2(self.share_data['pubkey_hash'])
     self.desired_version = self.share_data['desired_version']
     self.absheight = self.share_info['absheight']
     self.abswork = self.share_info['abswork']
     
     n = set()
     for share_count, tx_count in self.iter_transaction_hash_refs():
         assert share_count < 110
         if share_count == 0:
             n.add(tx_count)
     assert n == set(range(len(self.share_info['new_transaction_hashes'])))
     
     self.gentx_hash = check_hash_link(
         self.hash_link,
         self.get_ref_hash(net, self.share_info, contents['ref_merkle_link']) + pack.IntType(64).pack(self.contents['last_txout_nonce']) + pack.IntType(32).pack(0),
         self.gentx_before_refhash,
     )
     merkle_root = bitcoin_data.check_merkle_link(self.gentx_hash, self.merkle_link)
     self.header = dict(self.min_header, merkle_root=merkle_root)
     self.pow_hash = net.PARENT.POW_FUNC(bitcoin_data.block_header_type.pack(self.header))
     #self.hash = self.header_hash = bitcoin_data.hash256(bitcoin_data.block_header_type.pack(self.header))
     self.hash = self.header_hash = net.PARENT.BLOCKHASH_FUNC(bitcoin_data.block_header_type.pack(self.header))
     
     if self.target > net.MAX_TARGET:
         from p2pool import p2p
         raise p2p.PeerMisbehavingError('share target invalid')
     
     if self.pow_hash > self.target:
         from p2pool import p2p
         raise p2p.PeerMisbehavingError('share PoW invalid')
     
     self.new_transaction_hashes = self.share_info['new_transaction_hashes']
     
     # XXX eww
     self.time_seen = time.time()
示例#4
0
 def handle_bestblock(self, header, peer):
     if self.node.net.PARENT.POW_FUNC(
             dash_data.block_header_type.pack(
                 header)) > header['bits'].target:
         raise p2p.PeerMisbehavingError(
             'received block header fails PoW test')
     self.node.handle_header(header)
示例#5
0
文件: data.py 项目: hua002/p2pool
def load_share(share, net, peer):
    if share['type'] in [0, 1, 2, 3, 4, 5, 6, 7, 8]:
        from p2pool import p2p
        raise p2p.PeerMisbehavingError('sent an obsolete share')
    elif share['type'] == Share.VERSION:
        return Share(net, peer, Share.share_type.unpack(share['contents']))
    else:
        raise ValueError('unknown share type: %r' % (share['type'],))
示例#6
0
def load_share(share, net, peer_addr):
    assert peer_addr is None or isinstance(peer_addr, tuple)
    if share['type'] < Share.VERSION:
        from p2pool import p2p
        raise p2p.PeerMisbehavingError('sent an obsolete share')
    elif share['type'] == Share.VERSION:
        return Share(net, peer_addr, Share.share_type.unpack(share['contents']))
    else:
        raise ValueError('unknown share type: %r' % (share['type'],))
示例#7
0
def load_share(share, net, peer_addr):
    assert peer_addr is None or isinstance(peer_addr, tuple)
    if share['type'] in share_versions:
        return share_versions[share['type']](net, peer_addr, share_versions[share['type']].get_dynamic_types(net)['share_type'].unpack(share['contents']))

    elif share['type'] < Share.VERSION:
        from p2pool import p2p
        raise p2p.PeerMisbehavingError('sent an obsolete share')
    else:
        raise ValueError('unknown share type: %r' % (share['type'],))
示例#8
0
def load_share(share, net, peer):
    if share['type'] in [0, 1, 2, 3]:
        from p2pool import p2p
        raise p2p.PeerMisbehavingError('sent an obsolete share')
    elif share['type'] == 4:
        return Share(net,
                     peer,
                     other_txs=None,
                     **Share.share1a_type.unpack(share['contents']))
    elif share['type'] == 5:
        share1b = Share.share1b_type.unpack(share['contents'])
        return Share(net,
                     peer,
                     merkle_link=bitcoin_data.calculate_merkle_link([0] + [
                         bitcoin_data.hash256(bitcoin_data.tx_type.pack(x))
                         for x in share1b['other_txs']
                     ], 0),
                     **share1b)
    else:
        raise ValueError('unknown share type: %r' % (share['type'], ))
示例#9
0
 def handle_bestblock(self, header, peer):
     if bitcoin_data.scrypt(bitcoin_data.block_header_type.pack(
             header)) > header['bits'].target:
         raise p2p.PeerMisbehavingError(
             'received block header fails PoW test')
     self.node.handle_header(header)
示例#10
0
    def check(self, tracker, known_txs=None, block_abs_height_func=None, feecache=None):
        from p2pool import p2p
        if self.timestamp > int(time.time()) + 600:
            raise ValueError("Share timestamp is %i seconds in the future! Check your system clock." %
                             self.timestamp - int(time.time()))
        counts = None
        if self.share_data['previous_share_hash'] is not None and block_abs_height_func is not None:
            previous_share = tracker.items[self.share_data['previous_share_hash']]
            if tracker.get_height(self.share_data['previous_share_hash']) >= self.net.CHAIN_LENGTH:
                counts = get_desired_version_counts(tracker, tracker.get_nth_parent_hash(
                    previous_share.hash, self.net.CHAIN_LENGTH*9//10), self.net.CHAIN_LENGTH//10)
                if type(self) is type(previous_share):
                    pass
                elif type(self) is type(previous_share).SUCCESSOR:
                    # switch only valid if 60% of hashes in [self.net.CHAIN_LENGTH*9//10, self.net.CHAIN_LENGTH] for new version
                    if counts.get(self.VERSION, 0) < sum(counts.itervalues())*60//100:
                        raise p2p.PeerMisbehavingError(
                            'switch without enough hash power upgraded')
                else:
                    raise p2p.PeerMisbehavingError('''%s can't follow %s''' % (
                        type(self).__name__, type(previous_share).__name__))
            elif type(self) is type(previous_share).SUCCESSOR:
                raise p2p.PeerMisbehavingError('switch without enough history')

        if self.VERSION < 34:
            other_tx_hashes = [tracker.items[tracker.get_nth_parent_hash(
                self.hash, share_count)].share_info['new_transaction_hashes'][tx_count] for share_count, tx_count in self.iter_transaction_hash_refs()]
        else:
            other_tx_hashes = []
        if known_txs is not None and not isinstance(known_txs, dict):
            print "Performing maybe-unnecessary packing and hashing"
            known_txs = dict((bitcoin_data.hash256(
                bitcoin_data.tx_type.pack(tx)), tx) for tx in known_txs)

        share_info, gentx, other_tx_hashes2, get_share = self.generate_transaction(tracker, self.share_info['share_data'], self.header['bits'].target, self.share_info['timestamp'], self.share_info['bits'].target, self.contents['ref_merkle_link'], [(h, None) for h in other_tx_hashes], self.net,
                                                                                   known_txs=None, last_txout_nonce=self.contents['last_txout_nonce'], segwit_data=self.share_info.get('segwit_data', None))

        if self.VERSION < 34:
            # check for excessive fees
            if self.share_data['previous_share_hash'] is not None and block_abs_height_func is not None:
                height = (block_abs_height_func(
                    self.header['previous_block'])+1)
                base_subsidy = self.net.PARENT.SUBSIDY_FUNC(height)
                fees = [feecache[x] for x in other_tx_hashes if x in feecache]
                missing = sum(
                    [1 for x in other_tx_hashes if not x in feecache])
                if missing == 0:
                    max_subsidy = sum(fees) + base_subsidy
                    details = "Max allowed = %i, requested subsidy = %i, share hash = %064x, miner = %s" % (
                        max_subsidy, self.share_data['subsidy'], self.hash,
                        self.address)
                    if self.share_data['subsidy'] > max_subsidy:
                        self.naughty = 1
                        print "Excessive block reward in share! Naughty. " + details
                    elif self.share_data['subsidy'] < max_subsidy:
                        print "Strange, we received a share that did not include as many coins in the block reward as was allowed. "
                        print "While permitted by the protocol, this causes coins to be lost forever if mined as a block, and costs us money."
                        print details

        if self.share_data['previous_share_hash'] and tracker.items[self.share_data['previous_share_hash']].naughty:
            print "naughty ancestor found %i generations ago" % tracker.items[
                self.share_data['previous_share_hash']].naughty
            # I am not easily angered ...
            print "I will not fail to punish children and grandchildren to the third and fourth generation for the sins of their parents."
            self.naughty = 1 + \
                tracker.items[self.share_data['previous_share_hash']].naughty
            if self.naughty > 6:
                self.naughty = 0

        assert other_tx_hashes2 == other_tx_hashes
        if share_info != self.share_info:
            raise ValueError('share_info invalid')
        if bitcoin_data.get_txid(gentx) != self.gentx_hash:
            raise ValueError('''gentx doesn't match hash_link''')
        if self.VERSION < 34:
            # the other hash commitments are checked in the share_info assertion
            if bitcoin_data.calculate_merkle_link([None] + other_tx_hashes, 0) != self.merkle_link:
                raise ValueError(
                    'merkle_link and other_tx_hashes do not match')

        update_min_protocol_version(counts, self)

        self.gentx_size = len(bitcoin_data.tx_id_type.pack(gentx))
        self.gentx_weight = len(
            bitcoin_data.tx_type.pack(gentx)) + 3*self.gentx_size

        # saving this share's gentx size as a class variable is an ugly hack, and you're welcome to hate me for doing it. But it works.
        type(self).gentx_size = self.gentx_size
        type(self).gentx_weight = self.gentx_weight

        _diff = self.net.PARENT.DUMB_SCRYPT_DIFF*float(
            bitcoin_data.target_to_difficulty(self.target))
        if not self.naughty:
            print("Received good share: diff=%.2e hash=%064x miner=%s" %
                  (_diff, self.hash, self.address))
        else:
            print("Received naughty=%i share: diff=%.2e hash=%064x miner=%s" %
                  (self.naughty, _diff, self.hash, self.address))
        return gentx  # only used by as_block
示例#11
0
    def __init__(self, net, peer_addr, contents):
        dynamic_types = self.get_dynamic_types(net)
        self.share_info_type = dynamic_types['share_info_type']
        self.share_type = dynamic_types['share_type']
        self.ref_type = dynamic_types['ref_type']

        self.net = net
        self.peer_addr = peer_addr
        self.contents = contents

        self.min_header = contents['min_header']
        self.share_info = contents['share_info']
        self.hash_link = contents['hash_link']
        self.merkle_link = contents['merkle_link']
        self.naughty = 0

        # save some memory if we can
        if self.VERSION < 34:
            txrefs = self.share_info['transaction_hash_refs']
            if txrefs and max(txrefs) < 2**16:
                self.share_info['transaction_hash_refs'] = array.array(
                    'H', txrefs)
            # in case we see blocks with more than 65536 tx in the future
            elif txrefs and max(txrefs) < 2**32:
                self.share_info['transaction_hash_refs'] = array.array(
                    'L', txrefs)

        segwit_activated = is_segwit_activated(self.VERSION, net)

        if not (2 <= len(self.share_info['share_data']['coinbase']) <= 100):
            raise ValueError('''bad coinbase size! %i bytes''' % (
                len(self.share_info['share_data']['coinbase']),))

        assert not self.hash_link['extra_data'], repr(
            self.hash_link['extra_data'])

        self.share_data = self.share_info['share_data']
        self.max_target = self.share_info['max_bits'].target
        self.target = self.share_info['bits'].target
        self.timestamp = self.share_info['timestamp']
        self.previous_hash = self.share_data['previous_share_hash']
        if self.VERSION >= 34:
            self.new_script = bitcoin_data.address_to_script2(
                self.share_data['address'], net.PARENT)
            self.address = self.share_data['address']
        else:
            self.new_script = bitcoin_data.pubkey_hash_to_script2(
                self.share_data['pubkey_hash'],
                net.PARENT.ADDRESS_VERSION, -1, net.PARENT)
            self.address = bitcoin_data.pubkey_hash_to_address(
                self.share_data['pubkey_hash'],
                net.PARENT.ADDRESS_VERSION, -1, net.PARENT)
        self.desired_version = self.share_data['desired_version']
        self.absheight = self.share_info['absheight']
        self.abswork = self.share_info['abswork']
        if net.NAME == 'bitcoin' and self.absheight > 3927800 and self.desired_version == 16:
            raise ValueError("This is not a hardfork-supporting share!")

        if self.VERSION < 34:
            n = set()
            for share_count, tx_count in self.iter_transaction_hash_refs():
                assert share_count < 110
                if share_count == 0:
                    n.add(tx_count)
            assert n == set(
                range(len(self.share_info['new_transaction_hashes'])))

        self.gentx_hash = check_hash_link(
            self.hash_link,
            self.get_ref_hash(net, self.share_info, contents['ref_merkle_link']) + pack.IntType(
                64).pack(self.contents['last_txout_nonce']) + pack.IntType(32).pack(0),
            self.gentx_before_refhash,
        )
        merkle_root = bitcoin_data.check_merkle_link(
            self.gentx_hash, self.share_info['segwit_data']['txid_merkle_link'] if segwit_activated else self.merkle_link)
        self.header = dict(self.min_header, merkle_root=merkle_root)
        self.pow_hash = net.PARENT.POW_FUNC(
            bitcoin_data.block_header_type.pack(self.header))
        self.hash = self.header_hash = bitcoin_data.hash256(
            bitcoin_data.block_header_type.pack(self.header))

        if self.target > net.MAX_TARGET:
            from p2pool import p2p
            raise p2p.PeerMisbehavingError('share target invalid')

        if self.pow_hash > self.target:
            from p2pool import p2p
            raise p2p.PeerMisbehavingError('share PoW invalid')

        if self.VERSION < 34:
            self.new_transaction_hashes = self.share_info['new_transaction_hashes']

        # XXX eww
        self.time_seen = time.time()
示例#12
0
    def __init__(self, net, peer, common, merkle_link, other_txs):
        self.net = net
        self.peer = peer
        self.common = common
        self.min_header = common['min_header']
        self.share_info = common['share_info']
        self.hash_link = common['hash_link']
        self.merkle_link = merkle_link
        self.other_txs = other_txs

        if len(self.share_info['share_data']['coinbase']) > 100:
            raise ValueError(
                '''coinbase too large! %i bytes''' %
                (len(self.share_info['share_data']['coinbase']), ))

        if len(merkle_link['branch']) > 16:
            raise ValueError('merkle branch too long!')

        if p2pool.DEBUG and other_txs is not None and bitcoin_data.calculate_merkle_link(
            [0] + [
                bitcoin_data.hash256(bitcoin_data.tx_type.pack(x))
                for x in other_txs
            ], 0) != merkle_link:
            raise ValueError('merkle_link and other_txs do not match')

        assert not self.hash_link['extra_data'], repr(
            self.hash_link['extra_data'])

        self.share_data = self.share_info['share_data']
        self.max_target = self.share_info['max_bits'].target
        self.target = self.share_info['bits'].target
        self.timestamp = self.share_info['timestamp']
        self.previous_hash = self.share_data['previous_share_hash']
        self.new_script = bitcoin_data.pubkey_hash_to_script2(
            self.share_data['pubkey_hash'])
        self.desired_version = self.share_data['desired_version']

        self.gentx_hash = check_hash_link(
            self.hash_link,
            self.get_ref_hash(net, self.share_info, common['ref_merkle_link'])
            + pack.IntType(32).pack(0),
            self.gentx_before_refhash,
        )
        merkle_root = bitcoin_data.check_merkle_link(self.gentx_hash,
                                                     merkle_link)
        self.header = dict(self.min_header, merkle_root=merkle_root)
        self.pow_hash = net.PARENT.POW_FUNC(
            bitcoin_data.block_header_type.pack(self.header))
        self.hash = self.header_hash = bitcoin_data.hash256(
            bitcoin_data.block_header_type.pack(self.header))

        if self.pow_hash > self.target:
            from p2pool import p2p
            raise p2p.PeerMisbehavingError('share PoW invalid')

        if other_txs is not None and not self.pow_hash <= self.header[
                'bits'].target:
            raise ValueError('other_txs provided when not a block solution')
        if other_txs is None and self.pow_hash <= self.header['bits'].target:
            raise ValueError('other_txs not provided when a block solution')

        # XXX eww
        self.time_seen = time.time()