Пример #1
0
def getInitialUser():
    private_key = ed25519.Ed25519PrivateKey.from_private_bytes(
        bytes.fromhex(
            "1d82897e5881368cac9eb99126cdfca1e0317629dbeaa7280484c5dae81e932b")
    )
    public_key = ed25519.Ed25519PublicKey.from_public_bytes(
        bytes.fromhex(
            "75efa6f1fdf1393a5ea815b2b3690293d079df187944f22ec79f3380ef7bd743")
    )
    txns = [
        Transaction.build_signed_txn(
            "75efa6f1fdf1393a5ea815b2b3690293d079df187944f22ec79f3380ef7bd743",
            [], [
                OutFlow(
                    10000,
                    "75efa6f1fdf1393a5ea815b2b3690293d079df187944f22ec79f3380ef7bd743"
                )
            ],
            "1d82897e5881368cac9eb99126cdfca1e0317629dbeaa7280484c5dae81e932b")
    ]

    # Note that we need two hexadecimal digits for the bytes.fromhex( str ) method to work,
    # hence we include two zeros
    block_obj = Block("00", txns, 0)

    success = False
    while not success:
        magic_num = os.urandom(32).hex()
        block_obj.magic_num = magic_num
        if int(block_obj.get_hash(), 16) & 0xFFFF == 0xCCCC:
            success = True
    print(json.dumps(block_obj.serialize()))
 def test_block(self):
     args = (0, "0", int(time.time()), "test")
     nonce = 0
     target = "f" * 64
     hash = Block.calculate_hash(*args, nonce, target)
     b = Block(*args, nonce=nonce, target=target, hash=hash)
     self.assertSerializable(Block, b, globals())
     self.assertTrue(b.valid)
     b.hash = "aaa"
     self.assertFalse(b.valid)
Пример #3
0
    def mine(self):
        """ Looks in redis for transactions and mines them to find the answer to the puzzle
        """
        print("Mining")

        prev_hash = self.r.get(PREV_HASH_KEY)
        if prev_hash:
            prev_hash = prev_hash.decode('utf-8')

        block = Block(prev_hash)

        # wait to fill the block with transactions
        while not block.full():
            # in between mining
            if self.stop_mining():
                print("Someone mined the coins")
                l = len(block.transactions)
                left = TRANSACTIONS_IN_BLOCK - l
                for _ in range(left):
                    self.r.blpop(TRANSACTION_QUEUE_KEY)
                return None

            print("Searching for transactions to fill the block")
            # blocking pop from transaction key
            transaction = Transaction.from_redis(
                self.r,
                json.loads(
                    self.r.blpop(TRANSACTION_QUEUE_KEY)[1].decode('utf-8')))
            print("found a transaction, adding it to block")
            block.add_transaction(transaction)

        # create a new transaction that creates a lazycoin and gives it to the user
        print("Block is full, now add a create transaction")
        print("Prev hash = ", prev_hash)
        create = Transaction(
            prev_hash=prev_hash,
            transaction_type='CREATE',
            sender=self.user.pub,
            receiver=self.user.pub,
        )

        # sign this transaction and add the signature to the transaction
        print("signing transaction")
        msg, sign = self.user.sign(create)
        create.add_signature(sign)

        print("adding transaction")
        block.add_transaction(create)

        print("finding nonce")
        nonce = self.solve_puzzle(block)

        block.add_nonce(nonce)
        print("block done")

        if self.stop_mining():
            print("stopping mining")
            return None

        return block
Пример #4
0
 def __mining(self) -> Optional[Block]:
     """挖矿"""
     trans_list = self.__get_mining_trans()
     with FullBlockChain.safe_use_blockchain() as blc:
         block = Block(blc.get_height() + 1, blc.get_top_hash())
     # 计算总交易费
     fee = Btc("0")
     for trans in trans_list:
         fee += blc.compute_transaction_fee(trans)
         block.add_transaction(trans)  # 添加交易到block中
     # 加上矿工奖励
     fee += block.get_now_ming_btcs()
     # 构造创块交易
     head_trans = Transaction()
     head_trans.add_output(TransOutput(address=self.address, btcs=fee))
     block.set_head_transaction(head_trans)
     # 正式开始挖矿
     while not block.veri_hash():
         if self.mine_flag:
             block.randnum += MINING_ADD_NUM
             block.timestap = time.time()
         else:  # 中止挖矿(失败了)
             self.add_trans(*trans_list)  # 把交易放回交易池
             return None
     return block
Пример #5
0
    def test_block_message(self):
        message = messages.msg_block()
        cblock = CBlock()
        message.block = cblock

        block = Block(None, BlockOrigin.private)
        block.cached_hash = message.block.GetHash()

        self.chain.blocks = {block.hash(): block}

        self.networking.block_message(self.private_connection, message)

        self.assertEqual(self.chain.blocks[block.hash()].cblock, cblock)
Пример #6
0
    def test_block_message_remove_from_blocks_in_flight(self):
        message = messages.msg_block()
        cblock = CBlock()
        message.block = cblock

        block = Block(None, BlockOrigin.private)
        block.cached_hash = message.block.GetHash()

        self.chain.blocks = {block.hash(): block}
        self.networking.blocks_in_flight = {block.hash(): 'in_flight'}

        self.networking.block_message(self.private_connection, message)

        self.assertEqual(len(self.networking.blocks_in_flight), 0)
Пример #7
0
    def test_block_message_two_times(self):
        message = messages.msg_block()
        cblock1 = CBlock(nNonce=1)
        cblock2 = CBlock(nNonce=2)
        message.block = cblock1

        block = Block(None, BlockOrigin.private)
        block.cached_hash = message.block.GetHash()

        self.chain.blocks = {block.hash(): block}

        self.networking.block_message(self.private_connection, message)
        message.block = cblock2
        self.networking.block_message(self.private_connection, message)
Пример #8
0
def init():
    # 删除旧文件
    if os.path.isfile(STORE_BLC_FILE_PATH):
        os.remove(STORE_BLC_FILE_PATH)
    if os.path.isfile(STORE_KEYS_FILE_PATH):
        os.remove(STORE_KEYS_FILE_PATH)
    # 打开N服务和B服务
    NetworkRouting.get_instance().start_server()
    FullBlockChain.get_instance().start_server()
    # 添加创世区块
    keys = [UserKey() for i in range(10)]
    for key in keys:
        Wallet.get_instance().add_key(key)
    Miner.get_instance().set_wallet_address(keys[0].get_address())
    t = Transaction()
    for key in keys:
        t.add_output(TransOutput(Btc("1000"), key.get_address()))
    block = Block(1)
    block.add_transaction(t)
    head_trans = Transaction()
    head_trans.add_output(TransOutput(Btc(MINING_BTCS), keys[0].get_address()))
    block.set_head_transaction(head_trans)
    block.find_randnum()
    FullBlockChain.get_instance().add_first_block(block)
    Wallet.get_instance().write_keys_to_file()
Пример #9
0
 def get_block(self, index: int) -> Block:
     """取出指定索引块"""
     with self.__auto_commit() as cusor:
         fet = cusor.execute(
             f"select block from blockchain where \"index\"={index}")
         b = fet.fetchone()[0]
         return Block.load(b)
Пример #10
0
    def test_adopt_two_blocks_lead_public(self):
        third_block_chain_b = Block(CBlock(), BlockOrigin.public)
        third_block_chain_b.height = 3
        third_block_chain_b.prevBlock = self.second_block_chain_b
        third_block_chain_b.cached_hash = '3b'

        self.executor.execute(Action.adopt, self.first_block_chain_a, third_block_chain_b)

        self.assertTrue(self.networking.send_inv.called)

        blocks = [block.hash() for block in self.networking.send_inv.call_args[0][0]]

        self.assertEqual(len(blocks), 3)
        self.assertTrue('1b' in blocks)
        self.assertTrue('2b' in blocks)
        self.assertTrue('3b' in blocks)
Пример #11
0
    def test_override_two_blocks_lead_private(self):
        third_block_chain_a = Block(CBlock(), BlockOrigin.private)
        third_block_chain_a.height = 3
        third_block_chain_a.prevBlock = self.second_block_chain_a
        third_block_chain_a.cached_hash = '3a'

        self.executor.execute(Action.override, third_block_chain_a, self.first_block_chain_b)

        self.assertTrue(self.networking.send_inv.called)

        blocks = [block.hash() for block in self.networking.send_inv.call_args[0][0]]

        self.assertEqual(len(blocks), 3)
        self.assertTrue('1a' in blocks)
        self.assertTrue('2a' in blocks)
        self.assertTrue('1b' in blocks)
Пример #12
0
 def __init__(self) -> None:
     self.trans_cache = MyQueue()  # 交易池
     self.trans_num = MAX_USER_TRANSACTION_NUMBER  # 一个区块打包多少个交易
     self.address = ""  # 获取收益的地址
     self.server_flag = True
     self.mine_flag = True
     self.trans_later = Transaction()
     self.block_later = Block()
Пример #13
0
    def test_getdata_message_with_block(self):
        cblock = CBlock()
        block = Block(cblock, BlockOrigin.private)
        block.cblock = cblock
        message = messages.msg_getdata()
        cInv = CInv()
        cInv.type = networking.inv_typemap['Block']
        cInv.hash = cblock.GetHash()
        message.inv = [cInv]

        self.chain.blocks = {cblock.GetHash(): block}

        self.networking.getdata_message(self.public_connection1, message)

        self.assertTrue(self.public_connection1.send.called)
        self.assertEqual(self.public_connection1.send.call_args[0][0], 'block')
        self.assertEqual(self.public_connection1.send.call_args[0][1].block,
                         cblock)
Пример #14
0
    def test_block_message_deferred_requests(self):
        message = messages.msg_block()
        cblock = CBlock()
        hash_ = cblock.GetHash()
        message.block = cblock

        block = Block(None, BlockOrigin.private)
        block.cached_hash = hash_

        self.networking.deferred_block_requests = \
            {hash_: [self.private_connection.host[0], self.public_connection2.host[0]]}
        self.networking.send_block = MagicMock()

        self.networking.block_message(self.public_connection1, message)

        self.assertEqual(len(self.networking.deferred_block_requests), 0)
        self.assertEqual(self.networking.send_block.call_count, 2)
        self.assertEqual(self.networking.send_block.call_args[0][1], cblock)
Пример #15
0
 def verify_new_block(cls, block: Block) -> bool:
     """验证一个新块"""
     if not cls.verify_block_depth(block):
         return False
     # pre_hash的值要正确
     if block.get_prehash() != BlockChain.get_instance().get_top_block(
     ).get_hash():
         return False
     # 验证每笔交易的有效性
     inputs = []
     for trans in block.get_user_transactions():
         if not cls.verify_new_transaction(trans):
             return False
         inputs.extend(trans.get_inputs())
     # 不同的交易不能有相同的输入
     if len(set(inputs)) != len(inputs):
         return False
     return True
Пример #16
0
 def run():
     """接收区块,广播区块线程"""
     while self.server_flag:
         node, msg = B_mailbox.get()
         if msg.type == "PUT":
             if msg.command == "BLOCK":  # 添加新块,广播新块
                 block = Block.load(msg.data)
                 if self.add_new_block(block):
                     NetworkRouting.get_instance().broad_a_msg(msg)
         elif msg.type == "GET":
             pass  # TODO
Пример #17
0
 def verify_block_depth(cls, block: Block) -> bool:
     """深入验证区块(包括区块中的交易)"""
     if not cls.verify_block(block):
         return False
     # 验证用户的交易
     for trans in block.get_user_transactions():
         if not cls.verify_transaction(trans):
             return False
     # 验证第一笔交易
     trans = block.get_head_transaction()
     # 计算交易费
     fee = BlockChain.get_instance().compute_block_fee(block)
     # 计算矿工奖励
     mini_fee = trans.compute_outputs_btcs() - fee
     # 计算这个区块时的矿工奖励
     mini_btcs = block.get_now_ming_btcs()
     # 验证矿工奖励合法性
     if mini_fee != mini_btcs:
         return False
     return True
Пример #18
0
    def test_getdata_message_with_two_blocks(self):
        cblock1 = CBlock()
        block1 = Block(cblock1, BlockOrigin.private)
        block1.cblock = cblock1
        cInv1 = CInv()
        cInv1.type = networking.inv_typemap['Block']
        cInv1.hash = cblock1.GetHash()
        cblock2 = CBlock()
        block2 = Block(cblock2, BlockOrigin.private)
        block2.cblock = cblock2
        cInv2 = CInv()
        cInv2.type = networking.inv_typemap['Block']
        cInv2.hash = cblock2.GetHash()
        message = messages.msg_getdata()
        message.inv = [cInv1, cInv2]

        self.chain.blocks = {
            cblock1.GetHash(): block1,
            cblock2.GetHash(): block2
        }

        self.networking.getdata_message(self.public_connection1, message)

        self.assertTrue(self.public_connection1.send.called)
        self.assertEqual(self.public_connection1.send.call_count, 2)
Пример #19
0
    def setUp(self):
        self.networking = MagicMock()
        self.executor = Executor(self.networking)

        self.first_block_chain_b = Block(CBlock(), BlockOrigin.public)
        self.first_block_chain_b.height = 1
        self.first_block_chain_b.prevBlock = test_util.genesis_block
        self.first_block_chain_b.cached_hash = '1b'

        self.second_block_chain_b = Block(CBlock(), BlockOrigin.public)
        self.second_block_chain_b.height = 2
        self.second_block_chain_b.prevBlock = self.first_block_chain_b
        self.second_block_chain_b.cached_hash = '2b'

        self.first_block_chain_a = Block(CBlock(), BlockOrigin.private)
        self.first_block_chain_a.height = 1
        self.first_block_chain_a.prevBlock = test_util.genesis_block
        self.first_block_chain_a.cached_hash = '1a'

        self.second_block_chain_a = Block(CBlock(), BlockOrigin.private)
        self.second_block_chain_a.height = 2
        self.second_block_chain_a.prevBlock = self.first_block_chain_a
        self.second_block_chain_a.cached_hash = '2a'
Пример #20
0
    def test_match_lead_public(self):
        private_tip = Block(CBlock(), None)
        private_tip.height = 1

        public_tip = Block(CBlock(), None)
        public_tip.height = 2

        with self.assertRaisesRegexp(ActionException, "private tip.*must >= then public tip.*match.*"):
            self.executor.execute(Action.match, private_tip, public_tip)
Пример #21
0
    async def proof_of_work(self):
        nonce = 0
        tx = None
        while True:
            h = sha256()
            difficulty = consensus.get_difficulty(self.chain_mgr.chain.chain)
            target = consensus.STANDARD_TARGET / difficulty
            prev_block = self.chain_mgr.chain.chain[-1]
            if not tx:
                # Poll transaction updates
                tx = self.pop_transaction()
            block = Block(
                **{
                    'index': prev_block.index + 1,
                    'timestamp': time.time(),
                    'data': {
                        'transactions': [tx.__dict__]
                    } if tx else 'mining test',
                    'prev_hash': prev_block.hash,
                    'difficulty': difficulty,
                })

            logger.info('Tx: {}'.format(tx))
            h.update('{}{}{}'.format(prev_block, block, nonce).encode('utf8'))
            hash_value = int(h.hexdigest(), 16)
            logger.info(
                'Hashed block{}@ difficulty={} nonce={} result={}'.format(
                    block.index, difficulty, nonce, h.hexdigest()))

            if hash_value < target:
                logger.info(
                    'solution found! {} @ target: {}, index: {}'.format(
                        nonce, target, block.index))
                block.nonce = nonce
                return block
            await asyncio.sleep(1)  # 1h/s
            nonce += 1
Пример #22
0
    def test_adopt_same_height(self):
        private_tip = Block(CBlock(), None)
        private_tip.height = 2

        public_tip = Block(CBlock(), None)
        public_tip.height = 2

        with self.assertRaisesRegexp(ActionException, "public tip.*must > then private tip.*adopt.*"):
            self.executor.execute(Action.adopt, private_tip, public_tip)
Пример #23
0
    def test_override_same_height(self):
        private_tip = Block(CBlock(), None)
        private_tip.height = 2

        public_tip = Block(CBlock(), None)
        public_tip.height = 2

        with self.assertRaisesRegexp(ActionException, "private tip.*must > then public tip.*override.*"):
            self.executor.execute(Action.override, private_tip, public_tip)
Пример #24
0
    def test_insert_block_initializing_false(self):
        prevBlock = Block(CBlock(), BlockOrigin.private)
        prevBlock.cached_hash = 'hash2'
        prevBlock.height = 45
        block = Block(CBlock(), BlockOrigin.private)
        block.cached_hash = 'hash1'
        self.chain.tips = [prevBlock]
        self.chain.initializing = False

        self.chain.insert_block(prevBlock, block)

        retrieved_block = self.chain.tips[0]
        self.assertEqual(retrieved_block, block)
        self.assertEqual(retrieved_block.transfer_allowed, False)
Пример #25
0
    def handle_receive_latest_block(self, block: dict) -> None:
        peer_block = Block.deserialize(block)
        latest_block = self.blockchain.latest_block
        is_added = self.blockchain.add_block(peer_block)
        if is_added:
            self.server.broadcast_message(
                Message.send_latest_block(peer_block))
        elif latest_block.index < peer_block.index:
            # peer is longer, ask for blockchain
            logger.debug("Having no latest block. Asking for blockchain")
            self.server.broadcast_message(Message.get_blockchain())
        else:
            # I'm on the edge!
            pass

        self.transport.close()
Пример #26
0
 def recv_broad_transaction():
     """接收交易、广播交易的进程"""
     while self.server_flag:  # 阻塞在取trans的地方
         node, msg = M_mailbox.get()
         if msg.type == "PUT":
             if msg.command == "TRANS":
                 trans = Transaction.load(msg.data)
                 if trans != self.trans_later and self.add_trans(trans):
                     self.trans_later = trans
                     NetworkRouting.get_instance().broad_a_msg(
                         msg)  # 广播交易
             elif msg.command == "BLOCK":  # 其它进程先挖到,暂停挖矿
                 block = Block.load(msg.data)
                 if self.block_later != block and Verify.verify_new_block(
                         block) and FullBlockChain.get_instance(
                         ).get_top_hash() == block.get_hash():
                     self.accept_block(block)
Пример #27
0
    def test_getdata_message_cblock_not_available(self):
        cblock = CBlock()
        hash_ = cblock.GetHash()
        block = Block(cblock, BlockOrigin.private)
        message = messages.msg_getdata()
        cInv = CInv()
        cInv.type = networking.inv_typemap['Block']
        cInv.hash = hash_
        message.inv = [cInv]

        self.chain.blocks = {hash_: block}
        self.networking.deferred_block_requests = {}
        self.networking.getdata_message(self.public_connection1, message)

        self.assertFalse(self.public_connection1.called)
        self.assertIn(hash_, self.networking.deferred_block_requests)
        self.assertIn(self.public_connection1.host[0],
                      self.networking.deferred_block_requests[hash_])
Пример #28
0
def main():
    blockchain = Blockchain()
    database = ["hello", "goodbye", "test", "DATA here", "test2"]

    num = 0

    for data in database:
        num += 1
        blockchain.mine(Block(num, data=data))

    for block in blockchain.chain:
        print(block)

    print(blockchain.isValid())
    # i try to change data in blck number 2 without valid nonce
    blockchain.chain[2].data = "NEW DATA"
    blockchain.mine(blockchain.chain[2])
    print(blockchain.isValid())
Пример #29
0
    def test_send_inv_public_blocks(self):
        block1 = Block(CBlock(), BlockOrigin.public)
        block1.cached_hash = 'hash1'
        block2 = Block(CBlock(), BlockOrigin.public)
        block2.cached_hash = 'hash2'
        self.networking.send_inv([block1, block2])

        self.assertFalse(self.public_connection1.send.called)
        self.assertFalse(self.public_connection2.send.called)

        self.assertTrue(self.private_connection.send.called)
        inv = self.private_connection.send.call_args[0][1].inv
        self.assertEqual(len(inv), 2)
Пример #30
0
    def test_insert_block(self):
        prevBlock = Block(CBlock(), BlockOrigin.private)
        prevBlock.cached_hash = 'hash2'
        prevBlock.height = 45
        block = Block(CBlock(), BlockOrigin.private)
        block.cached_hash = 'hash1'
        self.chain.tips = [prevBlock]

        self.chain.insert_block(prevBlock, block)

        self.assertFalse(prevBlock in self.chain.tips)
        self.assertEqual(len(self.chain.tips), 1)

        retrieved_block = self.chain.tips[0]
        self.assertEqual(retrieved_block, block)
        self.assertEqual(retrieved_block.prevBlock, prevBlock)
        self.assertEqual(retrieved_block.height, 46)