《区块链编程》第九章

《区块链编程》第九章

区块

练习1

p154

代码实现

# -*- coding: utf-8 -*-
# @Author: 从化北(喵星人)
# @Date:   2022-01-14 11:22:46
# @Last Modified by:   从化北
# @Last Modified time: 2022-01-14 11:26:57

class Tx:
...
    def is_coinbase(self):
        '''Returns whether this transaction is a coinbase transaction or not'''
        # check that there is exactly 1 input
        if len(self.tx_ins) != 1:
            return False
        # grab the first input
        first_input = self.tx_ins[0]
        # check that first input prev_tx is b'\x00' * 32 bytes
        if first_input.prev_tx != b'\x00' * 32:
            return False
        # check that first input prev_index is 0xffffffff
        if first_input.prev_index != 0xffffffff:
            return False
        return True

测试

练习2

p156

代码实现

# -*- coding: utf-8 -*-
# @Author: 从化北(喵星人)
# @Date:   2022-01-14 11:27:51
# @Last Modified by:   从化北
# @Last Modified time: 2022-01-14 11:27:51

class Tx:
...
    def coinbase_height(self):
        '''Returns the height of the block this coinbase transaction is in
        Returns None if this transaction is not a coinbase transaction
        '''
        # if this is NOT a coinbase transaction, return None
        if not self.is_coinbase() :
            return None
        # grab the first cmd
        element = self.tx_ins[0].script_sig.cmds[0]
        # convert the cmd from  little endian to int
        return little_endian_to_int(element)
        

测试

练习3

p157

代码实现

# -*- coding: utf-8 -*-
# @Author: 从化北(喵星人)
# @Date:   2022-01-14 11:33:46
# @Last Modified by:   从化北
# @Last Modified time: 2022-01-14 11:33:46
class Block:
...
    @classmethod
    def parse(cls, s):
        '''Takes a byte stream and parses a block. Returns a Block object'''
        # s.read(n) will read n bytes from the stream
        # version - 4 bytes, little endian, interpret as int
        version = little_endian_to_int(s.read(4))
        # prev_block - 32 bytes, little endian (use [::-1] to reverse)
        prev_block = s.read(32)[::-1]
        # merkle_root - 32 bytes, little endian (use [::-1] to reverse)
        merkle_root = s.read(32)[::-1]
        # timestamp - 4 bytes, little endian, interpret as int
        timestamp = little_endian_to_int(s.read(4))
        # bits - 4 bytes
        bits = s.read(4)
        # nonce - 4 bytes
        nonce = s.read(4)
        # initialize class
        return cls(version, prev_block, merkle_root, timestamp, bits, nonce)

测试

练习4

p157

代码实现

# -*- coding: utf-8 -*-
# @Author: 从化北(喵星人)
# @Date:   2022-01-14 11:40:27
# @Last Modified by:   从化北
# @Last Modified time: 2022-01-14 11:40:27
class Block:
...
    def serialize(self):
        '''Returns the 80 byte block header'''
        # version - 4 bytes, little endian
        result = int_to_little_endian(self.version, 4)
        # prev_block - 32 bytes, little endian
        result += self.prev_block[::-1]
        # merkle_root - 32 bytes, little endian
        result += self.merkle_root[::-1]
        # timestamp - 4 bytes, little endian
        result += int_to_little_endian(self.timestamp, 4)
        # bits - 4 bytes
        result += self.bits
        # nonce - 4 bytes
        result += self.nonce
        return result

运行结果

练习5

p157

代码实现

# -*- coding: utf-8 -*-
# @Author: 从化北(喵星人)
# @Date:   2022-01-14 11:44:10
# @Last Modified by:   从化北
# @Last Modified time: 2022-01-14 11:44:10

class Block:
...
    def hash(self):
        '''Returns the hash256 interpreted little endian of the block'''
        # serialize
        s = self.serialize()
        # hash256
        sha = hash256(s)
        # reverse
        return sha[::-1]

运行结果

练习6

p158

代码实现

# -*- coding: utf-8 -*-
# @Author: 从化北(喵星人)
# @Date:   2022-01-14 11:45:44
# @Last Modified by:   从化北
# @Last Modified time: 2022-01-14 11:45:44
class Block:
...
    def bip9(self):
        '''Returns whether this block is signaling readiness for BIP9'''
        # BIP9 is signalled if the top 3 bits are 001
        # remember version is 32 bytes so right shift 29 (>> 29) and see if
        # that is 001
        return self.version >> 29 == 0b001

运行结果

练习7

p159

代码实现

# -*- coding: utf-8 -*-
# @Author: 从化北(喵星人)
# @Date:   2022-01-14 11:47:52
# @Last Modified by:   从化北
# @Last Modified time: 2022-01-14 11:47:52
class Block:
...
    def bip91(self):
        '''Returns whether this block is signaling readiness for BIP91'''
        # BIP91 is signalled if the 5th bit from the right is 1
        # shift 4 bits to the right and see if the last bit is 1
        return self.version >> 4 & 1 == 1

运行结果

练习8

p159

代码实现

# -*- coding: utf-8 -*-
# @Author: 从化北(喵星人)
# @Date:   2022-01-14 11:49:22
# @Last Modified by:   从化北
# @Last Modified time: 2022-01-14 11:49:22
class Block:
...
    def bip141(self):
        '''Returns whether this block is signaling readiness for BIP141'''
        # BIP91 is signalled if the 2nd bit from the right is 1
        # shift 1 bit to the right and see if the last bit is 1
        return self.version >> 1 & 1 == 1

运行结果

练习9

p162

代码实现

# -*- coding: utf-8 -*-
# @Author: 从化北(喵星人)
# @Date:   2022-01-14 11:50:48
# @Last Modified by:   从化北
# @Last Modified time: 2022-01-14 11:50:48
def bits_to_target(bits):
    '''Turns bits into a target (large 256-bit integer)'''
    # last byte is exponent
    exponent = bits[-1]
    # the first three bytes are the coefficient in little endian
    coefficient = little_endian_to_int(bits[:-1])
    # the formula is:
    # coefficient * 256**(exponent-3)
    return coefficient * 256 ** (exponent - 3)

运行结果

练习10

p163

代码实现

# -*- coding: utf-8 -*-
# @Author: 从化北(喵星人)
# @Date:   2022-01-14 14:12:28
# @Last Modified by:   从化北
# @Last Modified time: 2022-01-14 14:12:28
class Block:
...
    def difficulty(self):
        '''Returns the block difficulty based on the bits'''
        # note difficulty is (target of lowest difficulty) / (self's target)
        # lowest difficulty has bits that equal 0xffff001d
        lowest = 0xffff * 256 ** (0x1d - 3)
        return lowest / self.target()

运行结果

练习11

p163

代码实现

# -*- coding: utf-8 -*-
# @Author: 从化北(喵星人)
# @Date:   2022-01-14 14:16:14
# @Last Modified by:   从化北
# @Last Modified time: 2022-01-14 14:16:14

class Block:
...
    def check_pow(self):
        '''Returns whether this block satisfies proof of work'''
        # get the hash256 of the serialization of this block
        sha = hash256(self.serialize())
        # interpret this hash as a little-endian number
        proof = little_endian_to_int(sha)
        # return whether this integer is less than the target
        return proof < self.target()

运行结果

练习12

p165

代码实现

# -*- coding: utf-8 -*-
# @Author: 从化北(喵星人)
# @Date:   2022-01-14 14:19:07
# @Last Modified by:   从化北
# @Last Modified time: 2022-01-14 14:26:27
from io import BytesIO
from block import Block
from helper import TWO_WEEKS
from helper import target_to_bits
block1_hex = '000000203471101bbda3fe307664b3283a9ef0e97d9a38a7eacd88000000\
00000000000010c8aba8479bbaa5e0848152fd3c2289ca50e1c3e58c9a4faaafbdf5803c5448dd\
b845597e8b0118e43a81d3'
block2_hex = '02000020f1472d9db4b563c35f97c428ac903f23b7fc055d1cfc26000000\
000000000000b3f449fcbe1bc4cfbcb8283a0d2c037f961a3fdf2b8bedc144973735eea707e126\
4258597e8b0118e5f00474'
last_block = Block.parse(BytesIO(bytes.fromhex(block1_hex)))
first_block = Block.parse(BytesIO(bytes.fromhex(block2_hex)))
time_differential = last_block.timestamp - first_block.timestamp
if time_differential > TWO_WEEKS * 4:
    time_differential = TWO_WEEKS * 4
if time_differential < TWO_WEEKS // 4:
    time_differential = TWO_WEEKS // 4
new_target = last_block.target() * time_differential // TWO_WEEKS
new_bits = target_to_bits(new_target)
print(new_bits.hex())


运行结果

80df6217
[Finished in 342ms]

练习13

p165

代码实现

# -*- coding: utf-8 -*-
# @Author: 从化北(喵星人)
# @Date:   2022-01-14 14:31:48
# @Last Modified by:   从化北
# @Last Modified time: 2022-01-14 14:49:10
MAX_TARGET = 0xffff * 256**(0x1d - 3)


def calculate_new_bits(previous_bits, time_differential):
    '''Calculates the new bits given
    a 2016-block time differential and the previous bits'''
    # if the time differential is greater than 8 weeks, set to 8 weeks
    if time_differential > TWO_WEEKS * 4:
        time_differential = TWO_WEEKS * 4
    # if the time differential is less than half a week, set to half a week
    if time_differential < TWO_WEEKS // 4:
        time_differential = TWO_WEEKS // 4
    # the new target is the previous target * time differential / two weeks
    new_target = bits_to_target(previous_bits) * time_differential // TWO_WEEKS
    # if the new target is bigger than MAX_TARGET, set to MAX_TARGET
    if new_target > MAX_TARGET:
        new_target = MAX_TARGET
    # convert the new target to bits
    return target_to_bits(new_target)

运行结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值