Beispiel #1
0
    def commit(self, chain, block, address_txn, ignore_save_wallet=False):
        # FIXME: This indexing approach is very inefficient

        blocks_left = helper.get_blocks_left(block.blockheader.blocknumber)

        staker = block.blockheader.stake_selector
        self.stake_validators_list.sv_list[staker].nonce += 1

        for address in address_txn:
            self._save_address_state(address, address_txn[address])

        for dup_tx in block.duplicate_transactions:
            if dup_tx.coinbase1.txto in self.stake_validators_list.sv_list:
                self.stake_validators_list.sv_list[dup_tx.coinbase1.txto].is_banned = True

        if blocks_left == 1:
            logger.info('EPOCH change: resetting stake_list, activating next_stake_list, updating PRF with '
                        'seed+entropy updating wallet hashchains..')

            self.stake_validators_list.move_next_epoch()
            # TODO: To be fixed later
            #self.stake_list_put(self.stake_validators_list.to_json())

            xmss = chain.wallet.address_bundle[0].xmss
            tmphc = hashchain(xmss.get_seed_private(), epoch=block.blockheader.epoch + 1)

            chain.hash_chain = tmphc.hashchain
            if not ignore_save_wallet:
                chain.wallet.save_wallet()

        self.state_set_blockheight(chain.height() + 1)

        logger.debug('%s %s tx passed verification.', bin2hstr(block.blockheader.headerhash), len(block.transactions))
        return True
Beispiel #2
0
    def state_add_block(self, chain, block, ignore_save_wallet=False):
        address_txn = dict()
        self.load_address_state(chain, block, address_txn)                                  # FIXME: Bottleneck

        if block.blockheader.blocknumber == 1:
            if not self.state_update_genesis(chain, block, address_txn):
                return False
            self.commit(chain, block, address_txn, ignore_save_wallet=ignore_save_wallet)
            return True

        blocks_left = helper.get_blocks_left(block.blockheader.blocknumber)
        nonce = self.stake_validators_list.sv_list[block.transactions[0].txto].nonce
        logger.debug('BLOCK: %s epoch: %s blocks_left: %s nonce: %s stake_selector %s',
                     block.blockheader.blocknumber,
                     block.blockheader.epoch,
                     blocks_left - 1,
                     nonce,
                     block.blockheader.stake_selector)

        if not self.state_update(block, self.stake_validators_list, address_txn):
            return

        self.commit(chain, block, address_txn, ignore_save_wallet=ignore_save_wallet)       # FIXME: Bottleneck

        return True
Beispiel #3
0
    def commit(self, block, stake_validators_list):
        blocknumber = block.blockheader.blocknumber
        blocks_left = get_blocks_left(blocknumber)
        stake_validators_list.sv_list[block.blockheader.stake_selector].nonce += 1
        for dup_tx in block.duplicate_transactions:
            if dup_tx.coinbase1.txto in stake_validators_list.sv_list:
                stake_validators_list.sv_list[dup_tx.coinbase1.txto].is_banned = True

        if blocks_left == 1:
            stake_validators_list.move_next_epoch()
            self.update_hash_chain(blocknumber)
Beispiel #4
0
    def state_update(self, block, stake_validators_list, address_txn):

        # reminder contents: (state address -> nonce, balance, [pubhash]) (stake -> address, hash_term, nonce)

        blocks_left = helper.get_blocks_left(block.blockheader.blocknumber)

        if block.blockheader.stake_selector not in stake_validators_list.sv_list:
            logger.warning('stake selector not in stake_list_get')
            return

        if stake_validators_list.sv_list[block.blockheader.stake_selector].is_banned:
            logger.warning('stake selector is in banned list')
            return
        # cycle through every tx in the new block to check state
        for tx in block.transactions:

            pubhash = tx.generate_pubhash(tx.PK, tx.ots_key)

            if tx.subtype == TX_SUBTYPE_COINBASE:
                expected_nonce = stake_validators_list.sv_list[tx.txfrom].nonce + 1
            else:
                expected_nonce = address_txn[tx.txfrom][0] + 1
            if tx.nonce != expected_nonce:
                logger.warning('nonce incorrect, invalid tx')
                logger.warning('subtype: %s', tx.subtype)
                logger.warning('%s actual: %s expected: %s', tx.txfrom, tx.nonce, expected_nonce)
                return False
            # TODO: To be fixed later
            if pubhash in address_txn[tx.txfrom][2]:
                logger.warning('pubkey reuse detected: invalid tx %s', tx.txhash)
                logger.warning('subtype: %s', tx.subtype)
                logger.info(pubhash)
                logger.info(address_txn[tx.txfrom][2])
                return False

            if tx.subtype == TX_SUBTYPE_TX:
                if address_txn[tx.txfrom][1] - tx.amount < 0:
                    logger.warning('%s %s exceeds balance, invalid tx', tx, tx.txfrom)
                    logger.warning('subtype: %s', tx.subtype)
                    logger.warning('Buffer State Balance: %s  Transfer Amount %s', address_txn[tx.txfrom][1], tx.amount)
                    return False

            elif tx.subtype == TX_SUBTYPE_STAKE:
                epoch_blocknum = config.dev.blocks_per_epoch - blocks_left
                if (not tx.first_hash) and epoch_blocknum >= config.dev.stake_before_x_blocks:
                    logger.warning('Block rejected #%s due to ST without first_reveal beyond limit',
                                   block.blockheader.blocknumber)
                    logger.warning('Stake_selector: %s', block.blockheader.stake_selector)
                    logger.warning('epoch_blocknum: %s Threshold: %s',
                                   epoch_blocknum,
                                   config.dev.stake_before_x_blocks)
                    return False

                address_txn[tx.txfrom][2].append(pubhash)
                next_sv_list = stake_validators_list.next_sv_list
                if tx.txfrom in next_sv_list:
                    if not next_sv_list[tx.txfrom].first_hash and tx.first_hash:
                        threshold_blocknum = stake_validators_list.get_threshold(tx.txfrom)
                        if epoch_blocknum < threshold_blocknum - 1:
                            logger.warning('Block rejected #%s due to ST before threshold',
                                           block.blockheader.blocknumber)
                            logger.warning('Stake_selector: %s', block.blockheader.stake_selector)
                            logger.warning('epoch_blocknum: %s Threshold: %s',
                                           epoch_blocknum,
                                           threshold_blocknum - 1)
                            return False
                        stake_validators_list.set_first_hash(tx.txfrom, tx.first_hash)
                else:
                    stake_validators_list.add_next_sv(tx.txfrom, tx.slave_public_key, tx.hash, tx.first_hash, tx.balance)

            if tx.subtype != TX_SUBTYPE_COINBASE:
                address_txn[tx.txfrom][0] += 1

            if tx.subtype == TX_SUBTYPE_TX:
                address_txn[tx.txfrom][1] -= tx.amount - tx.fee

            if tx.subtype in (TX_SUBTYPE_TX, TX_SUBTYPE_COINBASE):
                address_txn[tx.txto][1] += tx.amount

            address_txn[tx.txfrom][2].append(pubhash)

        return True