交易同步过程

1 通过命令cleos调用 cleos transfer ${from_account} ${to_account} ${quantity} 发起交易
2 eos调用chain_plugin 的push_transaction,内部调用注册好的方法。

1
app().get_method<incoming::methods::transaction_async>();

代码截图如下

在producer_plugin插件的plugin_initialize函数中提前注册了incoming::methods::transaction_async。

所以实际调用了producer_plugin_impl的on_incoming_transaction_async(trx, persist_until_expired, next )函数,
传递的参数分别是pretty_input,true,和一个lambda匿名函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
app().get_method<incoming::methods::transaction_async>()(pretty_input, true, [this, next](const fc::static_variant<fc::exception_ptr, transaction_trace_ptr>& result) -> void{
if (result.contains<fc::exception_ptr>()) {
next(result.get<fc::exception_ptr>());
} else {
auto trx_trace_ptr = result.get<transaction_trace_ptr>(); try {
chain::transaction_id_type id = trx_trace_ptr->id;
fc::variant output;
try {
output = db.to_variant_with_abi( *trx_trace_ptr, abi_serializer_max_time );
} catch( chain::abi_exception& ) {
output = *trx_trace_ptr;
} next(read_write::push_transaction_results{id, output});
} CATCH_AND_CALL(next);
}
});

3 在producer_plugin_impl的on_incoming_transaction_async中调用controller的 push_transaction,并执行trx。
将交易插入_pending_incoming_transactions中

接下来调用了controller的push_transaction函数

4 controller的push_transaction函数中发送消息accepted_transaction,而目前常用的网络插件为bnet_plugin,net_plugin目前已作为备用,
由于在bnet_plugin的startup函数中绑定了消息回调函数

1
2
3
4
my->_on_appled_trx_handle = app().get_channel<channels::accepted_transaction>()
.subscribe( [this]( transaction_metadata_ptr t ){
my->on_accepted_transaction(t);
});

通过app().get_channel将channels::accepted_transaction信号和lambda表达式绑定起来,所以当controller发送信号accepted_transaction就会调用这个lambda表达式传递参数,从而调用bnet_plugin_impl中on_accepted_transaction函数。
5 bnet_plugin_impl通过on_accepted_transaction将消息广播到其他节点

1
2
3
4
void on_accepted_transaction( transaction_metadata_ptr trx ) {
if( trx->implicit || trx->scheduled ) return;
for_each_session( [trx]( auto ses ){ ses->on_accepted_transaction( trx ); } );
}

6 其他节点收到消息后,进入on处理流程,发送transction消息
bnet_plugin处理消息函数

transaction消息处理

通过

1
app().get_channel<incoming::channels::transaction>().publish(p);

发送transaction消息。
7 producer_plugin绑定了消息处理的回调函数

收到消息后,调用on_incoming_transaction_async,调用controller的 push_transaction,并执行trx。
以上就是eos交易同步过程。

区块生产过程

整体的区块生产流程

1 检查自己是否是生产者,一个生产者500ms出一次块,共出12次之后切换生产者。
2 对上次确认的区块到本次的区块做BFT签名,涉及函数set_confirmed和maybe_promote_pending,具体可以参看controller中start_block函数
3 等待一个出块周期500ms
4 计算action的merkle root
5 计算transaction的merkle root
6 对区块签名
7 提交区块到DB
8 递归调用schedule_production_loop

区块同步过程

1 参考区块生产过程,producer_plugin循环生产区块,先start_block处理BFT签名并确定不可逆的区块数,之后produce_block调用controller
2 controller使用finalize_block计算merkle root,使用commit_block提交到fork database中,fork db会依据1中计算的不可逆区块数,将不可逆的区块删除,并发送irreversible消息,controller绑定了该消息处理的回调函数

1
2
3
fork_db.irreversible.connect( [&]( auto b ) {
on_irreversible(b);
});

3 controller收到消息后,调用on_irreversible处理发送irreversible_block消息。bnet注册了该消息处理的回调函数

1
2
3
4
my->_on_irb_handle = app().get_channel<channels::irreversible_block>()
.subscribe( [this]( block_state_ptr s ){
my->on_irreversible_block(s);
});

4 bnet_plugin 收到消息后,调用on_irreversible_block处理。并广播给其他节点。
5 controller发送accepted_block_header和accepted_block消息。
6 producer_plugin收到消息后, 调用on_block,calc_dpos_last_irreversible计算不可逆块。
7 bnet_plugin/net_plugin 收到之后广播到其他节点。
8 其他节点的bnet_plugin/net_plugin收到P2P消息后,发送block消息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void on( const signed_block_ptr& b ) {
peer_ilog(this, "received signed_block_ptr");
if (!b) {
peer_elog(this, "bad signed_block_ptr : null pointer");
EOS_THROW(block_validate_exception, "bad block" );
}
status( "received block " + std::to_string(b->block_num()) );
//ilog( "recv block ${n}", ("n", b->block_num()) );
auto id = b->id();
mark_block_status( id, true, true ); app().get_channel<incoming::channels::block>().publish(b); mark_block_transactions_known_by_peer( b );
}

9 Producer_plugin收到block消息后调用controller的push_block函数
10 Controller调用apply_block判断如果新收到的block比原有的链长,则切换到新链上
11 Controller调用finalize_block计算merkle root,使用commit_block提交到DB
以上就是区块同步过程。
感谢关注我的公众号

eos交易同步过程和区块生产过程源码分析的更多相关文章

  1. 【精】EOS智能合约:system系统合约源码分析

    系统合约在链启动阶段就会被部署,是因为系统合约赋予了EOS链资源.命名拍卖.基础数据准备.生产者信息.投票等能力.本篇文章将会从源码角度详细研究system合约. 关键字:EOS,eosio.syst ...

  2. Spring源码分析之Bean的创建过程详解

    前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 Spring源码分析之BeanFactoryPostProcessor调用过程详解 本文内容: 在 ...

  3. 【Netty源码分析】发送数据过程

    前面两篇博客[Netty源码分析]Netty服务端bind端口过程和[Netty源码分析]客户端connect服务端过程中我们分别介绍了服务端绑定端口和客户端连接到服务端的过程,接下来我们分析一下数据 ...

  4. Spring源码分析之`BeanFactoryPostProcessor`调用过程

    前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 本文内容: AbstractApplicationContext#refresh前部分的一点小内容 ...

  5. React Fiber源码分析 (介绍)

    写了分析源码的文章后, 总觉得缺少了什么, 在这里补一个整体的总结,输出个人的理解~ 文章的系列标题为Fiber源码分析, 那么什么是Fiber,官方给出的解释是: React Fiber是对核心算法 ...

  6. Spring源码分析之循环依赖及解决方案

    Spring源码分析之循环依赖及解决方案 往期文章: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 Spring源码分析之BeanFactoryPostPro ...

  7. v76.01 鸿蒙内核源码分析(共享内存) | 进程间最快通讯方式 | 百篇博客分析OpenHarmony源码

    百篇博客分析|本篇为:(共享内存篇) | 进程间最快通讯方式 进程通讯相关篇为: v26.08 鸿蒙内核源码分析(自旋锁) | 当立贞节牌坊的好同志 v27.05 鸿蒙内核源码分析(互斥锁) | 同样 ...

  8. v79.01 鸿蒙内核源码分析(用户态锁篇) | 如何使用快锁Futex(上) | 百篇博客分析OpenHarmony源码

    百篇博客分析|本篇为:(用户态锁篇) | 如何使用快锁Futex(上) 进程通讯相关篇为: v26.08 鸿蒙内核源码分析(自旋锁) | 当立贞节牌坊的好同志 v27.05 鸿蒙内核源码分析(互斥锁) ...

  9. v77.01 鸿蒙内核源码分析(消息封装篇) | 剖析LiteIpc(上)进程通讯内容 | 新的一年祝大家生龙活虎 虎虎生威

    百篇博客分析|本篇为:(消息封装篇) | 剖析LiteIpc进程通讯内容 进程通讯相关篇为: v26.08 鸿蒙内核源码分析(自旋锁) | 当立贞节牌坊的好同志 v27.05 鸿蒙内核源码分析(互斥锁 ...

随机推荐

  1. C语言和python的区别

    Python可以说是目前最火的语言之一了,人工智能的兴起让Python一夜之间变得家喻户晓,Python号称目前最最简单易学的语言,现在有不少高校开始将Python作为大一新生的入门语言.本萌新也刚开 ...

  2. Jq_$.getJSON( )

    jQuery中的$.getJSON( )方法函数主要用来从服务器加载json编码的数据,它使用的是GET HTTP请求.使用方法如下: $.getJSON( url [, data ] [, succ ...

  3. Jenkins报表 代码 指标分析

    Jenkins报表 这表现在前面的章节中,也有可用最简单的一种是适用于 JUnit 测试报告的许多报表插件. 在生成后动作进行任何工作,你可以定义要创建的报告. 该构建已经完成,测试结果选项将可进一步 ...

  4. Kubernetes调用vSphere vSAN做持久化存储

    参考 1.vSphere Storage for Kubernetes 2.IBM vSphere Cloud Provider 3.GitHub vSphere Volume examples 一. ...

  5. openstack删除僵尸卷

    问题描述: 最近在清理openstack环境,在删除cinder云硬盘时,一直发现有两个卷在删除中. 解决方法如下: 首先我们去cinder的数据库中找到这个卷,命令为: MariaDB [(none ...

  6. A1020. Tree Traversals(25)

    这是一题二叉树遍历的典型题,告诉我们中序遍历和另外一种遍历序列,然后求任何一种遍历序列. 这题的核心: 建树 BFS #include<bits/stdc++.h> using names ...

  7. B1030 完美数列 (25 分)

    这是一道二分法的题目,许久不使用二分法,感觉有点生疏. #include<bits/stdc++.h> using namespace std; const int MAXN=100000 ...

  8. Linux第七周学习总结——可执行程序的装载

    Linux第七周学习总结--可执行程序的装载 作者:刘浩晨 [原创作品转载请注明出处] <Linux内核分析>MOOC课程http://mooc.study.163.com/course/ ...

  9. Oracle 12c 之前的版本路线图

  10. OneZero第二周第三次站立会议(2016.3.30)

    会议时间:2016年3月30日  13:00~13:20 会议成员:冉华,张敏,王巍,夏一鸣. 会议目的:汇报前一天工作,全体成员评论,确定会后修改内容或分配下一步任务. 会议内容: 1.前端,完成功 ...