1. 首页
  2. 资讯
  3. 技术指南

Algorand测试网第三方代码审计和测试:系统成熟 抗攻击性良好

Algorand的代码评审和测试——InCodeWeTrust团队.

发布于2019年5月 MaksKyryliuk

Algorand最近向公众开放了它的TestNet,以及他们发布的Java/JavaScript和GolangSDKs。

TestN…

Algorand代码评审和测试——InCodeWeTrust团队.

发布于2019年5月 MaksKyryliuk

Algorand最近向公众开放了它的TestNet,以及他们发布的Java/JavaScript和GolangSDKs。

TestNet资源被收集在一个完美的结构开发网络上(https://developer.algorand.org),并且包含了以开发为目的的用来运营独立节点和设置私人测试网络的所有东西。虽然源代码还没有公开发布在网络上(除了几个安装脚本文件),但是InCodeWeTrust已经获得了访问Algorand的私有代码库的许可,而这就是本篇文章的目的。

ALGORAND网络原则

Algorand的新协议旨在提高速度。从理论上讲,通过只在一轮投票中确定区块是最有效的。因此,应该大大增加每秒的交易量,并且保证每一个区块都立刻被完成。

由于没有安全性的速度并不能提供任何实际价值,Algorand将设计网络协议的重点放在“能够抵御长时间的网络分区,并从这些分区中快速恢复,从而解决现实世界中的许多攻击”上。网络分区是网络级攻击(与协议级攻击相反),攻击者将目标对准用户之间的通信链接,使用户很难或不可能进行交互。

网络攻击可以在任何去中心化的系统上执行。无论区块链是如何设计的,如果攻击者足够强大到可以永远停转一个网络分区,那么就不会有任何区块被产出。我们能做的最好的方法就是增加攻击者的区块链停止成本。

在PoW中,最坏的情况是相当糟糕的。两条链将会生成,每个分区各一条。当分割愈合时,较小的链就会消失。出现在那条链的所有交易都将被还原。网络攻击可以说是非常狡猾的。一个熟练而强大的对手可能会允许除特定协议信息之外的所有流量不受干扰地通过,这使得分区检测几乎不可能。

Algorand使用拜占庭协议,但针对全球规模和高性能进行了优化。(传统的BA最多有12个用户,要求参与者预先确定和公开。)这在大于三分之二的多数诚实条件下有效,并且不依赖于参与者有同步时钟。当诚实的信息被传递时,如果当选的领导人是恶意的,那么最坏情况下的延迟协议将在固定数量的步骤后达成,如果当选的领导人是诚实的,那么这个延迟协议将在两个步骤后达成。

该协议对任意长度未知的网络分区都具有较强的恢复能力,并且在分区解析和消息延迟修复后恢复速度较快。因为几乎瞬间从分区中恢复的功能,Algorand 协议使得停转区块链在经济上非常昂贵(因为攻击者需要频繁地为破坏网络付出费用)。

当一个诚实的领导者提出一个交易块时,第一个投票步骤与区块传播并行进行(即网络参与者在收到区块后立即投票)。实际上,在区块通过所有参与节点传播之后,只需要投票这一个步骤就可以生成证书。

为了将共识扩大到更多的网络参与者,Algorand使用了一种基于可验证随机函数的新机制,这个机制允许参与者私下检查他们是否被选中参与下一个区块的协议,而对他们选择的证明也会被包含在网络消息中。

在Algorand的协议中,用户除了私钥之外不保留任何私有状态,这就允许了Algorand可以在参与者发送消息后立即替换他们。这减少了在选定的参与者的身份暴露后而针对他们的攻击。

即使攻击者实现了对网络的完全控制,并指定哪个用户何时接收哪些消息,Algorand协议也不会分叉,用户的余额也将保持安全。

Algorand被设计为在完全无需许可的环境中高效而安全地工作,在这种环境中,任意数量的参与者都可以在任何时候加入或离开网络,而无需任何审查或任何类型的许可。

源代码审查

下面的代码评审完全基于Algorand私有存储库,目前还没有对公众开放。我们要感谢Algorand为我们提供访问权限,让我们作为第一个外部方执行此审查。由于存储库的私有状态,我们不能详细讨论代码逻辑。

代码结构和架构:

• 代码结构良好
•功能清晰
•代码短小
•无workarounds或黑客

代码格式和注释:
•适合13英寸的屏幕,无需水平滚动
•评论是描述性的
•没有代码注释,也没有代码碎片

可维护性:
•代码是自解释的,并为变量/函数命名适当的名称
•可重用性和可测试性得到了很好的支持

代码遵循面向对象的分析和设计原则。文件很短(通常少于300行),并且有重点。开发很直接了当,代码质量也很高。
代码遵循可配置性方法,并单独保存可配置值,因此即使值频繁更改,也不需要更改代码。

只需对现有代码进行最小的更改就可以很容易地添加扩展,并且代码是模块化的,因此可以很容易地替换组件。
从性能的角度来看,所有使用的数据类型都非常适合它们的用途——例如StringBuilder泛型集合类。

公共区块链项目总是要求高水平的安全性,我们很高兴得看到Algorand在身份验证、授权和数据输入验证方面使用了最佳的实践方法来抵御安全威胁。特别是可以在安全的外部机器上运行的kmd(KeyManagement Daemon密钥管理守护进程)将这个项目提升到了一个更高的层次。

源代码被有组织性地保存在命名优秀和解释恰当的文件夹中。
进一步查看选定的文件:

如上例所示,这种类型的注释经常出现在源文件中。它非常准确地解释了逻辑关系,不存在任何被误解的余地,这使得我们对逻辑的进一步预排变得无用武之地。
代码遵循典型的开闭原则和SRS(SingleResponsibility Principle 单责任原则)。函数和类构建良好,依赖项作为package来链接。
另一点值得一提的是,用于开发中的项目的私有存储库通常没有良好的文档记录,并且缺少自述文件。但Algorand并非如此,即使是私有存储库也有优秀的记录文档。

如此看来团队已经为储存库的公开发布做好了充分的准备。另外我们还注意到存储库使用了docker来统一安装过程。

该项目有2171提交和142个分支,发展得非常好。

在service.go,Algorand将服务定义为协议的实例。这个代码是Algorand共事的核心。

同样,代码也得到了很好的开发和注释。团队还使用TODO标记,它为开发人员创建一个自动的ToDo-list,这使团队易于管理源代码开发。

安装和功能测试。


储存库检查的第二部分是安装系统。为此,我们使用了两个不同的目标平台(OS-X和Linux)来评估不同的安装方法。
我们在MacBookPro 15(2017)、i72.8 GHz、16GBRAM、OSX High Sierra上安装了Algorand,并且在i73.2 GHz、16GBRAM、Ubuntu17.04 LTS上也安装了Algorand。两个系统都配备了512GBSSD。
有关安装说明,请参阅https://developer.algorand.org/

节点安装;System: Apple OS-X
下载和提取tar.gz文件后,安装运行,并自动缓解丢失目录等问题;非常顺利的过程:

:./update.sh-i -c stable -p ~/node -d ~/node/data –n
./update.sh: line102: /Users/xxx/node/algod: No such file or directory
CurrentVersion = 0
Latest Version = 131084
New versionfound
Update Downloaded to/var/folders/sf/t15_85yx06g29jf2ts1hpw7h0000gn/T/tmp.vhku2NPV/131084.tar.gz
Expandingupdate…
Validating update…
Starting the new updatescript to complete the installation…
./update.sh: line 301:pushd: /Users/xxx/node/data: No such file or directory
Failed toarchive logs (or none to archive)
./update.sh: line 313: popd:directory stack empty
… Resuming installation from the latestupdatescript
/var/folders/sf/t15_85yx06g29jf2ts1hpw7h0000gn/T/tmp.vhku2NPV/a/bin/update.sh:line 123: /Users/xxx/node/algod: No such file or directory
CurrentVersion = 0
Stopping node…
… node not running
Backingup current binary files…
Backing up current data files from/Users/xxx/node/data…
Installing new binary files…
Installingnew data files into /Users/xxx/node/data…
Checking for newledger in /Users/xxx/node/data
head:/Users/xxx/node/data/wallet-genesis.id: No such file or directory
Newgenesis ID, resetting wallets
New Ledger – restoring genesiswallets in /Users/xxx/node/data
New Ledger – importingrootkeys for genesis wallets
Imported 0 keys
Applyingmigration fixups…
Deleting existing log files in/Users/xxx/node/data
Install complete – restart node manually

配置好遥测后,我们开始启动节点:

:./goalnode start -d data
Algorand node successfully started!
Wethen check if the node daemon process is really running:
:pgrepalgod
61072

:./goalnode status -d data
Last committed block: 299
Time sincelast block: 0.0s
Sync Time: 0.0s
Last consensus protocol:v2
Next consensus protocol: v2
Round for next consensusprotocol: 300
Next consensus protocol supported: true

:./carpenter-d data
Watching file: data/node.log…
could not decodeline from JSON: ++++++++++++++++++++++++++++++++++++++++
couldnot decode line from JSON: Logging Starting
could not decodeline from JSON: Telemetry Enabled:486c33a2-cb1c-44ca-ac8e-746dd8de603f:Dirks-MacBook-Pro-2
couldnot decode line from JSON: Session:914dbb7b-1ff0-40fb-80c0-3da891f027f5
could not decode line fromJSON: ++++++++++++++++++++++++++++++++++++++++
:ProposalAssembled -300.0.0|
300.0.1: StepTimeout – |
:ProposalFrozen AAAAA-300.0.0|
300.0.2: StepTimeout –|
300.0.3: VoteAttest AAAAA- |
300.0.3: StepTimeout –|
300.0.4: VoteAttest AAAAA- |
300.0.4: StepTimeout –|
300.0.5: VoteAttest AAAAA- |
300.0.5: StepTimeout –|
300.0.6: VoteAttest AAAAA- |
300.0.6: StepTimeout –|
300.0.0: RoundInterrupted – |
: ProposalAssembled-301.0.0|
301.0.0: RoundInterrupted – |
:ProposalAssembled -302.0.0|
302.0.0: RoundInterrupted –|
…(truncated)

节点安装;System: Ubuntu 17.04

运行一个私人局域网testmode

虽然节点试图在一个无需许可的网络中运行,但是Algorand提供了一个选项,在部署到主网络之前创建一个用于开发和测试目的的许可(私有)网络。
我们首先定义由两个节点和三个钱包组成的私有网络:
TestNetwork.json
{
“Genesis”:{
“NetworkName”: “TestNetwork”,
“Wallets”:[
{
“Name”: “Wallet1”,
“Stake”:50,
“Online”: true
},
{
“Name”:“Wallet2”,
“Stake”: 40,
“Online”:true
},
{
“Name”: “Wallet3”,
“Stake”:10,
“Online”: false
}
]
},
“Nodes”:[
{
“Name”: “Primary”,
“IsRelay”:true,
“Wallets”: [
{
“Name”:“Wallet1”,
“ParticipationOnly”: false
}
]
},
{
“Name”:“Node”,
“Wallets”: [
{
“Name”:“Wallet2”,
“ParticipationOnly”: false
},
{
“Name”:“Wallet3”,
“ParticipationOnly”:false
}
]
}
]
}
我们根据上面的配置文件创建网络:

:./goalnetwork create -r ~/net1 -n private -t ./TestNetwork.json
Creatednew rootkey: /Users/xxx/net1/Wallet1.rootkey
Created newpartkey: /Users/xxx/net1/Wallet1.300.1000300.partkey
Created newrootkey: /Users/xxx/net1/Wallet2.rootkey
Created new partkey:/Users/xxx/net1/Wallet2.300.1000300.partkey
Created new rootkey:/Users/xxx/net1/Wallet3.rootkey
Created new partkey:/Users/xxx/net1/Wallet3.300.1000300.partkey
Network privatecreated under /Users/xxx/net1

然后我们用两个节点开始我们的网络:

:./goalnetwork start -r ~/net1
Network Started under/Users/drdirkbauer/net1

现在我们需要检查我们的网络状态与我们的节点“Prinmary”和“Node”:

:./goalnetwork status -r ~/net1
[Primary]
Last committed block:308
Time since last block: 2.4s
Sync Time: 0.0s
Lastconsensus protocol: v4
Next consensus protocol: v4
Roundfor next consensus protocol: 309
Next consensus protocolsupported: true

[代码翻译内容][节点]
最后一次提交区块:308
从上一个区块开始的时间:2.4s
同步时间:0.0s
上一个共识协议:v4
下一个共识协议:v4
下一轮共识协议:309
下一个支持的共识协议:true

节点可以被配置为标准节点或中继节点。标准节点有两种模式:存档模式和非存档模式。存档版本将存储系统上完整的区块链,non-archive版本只需要存储节点运行所需信息。中继节点将连接TestNet,并且总是存储系统上的完整区块链。
我们检查一下哪个钱包已经关联于我们的“Primary”节点:

:./goalwallet list -d ~/net1/Primary

#

Wallet:unencrypted-default-wallet
ID: 04df26305aa1337dcf6e787622b78cce

#

正如预期的那样,根据最初为网络提供的配置,只有一个钱包。我们尝试为这个节点创建另一个钱包:

:./goalwallet new MyWallet -d ~/net1/Primary
Please choose a passwordfor wallet ‘MyWallet’:
Please confirm thepassword:
Creating wallet…
Created wallet‘MyWallet’
Your new wallet has a backup phrase that can beused for recovery.
Keeping this backup phrase safe is extremelyimportant.
Would you like to see it now? (Y/n): Y
Yourbackup phrase is printed below.
Keep this information safe —never share it with anyone!
patient stand liar plunge hidden….(truncated seed phrase)

代码纯译文【:./goalwallet new MyWallet -d~/net1/Primary

请选择一个“MyWallet”的密码:
请确认密码:
创建钱包…
创建钱包‘MyWallet’
你的新钱包有一个备份可用于恢复。
保证这个备份的安全是非常重要的。
现在你想看到它吗?(Y/n):Y
你的备份如下。
保证这些信息的安全— 不要与任何人分享它!
patientstand liar plunge hidden ….(truncated seed phrase)】

我们将这个节点的新钱包设置为默认值:

:./goalwallet -f MyWallet -d ~/net1/Primary
And create two addressesfor the new default wallet
:./goal account new -d~/net1/Primary
Created new account with addressESIVU7EFBABFHE4ZGAYHYENRORD7DCN34JAHHVF5NJP3HDA6O6WTN35SXY
:./goal account new -d ~/net1/Primary
Created new account withaddress RZTAVIJEF7XNNDWUAMORBTLKVHGOA4WCJV7VRYR2XJ4RO23LZ5IWQQREO4

我们继续在这个钱包的两个地址之间创建一个交易:

:./goalclerk send -s -o ./raw.tx -a 100 -fESIVU7EFBABFHE4ZGAYHYENRORD7DCN34JAHHVF5NJP3HDA6O6WTN35SXY -tRZTAVIJEF7XNNDWUAMORBTLKVHGOA4WCJV7VRYR2XJ4RO23LZ5IWQQREO4 -d~/net1/Primary
Please enter the password for wallet ‘MyWallet’:…

我们检查交易是否成功:

:curl-s -X POST –>不出所料,这笔交易没有成功,因为我们从来没有资助过这个钱包。
最后,我们在这两种节点类型运行了超过48小时,并没有任何稳定性问题的情况下终止了私有网络的执行:

:./goalnetwork stop -r ~/net1
网络在/Users/drdirkbauer/net1下停止
在停止之前,我们还尝试了GoalCLI的其余命令集,没有遇到任何问题。一切都按照规格进行。
同样值得一提的是,我们对各种目标命令在选项/参数方面的一致性印象深刻。甚至与Linux相比,在Linux中,人们经常被迫使用不一致的选项的特定顺序。
Algorand给人的印象是一个非常坚实和成熟的系统,它给我们提供了一个非常精益的体验。

RestAPI
RestAPI可以在algod(Algorand协议守护进程)或kmd(密钥管理守护进程)上使用。algod进程在节点启动时自动启动。kmd流程需要被Goal调动。它主要用于密钥管理和交易签名,并且可以在独立的机器上运行(提高安全性)。它是一个支持关键业务流程的好概念。
我们通过签署一个交易来尝试RestAPI,它的工作方式完全符合预期。

SDK
Algorand为三种主要的开发语言Go、JS(node.js)和Java提供了SDK。GoSDK(我们过去使用的)在AlgorandGitHub上是可用的。SDK可以对抗kmd和algod(参见RestAPI)。
我们从GitHub上安装了GOSDK并进行了测试(前提是安装了GO语言库)。

:go get -u github.com/algorand/go-algorand-sdk/…
Then we startour node and key management daemon again:
:./goal node start -d~/algorand/TestNet/data/relay
Algorand node successfullystarted!

:./goalkmd start -d ./data/relay
Successfully started kmd

结论

Algorand之前为区块链生态系统引入了几个关键组件,现在已被广泛采用,它通过引入用于网络分区攻击的恢复机制进一步改进了区块链技术,使对手在任何时间中断网络的代价都变得异常高昂。

在测试体验方面,Algorand给人留下了深刻的印象,显示的小故障甚至比来自苹果和微软等全球供应商的软件还少(我们在日常的各种客户项目中都有经验)。

(InCodeWeTrust团队)

声明:登载此文出于传递更多信息之目的,观点仅代表作者本人,绝不代表Hi区块链赞同其观点或证实其描述。
提示:投资有风险,入市须谨慎。本资讯不作为投资理财建议。

特此通告:由于运营管理等问题,本站已转让出售。