Esempio n. 1
0
    async def generate(cls,
                       config,
                       transactions,
                       public_key,
                       private_key,
                       force_version=None,
                       index=None,
                       force_time=None):
        try:
            mongo = config.mongo
            app_log = getLogger("tornado.application")
            if force_version is None:
                version = CHAIN.get_version_for_height(index)
            else:
                version = force_version
            if force_time:
                xtime = str(int(force_time))
            else:
                xtime = str(int(time.time()))
            index = int(index)
            if index == 0:
                prev_hash = ''
            else:
                prev_hash = config.BU.get_latest_block()['hash']

            transaction_objs = []
            fee_sum = 0.0
            used_sigs = []
            for txn in transactions:
                try:
                    if isinstance(txn, FastGraph):
                        transaction_obj = txn
                    else:
                        transaction_obj = FastGraph.from_dict(index, txn)

                    if transaction_obj.transaction_signature in used_sigs:
                        print('duplicate transaction found and removed')
                        continue

                    if not transaction_obj.verify():
                        raise InvalidTransactionException(
                            "invalid transactions")

                    used_sigs.append(transaction_obj.transaction_signature)

                except:
                    try:
                        if isinstance(txn, Transaction):
                            transaction_obj = txn
                        else:
                            transaction_obj = Transaction.from_dict(index, txn)

                        if transaction_obj.transaction_signature in used_sigs:
                            print('duplicate transaction found and removed')
                            continue

                        transaction_obj.verify()
                        used_sigs.append(transaction_obj.transaction_signature)
                    except:
                        raise InvalidTransactionException(
                            "invalid transactions")
                try:
                    if int(index) > CHAIN.CHECK_TIME_FROM and (
                            int(transaction_obj.time) >
                            int(xtime) + CHAIN.TIME_TOLERANCE):
                        app_log.debug("Block embeds txn too far in the future")
                        continue

                    transaction_objs.append(transaction_obj)

                    fee_sum += float(transaction_obj.fee)
                except Exception as e:
                    await mongo.async_db.miner_transactions.delete_many(
                        {'id': transaction_obj.transaction_signature})
                    if config.debug:
                        app_log.debug('Exception {}'.format(e))
                    else:
                        continue

            block_reward = CHAIN.get_block_reward(index)
            coinbase_txn_fctry = TransactionFactory(
                index,
                public_key=public_key,
                private_key=private_key,
                outputs=[{
                    'value':
                    block_reward + float(fee_sum),
                    'to':
                    str(
                        P2PKHBitcoinAddress.from_pubkey(
                            bytes.fromhex(public_key)))
                }],
                coinbase=True)
            coinbase_txn = coinbase_txn_fctry.generate_transaction()
            transaction_objs.append(coinbase_txn)

            transactions = transaction_objs
            block_factory = cls()
            block = Block(version=version,
                          block_time=xtime,
                          block_index=index,
                          prev_hash=prev_hash,
                          transactions=transactions,
                          public_key=public_key)
            txn_hashes = block.get_transaction_hashes()
            block.set_merkle_root(txn_hashes)
            block.merkle_root = block.verify_merkle_root
            block_factory.block = block
            return block_factory
        except Exception as e:
            import sys, os
            print("Exception {} BlockFactory".format(e))
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            print(exc_type, fname, exc_tb.tb_lineno)
            raise
Esempio n. 2
0
"""
Temp. test for block reward function precision
"""

import sys
import random

sys.path.append('../')
from yadacoin.chain import CHAIN


if __name__ == "__main__":
    for i in range(1000):
        index = random.randint(1, 6930000+21000)
        value1 = CHAIN.get_block_reward_deprecated(index)
        value2 = CHAIN.get_block_reward(index)
        if value1 != value2:
            print("Error", index, value1, value2)

    # boundary tests
    test2 = (2519999, 2520000, 2520001, 2729999, 2730000, 2730001)
    for index in test2:
        value1 = CHAIN.get_block_reward_deprecated(index)
        value2 = CHAIN.get_block_reward(index)
        if value1 != value2:
            print("Error2", index, value1, value2)

Esempio n. 3
0
    def verify(self):
        try:
            getcontext().prec = 8
            if int(self.version) != int(
                    CHAIN.get_version_for_height(self.index)):
                raise Exception("Wrong version for block height", self.version,
                                CHAIN.get_version_for_height(self.index))

            txns = self.get_transaction_hashes()
            self.set_merkle_root(txns)
            if self.verify_merkle_root != self.merkle_root:
                raise Exception("Invalid block merkle root")

            header = BlockFactory.generate_header(self)
            hashtest = BlockFactory.generate_hash_from_header(
                header, str(self.nonce))
            # print("header", header, "nonce", self.nonce, "hashtest", hashtest)
            if self.hash != hashtest:
                getLogger("tornado.application").warning(
                    "Verify error hashtest {} header {} nonce {}".format(
                        hashtest, header, self.nonce))
                raise Exception('Invalid block hash')

            address = P2PKHBitcoinAddress.from_pubkey(
                bytes.fromhex(self.public_key))
            try:
                # print("address", address, "sig", self.signature, "pubkey", self.public_key)
                result = verify_signature(base64.b64decode(self.signature),
                                          self.hash.encode('utf-8'),
                                          bytes.fromhex(self.public_key))
                if not result:
                    raise Exception("block signature1 is invalid")
            except:
                try:
                    result = VerifyMessage(
                        address,
                        BitcoinMessage(self.hash.encode('utf-8'), magic=''),
                        self.signature)
                    if not result:
                        raise
                except:
                    raise Exception("block signature2 is invalid")

            # verify reward
            coinbase_sum = 0
            for txn in self.transactions:
                if int(self.index) > CHAIN.CHECK_TIME_FROM and (int(
                        txn.time) > int(self.time) + CHAIN.TIME_TOLERANCE):
                    raise Exception("Block embeds txn too far in the future")

                if txn.coinbase:
                    for output in txn.outputs:
                        coinbase_sum += float(output.value)

            fee_sum = 0.0
            for txn in self.transactions:
                if not txn.coinbase:
                    fee_sum += float(txn.fee)
            reward = CHAIN.get_block_reward(self.index)

            #if Decimal(str(fee_sum)[:10]) != Decimal(str(coinbase_sum)[:10]) - Decimal(str(reward)[:10]):
            """
            KO for block 13949
            0.02099999 50.021 50.0
            Integrate block error 1 ('Coinbase output total does not equal block reward + transaction fees', 0.020999999999999998, 0.021000000000000796)
            """
            if quantize_eight(fee_sum) != quantize_eight(coinbase_sum -
                                                         reward):
                print(fee_sum, coinbase_sum, reward)
                raise Exception(
                    "Coinbase output total does not equal block reward + transaction fees",
                    fee_sum, (coinbase_sum - reward))
        except Exception as e:
            exc_type, exc_obj, exc_tb = exc_info()
            fname = path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            getLogger("tornado.application").warning("verify {} {} {}".format(
                exc_type, fname, exc_tb.tb_lineno))
            raise