def calc_difficulty(parent, timestamp):
config = parent.config
offset = parent.difficulty // config['BLOCK_DIFF_FACTOR']
if parent.number >= (config['METROPOLIS_FORK_BLKNUM'] - 1):
sign = max(len(parent.uncles) - ((timestamp - parent.timestamp) // config['METROPOLIS_DIFF_ADJUSTMENT_CUTOFF']), -99)
elif parent.number >= (config['HOMESTEAD_FORK_BLKNUM'] - 1):
sign = max(1 - ((timestamp - parent.timestamp) // config['HOMESTEAD_DIFF_ADJUSTMENT_CUTOFF']), -99)
else:
sign = 1 if timestamp - parent.timestamp < config['DIFF_ADJUSTMENT_CUTOFF'] else -1
# If we enter a special mode where the genesis difficulty starts off below
# the minimal difficulty, we allow low-difficulty blocks (this will never
# happen in the official protocol)
o = int(max(parent.difficulty + offset * sign, min(parent.difficulty, config['MIN_DIFF'])))
period_count = (parent.number + 1) // config['EXPDIFF_PERIOD']
if period_count >= config['EXPDIFF_FREE_PERIODS']:
o = max(o + 2 ** (period_count - config['EXPDIFF_FREE_PERIODS']), config['MIN_DIFF'])
# print('Calculating difficulty of block %d, timestamp difference %d, parent diff %d, child diff %d' % (parent.number + 1, timestamp - parent.timestamp, parent.difficulty, o))
return o
以上方法计算困难度
一个以太坊账号的类(Account):
内部的属性:
"""
在这个类Account的参数列表中有一个参数rlp.Serializeable,应该表示一个经过序列化后的rlp编码格式的对象字符
:ivar nonce:一个账户的nonce(表示这个账户的交易数目)
:ivar balance:这个账户的余额
:ivar storage: 表示这个账户的tire的根
:ivar code_hash: 表示和账户关联的经过SHA3的哈希串
""" fields = [
('nonce', big_endian_int),
('balance', big_endian_int),
('storage', trie_root),
('code_hash', hash32)
]
该类的_init_方法参数列表(self, nonce, balance, storage, code_hash, db),初始化方法如下,使用
def __init__(self, nonce, balance, storage, code_hash, db):
assert isinstance(db, BaseDB)
self.db = db
super(Account, self).__init__(nonce, balance, storage, code_hash)
以下获得code值,方法如下:(code指什么?codehash?)
@property
def code(self):
"""The EVM code of the account. This property will be read from or written to the db at each access,
with :ivar:`code_hash` used as key.
"""
return self.db.get(self.code_hash)
以下设置code的值
@code.setter
def code(self, value):
self.code_hash = utils.sha3(value)
# Technically a db storage leak, but doesn't really matter; the only
# thing that fails to get garbage collected is when code disappears due
# to a suicide
self.db.inc_refcount(self.code_hash, value)
下面方法设置一个空白账户:
@classmethod
def blank_account(cls, db, initial_nonce=0):
"""Create a blank account The returned account will have zero nonce and balance, a blank storage
trie and empty code. :param db: the db in which the account will store its code.
"""
code_hash = utils.sha3(b'')
db.put(code_hash, b'')
return cls(initial_nonce, 0, trie.BLANK_ROOT, code_hash, db)
类Receipt
#state_root用于对数据库进行校验,当和其他数据库不一致的时候,表明有非法交易或者需要同步,用于校验
fields = [
('state_root', trie_root),
('gas_used', big_endian_int),
('bloom', int256),
('logs', CountableList(processblock.Log))
]
类blockhead
他的类内的属性为:
fields = [
('prevhash', hash32), //前一个block的32字节hash值
('uncles_hash', hash32), // 32字节的 经过RLP编码的uncle headers的列表
('coinbase', address), //20字节的coinbase字节的地址
('state_root', trie_root), // state trie的根
('tx_list_root', trie_root), //
('receipts_root', trie_root),
('bloom', int256),
('difficulty', big_endian_int), //区块的难度
('number', big_endian_int), //区块祖先的个数
('gas_limit', big_endian_int),
('gas_used', big_endian_int), //这个区块上所有的交易消耗的gas
('timestamp', big_endian_int),
('extra_data', binary), ///最多1024字节
('mixhash', binary),
('nonce', Binary(8, allow_empty=True)) //32字节 作为占位符或者去构成工作量证明
]
这些属性的初始化如下:
def __init__(self,
prevhash=default_config['GENESIS_PREVHASH'], //default 在etherum下的config包中 GENESIS_PREVHASH=b'\x00' * 32,
uncles_hash=utils.sha3rlp([]),
coinbase=default_config['GENESIS_COINBASE'],//GENESIS_COINBASE=b'\x00' * 20,
state_root=trie.BLANK_ROOT,
tx_list_root=trie.BLANK_ROOT,
receipts_root=trie.BLANK_ROOT,
bloom=0,
difficulty=default_config['GENESIS_DIFFICULTY'],
number=0,
gas_limit=default_config['GENESIS_GAS_LIMIT'], //GENESIS_GAS_LIMIT=3141592
gas_used=0,
timestamp=0,
extra_data='',
mixhash=default_config['GENESIS_MIXHASH'],
nonce=''):
# at the beginning of a method, locals() is a dict of all arguments
fields = {k: v for k, v in locals().items() if k != 'self'}
if len(fields['coinbase']) == 40:
fields['coinbase'] = decode_hex(fields['coinbase'])
assert len(fields['coinbase']) == 20
self.block = None
super(BlockHeader, self).__init__(**fields)