Beispiel #1
0
class BlockMessageSerializer(Serializer):
    block_serializer = BlockSerializer()
    
    def __init__(self):    
        pass     
                                                      
    def serialize(self, block_msg):
        return (self.block_serializer.serialize(block_msg.block))
        
    def deserialize(self, data, cursor=0):
        block, cursor = self.block_serializer.deserialize(data, cursor)
        return (BlockMessage(block), cursor)
Beispiel #2
0
 def __init__(self, runmode):
     self.runmode = runmode
     self.block_serializer = BlockSerializer()
     self.tx_verifier = TxVerifier(self.runmode)
Beispiel #3
0
class BlockVerifier():
    def __init__(self, runmode):
        self.runmode = runmode
        self.block_serializer = BlockSerializer()
        self.tx_verifier = TxVerifier(self.runmode)
        
    """
        basic_check: run tests that don't require context or the block parent.
    """
    def basic_checks(self, hash, block):
        self.check_size_limit(hash, block)
        self.check_proof_of_work(hash, block)
        self.check_coinbase(hash, block)
        self.check_transactions(hash, block)
        self.check_merkle_root(hash, block)
                                    

    def check_size_limit(self, hash, block):
        #FIXME: don't serialize the block here (add get_serialize_size() in serialize objects
        #or cache previoulsy serialized block)
        if (not block.rawdata):
            block.rawdata = self.block_serializer.serialize(block)
        if len(block.rawdata) > MAX_BLOCK_SIZE:
            raise Exception("block size limit exceeded")
    
    def check_proof_of_work(self, hash, block):
        target = block.blockheader.target()
        if (target <= Uint256.zero() or target > PROOF_OF_WORK_LIMIT[self.runmode]):
            raise Exception("proof of work: value out of range : %x" % (block.blockheader.bits))
        if (hash > target):
            raise Exception("proof of work: hash doesn't match target hash:%s, target:%s" % (hash, target))
    
    # not out of context: (check elsewhere) 
    # def check_timestamp(self, hash, block):
    #     block.blockheader.time > time.time
    


    def check_coinbase(self, hash, block):
        if not len(block.transactions):
            raise Exception("Block has no transactions" )
        if not block.transactions[0].iscoinbase():
            raise Exception("block's first transactions is not coinbase" )
        for tx in block.transactions[1:]:
            if tx.iscoinbase():
                raise Exception("more than one coinbase" )
    
    def check_transactions(self, hash, block):
        for tx in block.transactions:
            err = self.tx_verifier.basic_checks(tx)
            if err:
                return err

    def check_merkle_root(self, hash, block):
        merkle = compute_merkle_root(block.transactions)
        if merkle != block.blockheader.hash_merkle:
            raise Exception("merkel root incorrect for block %s: %s != %s" % (str(hash), str(merkle), str(block.blockheader.hash_merkle)) )
            
    """
        accept_block: check block after finding the parent block.
    """
    #AcceptBlock: main.cpp:1445
    def accept_block(self, hash, block, blockchain):
        prevblockhandle = blockchain.get_block_handle(block.blockheader.hash_prev)
        
        self.check_target(blockchain, prevblockhandle, hash, block)
        self.check_timestamp(blockchain, prevblockhandle, hash, block)
        self.check_tx_finalized(prevblockhandle, hash, block)
        self.check_checkpoints(prevblockhandle, hash, block)
      
        
    def check_target(self, blockchain, prevblockhandle, hash, block):
        #Check proof of work target
        if (blockchain.get_next_work_required(prevblockhandle.hash, block) != block.blockheader.bits):
            raise Exception("Incorrect difficulty target, found:%08x != required:%08x in block %s" % (block.blockheader.bits, blockchain.get_next_work_required(prevblockhandle.hash, block), hash) )

        
    def check_timestamp(self, blockchain, prevblockhandle, hash, block):
        if (block.blockheader.time <= blockchain.get_median_time_past(prevblockhandle.hash)):
            raise Exception("block's timestamp is smaller than the median of past %d block: %d <= %d" % (MEDIAN_TIME_SPAN, prevblockhandle.get_blockheader().time , prevblockhandle.get_median_time_past()))

    def check_tx_finalized(self, prevblockhandle, hash, block):
        height = prevblockhandle.get_height()+1
        #Check that all transactions are finalized (can this be done somewhere else?)
        for tx in block.transactions:
            if not tx.isfinal(height, block.blockheader.time):
                raise Exception("transaction is not final: %s" % str(hash_tx(tx)))
    
    def check_checkpoints(self, prevblockhandle, hash, block):
        height = prevblockhandle.get_height()+1
        if not verify_checkpoints(self.runmode, height, hash):
            raise Exception("blockchain checkpoint error: height:%d value:%s != %s" % (height, hash, str(get_checkpoint(self.runmode, height))))
Beispiel #4
0
 def test_block_serialize(self):
     blockheader = BlockHeader(
         version=1,
         hash_prev=Uint256.from_hexstr(
             "000000000fec081581146e8b16b275bfa52150ac4174a246cdf62694671ea7a3"
         ),
         hash_merkle=Uint256.from_hexstr(
             "0d9da162550fc45b1aaa00e933b23b3cbc7f37a9b2d2070d61235eaec11a926a"
         ),
         time=1301129903,
         bits=470809215,
         nonce=1280448751)
     tx1 = Tx(
         version=1,
         in_list=[
             TxIn(previous_output=Outpoint.null(),
                  script=Script([
                      Instruction(4, decodehexstr("7ffa0f1c")),
                      Instruction(1, decodehexstr("4e"))
                  ]),
                  sequence=TxIn.NSEQUENCE_FINAL)
         ],
         out_list=[
             TxOut(
                 value=5002000000,
                 script=Script([
                     Instruction(
                         65,
                         decodehexstr(
                             "049cc3cae30927c40598032044b9e9e25f4739b0d7ade62803f5e9cf075debc817e6d29f42c70d0a1beb1c904eaaa50ef885b011f9fbaa16ef288a7ad193e11567"
                         )),
                     Instruction(OP_CHECKSIG)
                 ]))
         ],
         locktime=0)
     tx2 = Tx(
         version=1,
         in_list=[
             TxIn(previous_output=Outpoint(hash=Uint256.from_hexstr(
                 "17c5cb687ba453ab65e12cdc0d8721c70ab4678665eb200c50cb9f1e3207090e"
             ),
                                           index=0),
                  script=Script([
                      Instruction(
                          72,
                          decodehexstr(
                              "3045022100ab2dc8932ca1d26f4cdac1feae09020a60ccc4d17b14e5fc5b21f3ab8c3a9cee022040a7208c172d19a19902280d66201c7fe2c3d8b2df7e23cc4e5b70fd52ecba2c01"
                          )),
                      Instruction(
                          65,
                          decodehexstr(
                              "04b77dd1f3a21cb3d067a7e76982a609d7310f8692f5d61346f3225323c425604a0c12862755335c49e392673106adfc5dfdee1e4d367f10353e8911fac687db3e"
                          ))
                  ]),
                  sequence=TxIn.NSEQUENCE_FINAL)
         ],
         out_list=[
             TxOut(value=24990000000,
                   script=Script([
                       Instruction(OP_DUP),
                       Instruction(OP_HASH160),
                       Instruction(
                           20,
                           decodehexstr(
                               "4d8b17fbce571614be89df4bd872de892a479844")),
                       Instruction(OP_EQUALVERIFY),
                       Instruction(OP_CHECKSIG)
                   ])),
             TxOut(value=5000000000,
                   script=Script([
                       Instruction(OP_DUP),
                       Instruction(OP_HASH160),
                       Instruction(
                           20,
                           decodehexstr(
                               "fadad27c40adbe230f5e3c04d44a292975084831")),
                       Instruction(OP_EQUALVERIFY),
                       Instruction(OP_CHECKSIG)
                   ]))
         ],
         locktime=0)
     blk = Block(blockheader, [tx1, tx2])
     data = BlockSerializer().serialize(blk)
     self.assertEquals(
         data,
         decodehexstr(
             "01000000a3a71e679426f6cd46a27441ac5021a5bf75b2168b6e14811508ec0f000000006a921ac1ae5e23610d07d2b2a9377fbc3c3bb233e900aa1a5bc40f5562a19d0dafaa8d4d7ffa0f1cef18524c0201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff07047ffa0f1c014effffffff018076242a010000004341049cc3cae30927c40598032044b9e9e25f4739b0d7ade62803f5e9cf075debc817e6d29f42c70d0a1beb1c904eaaa50ef885b011f9fbaa16ef288a7ad193e11567ac0000000001000000010e0907321e9fcb500c20eb658667b40ac721870ddc2ce165ab53a47b68cbc517000000008b483045022100ab2dc8932ca1d26f4cdac1feae09020a60ccc4d17b14e5fc5b21f3ab8c3a9cee022040a7208c172d19a19902280d66201c7fe2c3d8b2df7e23cc4e5b70fd52ecba2c014104b77dd1f3a21cb3d067a7e76982a609d7310f8692f5d61346f3225323c425604a0c12862755335c49e392673106adfc5dfdee1e4d367f10353e8911fac687db3effffffff02802385d1050000001976a9144d8b17fbce571614be89df4bd872de892a47984488ac00f2052a010000001976a914fadad27c40adbe230f5e3c04d44a29297508483188ac00000000"
         ))
Beispiel #5
0
 def __init__(self, runmode):
     self.runmode = runmode
     self.block_serializer = BlockSerializer()
     self.tx_verifier = TxVerifier(self.runmode)
Beispiel #6
0
class BlockVerifier():
    def __init__(self, runmode):
        self.runmode = runmode
        self.block_serializer = BlockSerializer()
        self.tx_verifier = TxVerifier(self.runmode)

    """
        basic_check: run tests that don't require context or the block parent.
    """

    def basic_checks(self, hash, block):
        self.check_size_limit(hash, block)
        self.check_proof_of_work(hash, block)
        self.check_coinbase(hash, block)
        self.check_transactions(hash, block)
        self.check_merkle_root(hash, block)

    def check_size_limit(self, hash, block):
        #FIXME: don't serialize the block here (add get_serialize_size() in serialize objects
        #or cache previoulsy serialized block)
        if (not block.rawdata):
            block.rawdata = self.block_serializer.serialize(block)
        if len(block.rawdata) > MAX_BLOCK_SIZE:
            raise Exception("block size limit exceeded")

    def check_proof_of_work(self, hash, block):
        target = block.blockheader.target()
        if (target <= Uint256.zero()
                or target > PROOF_OF_WORK_LIMIT[self.runmode]):
            raise Exception("proof of work: value out of range : %x" %
                            (block.blockheader.bits))
        if (hash > target):
            raise Exception(
                "proof of work: hash doesn't match target hash:%s, target:%s" %
                (hash, target))

    # not out of context: (check elsewhere)
    # def check_timestamp(self, hash, block):
    #     block.blockheader.time > time.time

    def check_coinbase(self, hash, block):
        if not len(block.transactions):
            raise Exception("Block has no transactions")
        if not block.transactions[0].iscoinbase():
            raise Exception("block's first transactions is not coinbase")
        for tx in block.transactions[1:]:
            if tx.iscoinbase():
                raise Exception("more than one coinbase")

    def check_transactions(self, hash, block):
        for tx in block.transactions:
            err = self.tx_verifier.basic_checks(tx)
            if err:
                return err

    def check_merkle_root(self, hash, block):
        merkle = compute_merkle_root(block.transactions)
        if merkle != block.blockheader.hash_merkle:
            raise Exception(
                "merkel root incorrect for block %s: %s != %s" %
                (str(hash), str(merkle), str(block.blockheader.hash_merkle)))

    """
        accept_block: check block after finding the parent block.
    """

    #AcceptBlock: main.cpp:1445
    def accept_block(self, hash, block, blockchain):
        prevblockhandle = blockchain.get_block_handle(
            block.blockheader.hash_prev)

        self.check_target(blockchain, prevblockhandle, hash, block)
        self.check_timestamp(blockchain, prevblockhandle, hash, block)
        self.check_tx_finalized(prevblockhandle, hash, block)
        self.check_checkpoints(prevblockhandle, hash, block)

    def check_target(self, blockchain, prevblockhandle, hash, block):
        #Check proof of work target
        if (blockchain.get_next_work_required(prevblockhandle.hash, block) !=
                block.blockheader.bits):
            raise Exception(
                "Incorrect difficulty target, found:%08x != required:%08x in block %s"
                % (block.blockheader.bits,
                   blockchain.get_next_work_required(prevblockhandle.hash,
                                                     block), hash))

    def check_timestamp(self, blockchain, prevblockhandle, hash, block):
        if (block.blockheader.time <= blockchain.get_median_time_past(
                prevblockhandle.hash)):
            raise Exception(
                "block's timestamp is smaller than the median of past %d block: %d <= %d"
                % (MEDIAN_TIME_SPAN, prevblockhandle.get_blockheader().time,
                   prevblockhandle.get_median_time_past()))

    def check_tx_finalized(self, prevblockhandle, hash, block):
        height = prevblockhandle.get_height() + 1
        #Check that all transactions are finalized (can this be done somewhere else?)
        for tx in block.transactions:
            if not tx.isfinal(height, block.blockheader.time):
                raise Exception("transaction is not final: %s" %
                                str(hash_tx(tx)))

    def check_checkpoints(self, prevblockhandle, hash, block):
        height = prevblockhandle.get_height() + 1
        if not verify_checkpoints(self.runmode, height, hash):
            raise Exception(
                "blockchain checkpoint error: height:%d value:%s != %s" %
                (height, hash, str(get_checkpoint(self.runmode, height))))