messageRound {// The round number.int64round_number=1;// Current miner information, miner public key -> miner information.map<string, MinerInRound>real_time_miners_information=2;// The round number on the main chainint64main_chain_miners_round_number=3;// The time from chain start to current round (seconds).int64blockchain_age=4;// The miner public key that produced the extra block in the previous round.stringextra_block_producer_of_previous_round=5;// The current term number.int64term_number=6;// The height of the confirmed irreversible block.int64confirmed_irreversible_block_height=7;// The round number of the confirmed irreversible block.int64confirmed_irreversible_block_round_number=8;// Is miner list different from the the miner list in the previous round.boolis_miner_list_just_changed=9;// The round id, calculated by summing block producers’ expecting time (second).int64round_id_for_validation=10;}messageMinerInRound {// The order of the miner producing block.int32order=1;// Is extra block producer in the current round.boolis_extra_block_producer=2;// Generated by secret sharing and used for validation between miner.aelf.Hashin_value=3;// Calculated from current in value.aelf.Hashout_value=4;// Calculated from current in value and signatures of previous round.aelf.Hashsignature=5;// The expected mining time.google.protobuf.Timestampexpected_mining_time=6;// The amount of produced blocks.int64produced_blocks=7;// The amount of missed time slots.int64missed_time_slots=8;// The public key of this miner.stringpubkey=9;// The InValue of the previous round.aelf.Hashprevious_in_value=10;// The supposed order of mining for the next round.int32supposed_order_of_next_round=11;// The final order of mining for the next round.int32final_order_of_next_round=12;// The actual mining time, miners must fill actual mining time when they do the mining.repeatedgoogle.protobuf.Timestampactual_mining_times=13;// The encrypted pieces of InValue.map<string, bytes>encrypted_pieces=14;// The decrypted pieces of InValue.map<string, bytes>decrypted_pieces=15;// The amount of produced tiny blocks.int64produced_tiny_blocks=16;// The irreversible block height that current miner recorded.int64implied_irreversible_block_height=17;}
Consensus Extra Data保存于Block Header中的ExtraData字段中(aelf区块数据结构和ChainId )。该字段用于保存aelf系统各个部分可用于辅助完成区块验证的信息。Consensus Extra Data就是用于辅助完成共识信息验证的数据,由于保存在区块头中,用于帮助收到区块的全节点在执行区块中的交易之前,快速验证一下共识信息:如果包含在区块头中的共识信息就是错误的,那这个区块的交易就不必执行了,可以直接丢弃。BP在生产区块的过程中,通过AEDPoS合约的GetConsensusExtraData方法获得要设置进区块头中的Consensus Extra Data。这个方法的参数是二进制数组,不同的共识机制可以定制自己的形参类型,在方法实现中进行反序列化即可。在AEDPoS实现中,认为入参是一个AElfConsensusTriggerInformation结构:
而Consensus Extra Data的获取,首先基于AElfConsensusTriggerInformation的behaviour字段,不同的共识行为会生成不同的区块头信息。比如UpdateValue中,会公开前一轮的In Value,公布这一轮的Out Value;在TinyBlock中,则只是把这一轮的Round信息中相应BP的小块数量加一;NextRound和NextTerm中,都会生成新的Round的信息,不同的地方在于后者会重新获取Miner List(TryToGetVictories方法,回去调用Election合约)。最后,为了防止返回的AElfConsensusHeaderInformation实例太大,会删除掉Secret Sharing相关的数据,这一部分数据无需包含在区块头中验证。
GenerateConsensusTransactions
关于系统交易,见[WIP]aelf System Transaction机制 。这个方法用于辅助BP生成即将包含在新生产的区块中的Consensus System Transaction。入参同GetConsensusExtraData,也是AElfConsensusTriggerInformation。返回值是TransactionList:
该方法用于验证共识系统交易(就是通过GenerateConsensusTransactions方法生成的交易)执行完毕后,执行结果是否与Consensus Extra Data一致。会顺便看一下这一轮的信息是否做过修改,如果被做过修改的话,进行的修改是否恰当。(比如这一轮发生了BP替换的话,会有修改,这时候会校验替换的结果是否正确。)
message ConsensusCommand {
// Time limit of mining next block.
int32 limit_milliseconds_of_mining_block = 1;
// Context of Hint is diverse according to the consensus protocol we choose, so we use bytes.
bytes hint = 2;
// The time of arrange mining.
google.protobuf.Timestamp arranged_mining_time = 3;
// The expiration time of mining.
google.protobuf.Timestamp mining_due_time = 4;
}
message AElfConsensusHint {
// The behaviour of consensus.
AElfConsensusBehaviour behaviour = 1;
// The round id.
int64 round_id = 2;
// The previous round id.
int64 previous_round_id = 3;
}
service CrossChainInteractionContract {
// Update the consensus information of the side chain.
rpc UpdateInformationFromCrossChain (google.protobuf.BytesValue) returns (google.protobuf.Empty) {
}
// Get the current miner list and consensus round information.
rpc GetChainInitializationInformation (google.protobuf.BytesValue) returns (google.protobuf.BytesValue) {
option (aelf.is_view) = true;
}
// Verify that the input address is the current miner.
rpc CheckCrossChainIndexingPermission (aelf.Address) returns (google.protobuf.BoolValue) {
option (aelf.is_view) = true;
}
}