Zhuang's Diary

言之有物,持之以恒

关于ethereum 中,nonce问题总结:

  • Tx 中 nonce 过低(too low)时,Tx 立即被拒绝
  • Tx 中 nonce 过高(too high)时,Tx 被放入交易池队列 transaction pool queue
  • 如果 Tx 的 nonce 正好填补了最新的有效的 nonce 和过高的nonce之间的空隙,是的nonce的顺序完整连接时,交易池队列中的交易将被执行
  • 当 Geth 被关掉或者重新启动时,交易池中的 Txs 将消失

nonce问题,详细介绍:

  • 当 Tx 中 nonce 过低时,
1
2
3
4
5
6
> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(1, "ether"), nonce:0})
Nonce too low
at InvalidResponse (<anonymous>:-81662:-106)
at send (<anonymous>:-156322:-106)
at sendTransaction (<anonymous>:-133322:-106)
at <anonymous>:1:1
  • 当 Tx 中 nonce 过高时,
1
2
3
4
5
> txpool.status
{
pending: 0,
queued: 1
}
  • Geth 重启时,
1
2
3
4
5
> txpool.status
{
pending: 0,
queued: 0
}

解决方案

  • 在应用本地保存nonce在数据库中,并且,数据库中的nonce值更新时需要访问锁保护。不建议将nonce保存在内存中,那样的话,在应用死机或者重启时,nonce将丢失。目前思考 Redis DB 是比较好的选择。

  • 如果本地nonce出了问题,可以使用 web3.eth.getTransactionCount(ethAddress) 来恢复。但是 web3.eth.getTransactionCount(ethAddress) 是内存中的值,不是实时准确的,不建议实时使用。

另外:

  • 即使交易池(queue)中有交易存在,nonce正确的交易仍然可以继续进行。

  • 当共识停止工作了,nonce正确的交易进入到pending队列中,nonce较高的交易进入到queue队列中。当共识重新正常工作时,pending队列中的交易会被自动处理而清空。

  • 同时节点具有每隔一个小时,重新处理一次本地交易的能力。(handle local transaction journal rotation)

参考链接 ==> https://ethereum.stackexchange.com/questions/2808/what-happens-when-a-transaction-nonce-is-too-high

参考代码 ==>

1
2
3
4
5
ethereum/go-ethereum/core/tx_pool.go 

func (pool *TxPool) loop() {
......
}

本问题调查过程中,使用到的命令==>

1
2
3
4
5
6
7
8
9
10
11
12
13
eth.getTransactionCount(eth.accounts[0])

personal.unlockAccount(eth.accounts[0],"1234",99999)

eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[0],value:100,nonce:200})

txpool.status

eth.sendTransaction({from:eth.accounts[0],to:eth.accounts[0]})

txpool.status

./odyssey update_Validator localhost:26657 UpdateValidator:OA+kUHbBDxh6q2kqF1jNQFoPqjTYsTS2m17un4Z9vI0=*/*10000

开源是社会化协作的基础。随着软件越来越昂贵、风险越来越大,单靠一个企业内的合作已经不够了,需要全球供应链、全球生产链来共同生产软件、维护软件、交付软件。开源也是社会化生产的需要。经过20年的发展,开源已经今非昔比。20年前,开源是一种软件的开发和交付方式;2020年,开源已经演进发展为一种生态竞争的模式。

开源的生产交付模式已发展成熟。2019年,70%的财富50强企业为GitHub(代码托管网站)贡献了开源代码。开源已经形成了两种模式:基金会主导模式(Linux模式)和企业主导模式(Android模式)。码农数量激增,因为码农是数字社会先进生产力的代表。

总而言之,开源几乎是躲不掉的,99%的组织已经在其 IT系统中使用了开源软件。2019年,中国的代码贡献量上升了48%。在中国,过去,开源的核心是国际项目本土化,现在,国内开源的焦点是本土项目国际化。重要的是,要将风险管控前置来治理开源。

参考链接:

何宝宏:预见2020,拐点已至丨风向Talks

https://spdx.org/licenses/

关于PBFT的监控,已tendermint为例,已经具备 Prometheus 监控能力。

具体参数请参见 ==> https://docs.tendermint.com/master/tendermint-core/metrics.html

List of available metrics

The following metrics are available:

Name Type Since Tags Description
consensus_height Gauge 0.21.0 Height of the chain
consensus_validators Gauge 0.21.0 Number of validators
consensus_validators_power Gauge 0.21.0 Total voting power of all validators
consensus_validator_power Gauge 0.33.0 Voting power of the node if in the validator set
consensus_validator_last_signed_height Gauge 0.33.0 Last height the node signed a block, if the node is a validator
consensus_validator_missed_blocks Gauge 0.33.0 Total amount of blocks missed for the node, if the node is a validator
consensus_missing_validators Gauge 0.21.0 Number of validators who did not sign
consensus_missing_validators_power Gauge 0.21.0 Total voting power of the missing validators
consensus_byzantine_validators Gauge 0.21.0 Number of validators who tried to double sign
consensus_byzantine_validators_power Gauge 0.21.0 Total voting power of the byzantine validators
consensus_block_interval_seconds Histogram 0.21.0 Time between this and last block (Block.Header.Time) in seconds
consensus_rounds Gauge 0.21.0 Number of rounds
consensus_num_txs Gauge 0.21.0 Number of transactions
consensus_total_txs Gauge 0.21.0 Total number of transactions committed
consensus_block_parts counter on dev peer_id number of blockparts transmitted by peer
consensus_latest_block_height gauge on dev /status sync_info number
consensus_fast_syncing gauge on dev either 0 (not fast syncing) or 1 (syncing)
consensus_block_size_bytes Gauge 0.21.0 Block size in bytes
p2p_peers Gauge 0.21.0 Number of peers node’s connected to
p2p_peer_receive_bytes_total counter on dev peer_id, chID number of bytes per channel received from a given peer
p2p_peer_send_bytes_total counter on dev peer_id, chID number of bytes per channel sent to a given peer
p2p_peer_pending_send_bytes gauge on dev peer_id number of pending bytes to be sent to a given peer
p2p_num_txs gauge on dev peer_id number of transactions submitted by each peer_id
p2p_pending_send_bytes gauge on dev peer_id amount of data pending to be sent to peer
mempool_size Gauge 0.21.0 Number of uncommitted transactions
mempool_tx_size_bytes histogram on dev transaction sizes in bytes
mempool_failed_txs counter on dev number of failed transactions
mempool_recheck_times counter on dev number of transactions rechecked in the mempool
state_block_processing_time histogram on dev time between BeginBlock and EndBlock in ms

go-ethereum 在 2019 年 7 月推出了 Geth v1.9.x 版本。

Geth 可以通过 --metrics 命令符收集运行状态信息。 Geth v1.9.x 有3套独立的监控体系,ExpVarsInfluxDBPrometheus

  1. ExpVars

是将Golang系统公共指标暴露给到HTTP接口。Geth 用 pprof 来作为埋点暴露这些公共参数。

运行 Geth –metrics –pprof 将暴露指标成为ExpVars的格式,于地址

http://127.0.0.1:6060/debug/metrics。

ExpVars 有 Golang 非常好的支持。

  1. Prometheus

同理 ExpVars,运行 Geth –metrics –pprof 将暴露指标成为Prometheus的格式,于地址

http://127.0.0.1:6060/debug/metrics/prometheus。

Prometheus更加接近业界的标准。

  1. InfluxDB

ExpVarsPrometheus 是拉取pull数据的监控方式。InfluxDB 是推送push数据的监控方式。

InfluxDB的启用有些麻烦,请参见 geth help 中的 --metrics.influxdb 及其子标识。

参数可视化

推荐使用 Grafana,建议使用 geth-prometheus 项目中给出的图表,参考链接==> https://github.com/karalabe/geth-prometheus。效果如下图:

参考文档==> Geth v1.9.0 Six months distilled

具体功能如下:

  • 节点进程监控
    • 节点的存活,进程中CPU、内存使用率,IO
  • 区块链数据健康监控
    • 节点出块高度历史,出块时间,出块间隔趋势,交易量历史,TPS,磁盘占用,数据目录大小增长趋势
  • 运行环境监控
    • 主机运行环境的系统负载、CPU、内存、磁盘空间使用情况、网络流量、TCP 连接数等
  • 故障告警通知
    • 监控告警策略
    • 支持邮件通知、短信通知
  • 节点网络监控
    • 连接节点数、网络拓扑、地理位置等

仪表板的监控指标:

  • Summary Dashboard
    • 各节点最新块高
    • 各节点监控进程存活
    • 各节点 CPU 使用率变化
    • 节点列表
  • Node Info Dashboard
    • Chain Meta Data - 链的配置信息,如 Chain Name、创建时间等
    • Chain Info - 链的最新块高、共识节点数、共识节点出块历史趋势
    • Node Info - 选定节点的详细信息,包括区块链数据、运行环境、运行软件信息
  • Host Info Dashboard
    • 各节点运行主机的信息,包括系统负载、CPU、内存、硬盘使用率、网络流量
  • Process Info Dashboard
    • 节点中进程(pprof)的历史情况、CPU、内存、IO 变化历史

go-ethereum 在 2019 年 7 月推出了 v1.9.x 版本。

Geth v1.9.0为轻型客户端提供了一种新模式,称为超轻型客户端 ultra light client

此模式旨在将自己定位在受信任服务器和轻型服务器之间的安全范围中,用来自大多数受信任服务器的数字签名代替PoW验证。借助来自独立实体的足够签名,可以为非关键DApp实现远远超过足够的安全性。就是说,超轻量客户端模式并不是真正针对您的普通节点,而是希望将Geth嵌入到自己的流程中的项目。

轻客户端不下载和验证任何块头,而是使用硬编码检查点(hard coded checkpoint)作为起点。这个检查点包含了全部的必要的信息,从而验证之前的区块的正确性。所以从安全角度而言,没有任何的损失。

但是硬编码检查点(hard coded checkpoint)也有缺点:

  • 由于检查点被硬编码到发行版二进制文件中,因此较旧的发行版将始终从较旧的块开始同步。几个月就可以了,但是最终变得很烦人。当然,您可以更新Geth来获取一个新的检查点,也可以获取所有的变更,但是很少有人希望这样做。
  • 由于这些检查点已嵌入到代码中,因此如果您想在自己的专用网络中支持它们,那将很不幸,需要修改Geth,或通过配置文件配置检查点,并在每次更新检查点时分发一个新文件。可行,但长期而言并不可行。

Geth v1.9.x 附带了对链上检查点oracle的支持。超轻型客户端 ultra light client 可以不依赖于硬编码的检查点,而可以联系远程轻服务器,并要求它们返回存储在链上智能合约中的更新的检查点。最好的部分是,超轻型客户端 ultra light client 可以通过密码证明返回的数据已由所需数量的批准验证者签名!

等等,超轻型客户端 ultra light client 如何知道谁被授权签署链上检查站?对于开箱即用的受支持网络,Geth附带硬编码的检查点oracle地址和授权签署者的列表;对于专用网络,可以通过配置文件指定oracle详细信息。

尽管新旧检查点机制看起来很相似(两者都需要Geth或配置文件中的硬编码数据),但新检查点oracle只需要配置一次,然后可以任意长时间使用以发布新的检查点。

checkpoint-adminGeth v1.9.x 附带的针对 checkpoint oracle contract 的管理工具。

checkpoint-admin 可用于查询已部署合同的状态。--rpc 需要指向一个light node,或者一个开启 --lightserv 特性的 full node。

1
2
3
4
5
6
7
8
9
$ checkpoint-admin --rpc ~/.ethereum/rinkeby/geth.ipc status
Oracle => 0xebe8eFA441B9302A0d7eaECc277c09d20D684540

Admin 1 => 0xD9C9Cd5f6779558b6e0eD4e6Acf6b1947E7fA1F3
Admin 2 => 0x78d1aD571A1A09D60D9BBf25894b44e4C8859595
Admin 3 => 0x286834935f4A8Cfb4FF4C77D5770C2775aE2b0E7
Admin 4 => 0xb86e2B0Ab5A4B1373e40c51A7C712c70Ba2f9f8E

Checkpoint (published at #4638418) 140 => 0x488c2eba92d31baeccfb6968fad5c21a3df93181b43b4cf253b4d572b64172ef

该命令也可以用户部署一个oracle,用以更新checkpoint,并publish该checkpoint到区块链网络中。

将来,checkpoint-admin 也可以离线工作,并有 clef 钱包签名。

参考文档==> Geth v1.9.0 Six months distilled