Zhuang's Diary

言之有物,持之以恒

IP地址介绍

IP地址由两个部分组成,net-id和host-id,即网络号和主机号。
net-id:表示ip地址所在的网络号。
host-id:表示ip地址所在网络中的某个主机号码。

即:

1
IP-address ::=  { <Network-number>, <Host-number> }

IP地址分类

IP地址一共分为5类,即A~E,它们分类的依据是其net-id所占的字节长度以及网络号前几位。

  • A类地址:网络号占1个字节。

    网络号的第一位固定为0。

  • B类地址:

    网络号占2个字节。

    网络号的前两位固定为10。

  • C类地址:

    网络号占3个字节。

    网络号的前三位固定位110。

  • D类地址:

    前四位是1110,用于多播(multicast),即一对多通信。

  • E类地址:

    前四位是1111,保留为以后使用。

其中,ABC三类地址为单播地址(unicast),用于一对一通信,是最常用的。

特殊IP地址

就是用来做一些特殊的事情。RFC1700中定义了以下特殊IP地址。

  1. {0,0}:网络号和主机号都全部为0,表示“本网络上的本主机”,只能用作源地址。
  2. {0,host-id}:本网络上的某台主机。只能用作源地址。
  3. {-1,-1}:表示网络号和主机号的所有位上都是1(二进制),用于本网络上的广播,只能用作目的地址,发到该地址的数据包不能转发到源地址所在网络之外。
  4. {net-id,-1}:直接广播到指定的网络上。只能用作目的地址。
  5. {net-id,subnet-id,-1}:直接广播到指定网络的指定子网络上。只用作目的地址。
  6. {net-id,-1,-1}:直接广播到指定网络的所有子网络上。只能用作目的地址。
  7. {127,}:即网络号为127的任意ip地址。都是内部主机回环地址(loopback),永远都不能出现在主机外部的网络中。

127.0.0.1和0.0.0.0地址的区别是什么?

我们先来看下共同点:

  1. 都属于特殊地址。
  2. 都属于A类地址。
  3. 都是IPV4地址。

0.0.0.0

IPV4中,0.0.0.0地址被用于表示一个无效的,未知的或者不可用的目标。

  • 在服务器中,0.0.0.0指的是本机上的所有IPV4地址,如果一个主机有两个IP地址,192.168.1.1 和 10.1.2.1,并且该主机上的一个服务监听的地址是0.0.0.0,那么通过两个ip地址都能够访问该服务。
  • 在路由中,0.0.0.0表示的是默认路由,即当路由表中没有找到完全匹配的路由的时候所对应的路由。

用途

  • 当一台主机还没有被分配一个IP地址的时候,用于表示主机本身。(DHCP分配IP地址的时候)
  • 用作默认路由,表示”任意IPV4主机”。用来表示目标机器不可用。
  • 用作服务端,表示本机上的任意IPV4地址。

127.0.0.1

127.0.0.1属于{127,}集合中的一个,而所有网络号为127的地址都被称之为回环地址,它们是包含关系,即回环地址包含127.0.0.1。
回环地址:所有发往该类地址的数据包都应该被loop back。

用途

  • 回环测试,通过使用ping 127.0.0.1 测试某台机器上的网络设备,操作系统或者TCP/IP实现是否工作正常。
  • DDos攻击防御:网站收到DDos攻击之后,将域名A记录到127.0.0.1,即让攻击者自己攻击自己。
  • 大部分Web容器测试的时候绑定的本机地址。

localhost

相比127.0.0.1,localhost具有更多的意义。localhost是个域名,而不是一个ip地址。之所以我们经常把localhost与127.0.0.1认为是同一个是因为我们使用的大多数电脑上都讲localhost指向了127.0.0.1这个地址。
在ubuntu系统中,/ets/hosts文件中都会有如下内容:

1
2
3
4
5
6
7
8
127.0.0.1   localhost
127.0.1.1 jason-Lenovo-V3000
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

上面第一行是几乎每台电脑上都会有的默认配置。
但是localhost的意义并不局限于127.0.0.1。

localhost是一个域名,用于指代this computer或者this host,可以用它来获取运行在本机上的网络服务。
在大多数系统中,localhost被指向了IPV4的127.0.0.1和IPV6的::1。

1
2
127.0.0.1    localhost
::1 localhost

所以,在使用的时候要注意确认IPV4还是IPV6

总结

127.0.0.1 是一个环回地址。并不表示“本机”。0.0.0.0才是真正表示“本网络中的本机”。
在实际应用中,一般我们在服务端绑定端口的时候可以选择绑定到0.0.0.0,这样我的服务访问方就可以通过我的多个ip地址访问我的服务。

比如我有一台服务器,一个外网地址A,一个内网地址B,如果我绑定的端口指定了0.0.0.0,那么通过内网地址或外网地址都可以访问我的应用。但是如果我只绑定了内网地址,那么通过外网地址就不能访问。所以如果绑定0.0.0.0,也有一定安全隐患,对于只需要内网访问的服务,可以只绑定内网地址。

简介

ERC777保持与 ERC20 兼容。

操作员通常利用合约发送token,并具备发送 / 接收钩子,以使得持有者对其token拥有更多的控制权。

它利用 ERC1820 来了解在合同和用户地址收到token时是否以及在何处通知它们。

解决的问题(相对于ERC20的优点)

  1. 同样使用 send(dest, value, data) 发送Ether
  2. 使用 tokensToSend 钩子,合约和用户地址都可以控制和拒绝发送出去的token
  3. 使用 tokensReceived 钩子,合约和用户地址都可以控制和拒绝接收到的token
  4. tokensReceived 钩子允许发送token到合约地址,并在交易中心发出通知。而ERC20需要approve/transferFrom 两次调用才能达到这样的效果
  5. token持有人可以指定/去除操作员(合约)地址,这些操作员通常是已经验证过的合约contract,例如交易所,支票处理器或自动收费系统
  6. 每一笔交易含有 dataoperatorData ,它们是bytes字段,在token持有人和操作员之间传递信息
  7. tokensReceived 钩子函数可以通过代理合约来部署,所以ERC777是与ERC20钱包兼容的

构建ERC777合约

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
pragma solidity ^0.5.0;

import "@openzeppelin/contracts/token/ERC777/ERC777.sol";

contract GLDToken is ERC777 {
constructor(
uint256 initialSupply,
address[] memory defaultOperators
)
ERC777("Gold", "GLD", defaultOperators)
public
{
_mint(msg.sender, msg.sender, initialSupply, "", "");
}
}

ERC777扩展了ERC20,对ERC20提供兼容性支持。使用 _mintinitialSupply 分配给部署者帐户。与ERC20的_mint不同,此参数包含一些额外的参数,但是可以放心地忽略它们。

initialSupply 没有设定小数。ERC777规定小数始终返回固定值18,因此无需自行设置。

最后,我们需要设置defaultOperators:操作员帐户(通常是智能合约地址),该帐户将能够代表其持有者转让token。如果不打算在token中使用操作员(合约),则只需传递一个空数组即可。

基本的ERC777合约就是这样! 现在,对其进行部署,并使用相同的balanceOf方法来查询部署者的余额:

1
2
> GLDToken.balanceOf(deployerAddress)
1000

要将token从一个帐户转移到另一个帐户,既可以使用ERC20的“transfer”方法,也可以使用新的ERC777的“send”方法,其作用非常相似,但是增加了一个可选的data字段:

1
2
3
4
5
6
> GLDToken.transfer(otherAddress, 300)
> GLDToken.send(otherAddress, 300, "")
> GLDToken.balanceOf(otherAddress)
600
> GLDToken.balanceOf(deployerAddress)
400

ERC777接口定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
interface ERC777Token {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function totalSupply() external view returns (uint256);
function balanceOf(address holder) external view returns (uint256);

// 定义代币最小的划分粒度。
// 要求必须在创建时设定,之后不可以更改,不管是在铸币、发送还是销毁操作的代币数量,必需是粒度的整数倍
function granularity() external view returns (uint256);

// 操作员 相关的操作(操作员是可以代表持有者发送和销毁代币的账号地址)
function defaultOperators() external view returns (address[] memory);
function isOperatorFor(
address operator,
address holder
) external view returns (bool);
// 设置一个地址作为 msg.sender 的操作员,需要触发 AuthorizedOperator 事件
function authorizeOperator(address operator) external;
// 移除 msg.sender 上 operator 操作员的权限, 需要触发 RevokedOperator 事件
function revokeOperator(address operator) external;

// 发送代币
function send(address to, uint256 amount, bytes calldata data) external;
function operatorSend(
address from,
address to,
uint256 amount,
bytes calldata data,
bytes calldata operatorData
) external;

// 销毁代币
function burn(uint256 amount, bytes calldata data) external;
function operatorBurn(
address from,
uint256 amount,
bytes calldata data,
bytes calldata operatorData
) external;

// 发送代币事件
event Sent(
address indexed operator,
address indexed from,
address indexed to,
uint256 amount,
bytes data,
bytes operatorData
);

// 铸币事件
event Minted(
address indexed operator,
address indexed to,
uint256 amount,
bytes data,
bytes operatorData
);

// 销毁代币事件
event Burned(
address indexed operator,
address indexed from,
uint256 amount,
bytes data,
bytes operatorData
);

// 授权操作员事件
event AuthorizedOperator(
address indexed operator,
address indexed holder
);

// 撤销操作员事件
event RevokedOperator(address indexed operator, address indexed holder);
}

钩子函数如何工作

首先来了解一下 ERC1820, ERC1820是一个全局的合约,在以太坊链上有一个唯一的合约地址,它总是 0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24

ERC1820 合约提过了两个主要接口:

  • setInterfaceImplementer(address _addr, bytes32 _interfaceHash, address _implementer)
    用来设置地址(_addr)的接口(_interfaceHash 接口名称的 keccak256 )由哪个合约实现(_implementer)。
  • getInterfaceImplementer(address _addr, bytes32 _interfaceHash) external view returns (address)
    这个函数用来查询地址(_addr)的接口由哪个合约实现。

ERC777 使用 send 转账时,会分别在持有者和接收者地址上使用 ERC1820 的 getInterfaceImplementer 函数进行查询,查看是否有对应的实现合约,ERC777 标准规范里预定了接口及函数名称,如果有实现则进行相应的调用。

ERC777 使用 operatorSend 转账时,可以通过参数operatorData携带操作者的信息,发送代币除了执行对应账户的余额加减和触发事件之外,还有额外的规定

  1. 如果持有者有通过 ERC1820 注册 ERC777TokensSender 实现接口,代币合约必须调用其 tokensToSend 钩子函数。
  2. 如果接收者有通过 ERC1820 注册 ERC777TokensRecipient 实现接口, 代币合约必须调用其 tokensReceived 钩子函数。
  3. 如果有 tokensToSend 钩子函数,必须在修改余额状态之前调用。
  4. 如果有 tokensReceived 钩子函数,必须在修改余额状态之后调用。
  5. 调用钩子函数及触发事件时,dataoperatorData必须原样传递,因为 tokensToSend 和 tokensReceived 函数可能根据这个数据取消转账(触发 revert)。

从而保证了ERC777交易以及钩子函数的原子性。

参考链接 ==>

https://eips.ethereum.org/EIPS/eip-777

https://github.com/0xjac/ERC777

https://docs.openzeppelin.com/contracts/2.x/erc777

https://github.com/OpenZeppelin/openzeppelin-contracts

go1.5.2 version

step 1. init

–home /home/zhuang/Documents/melody-bk/script/run/data init –melody_parameters=”–datadir /home/zhuang/Documents/melody-bk/script/run/data init /home/zhuang/Documents/melody-bk/script/etc/genesis.template”

step 1. start

–home
/home/zhuang/Documents/melody/script/run/data
–consensus.create_empty_blocks=false
node
–melody_parameters=”–datadir /home/zhuang/Documents/melody/script/run/data –http –http.addr=”0.0.0.0” –http.port=”8545” –ws –ws.addr=”0.0.0.0” –ws.port=”8546” –verbosity 3 –http.api eth,net,web3,personal,admin –tendermint_addr=tcp://0.0.0.0:26657 –abci_laddr=tcp://127.0.0.1”

nmon 工具运行于:

  • AIX® 4.1.5、4.2.0、4.3.2 和 4.3.3(nmon Version 9a:该版本的功能已经确定,并且不会对其进行进一步的开发。)
  • AIX 5.1、5.2 和 5.3(nmon Version 10:该版本现在支持 AIX 5.3 和基于 POWER5™ 处理器的计算机,并且提供了 SMT 和共享 CPU 微分区的支持。)
  • pSeries® p5 和 OpenPower™ 上的 Linux™ SUSE SLES 9、Red Hat EL 3 和 4、Debian
  • Linux SUSE、Red Hat 和许多最新的 x86(32 位模式的 Intel 和 AMD)上的发布版
  • zSeries® 或 mainframe 上的 Linux SUSE 和 Red Hat

该工具的作用

nmon 工具可以帮助在一个屏幕上显示所有重要的性能优化信息,并动态地对其进行更新。这个高效的工具可以工作于任何哑屏幕、telnet 会话、甚至拨号线路。另外,它并不会消耗大量的 CPU 周期,通常低于百分之二。在更新的计算机上,其 CPU 使用率将低于百分之一。

使用哑屏幕,在屏幕上对数据进行显示,并且每隔两秒钟对其进行更新。然而,您可以很容易地将这个时间间隔更改为更长或更短的时间段。如果您拉伸窗口,并在 X Windows、VNC、PuTTY 或类似的窗口中显示这些数据,nmon 工具可以同时输出大量的信息。

nmon 工具还可以将相同的数据捕获到一个文本文件,便于以后对报告进行分析和绘制图形。输出文件采用电子表格的格式 (.csv)。

nmon 工具可以为 AIX 和 Linux 性能专家提供监视和分析性能数据的功能,其中包括:

  • CPU 使用率
  • 内存使用情况
  • 内核统计信息和运行队列信息
  • 磁盘 I/O 速度、传输和读/写比率
  • 文件系统中的可用空间
  • 磁盘适配器
  • 网络 I/O 速度、传输和读/写比率
  • 页面空间和页面速度
  • CPU 和 AIX 规范
  • 消耗资源最多的进程
  • IBM HTTP Web 缓存
  • 用户自定义的磁盘组
  • 计算机详细信息和资源
  • 异步 I/O,仅适用于 AIX
  • 工作负载管理器 (WLM),仅适用于 AIX
  • IBM TotalStorage® Enterprise Storage Server® (ESS) 磁盘,仅适用于 AIX
  • 网络文件系统 (NFS)
  • 动态 LPAR (DLPAR) 更改,仅适用于面向 AIX 或 Linux 的 pSeries p5 和 OpenPower

获取nmon

http://nmon.sourceforge.net/pmwiki.php

示例

对于区块链应用场景,需要共识算法具有如下特性:

  • Throughput吞吐量:transaction per second 意味着区块链系统每秒能处理的交易笔数,为了能够满足全球用户,交易处理速度必须足够大,否则会造成交易积压,并导致回复时间长。比如 bitcoin 的交易拥堵和以太坊因为 crytokitties 造成的网络拥堵。
  • Latency交易延时:交易从提交到回复成功与否的时间。在 PoW 网络中,因为有分叉可能,一般要等待几个块后确定。在 BFT 共识系统中,因为正确节点都在共识结束后就确定性有相同结果,所以在交易不拥堵的情况下,响应速度与共识时间相同。
  • Scalability:区块链系统参与的节点数。对基于 PoW 共识的系统,安全度与参与的诚实算力相关。对于基于 BFT 共识的系统,参与节点数越多,能容纳的恶意节点越多,恶意节点少于 1/3。但是对于 BFT 系统,节点越多,通信和计算开销越大。Algorand 提出利用 Verifiable Random Function 随机选出一部分节点形成 committee参与共识,保证了无论总节点数多大,最后的 committee 数目一定,共识速度就不变。
  • Security:对于 BFT 共识,安全度包含 consistence,liveness 和 fairness。Consistence 是系统内所有诚实节点要最终达到相同的状态。Liveness 需要系统在任意情况下都能收敛到确定状态,并且能持续接受交易,产生正确的共识结果。Fairness 在于对于系统的用户,任意合法的交易都不会被拒绝。

对于传统的 PBFT 系统,需要假设网络处于弱同步状态,通过超时和换主来保证 liveness。但是因为换主是确定性地换到预先设定的下一个节点,而且每次换主导致的节点消息同步耗时长,主节点会被连续不断的网络攻击导致瘫痪,最终系统持续换主,永远无法共识交易,相当于停滞状态。

对此,Tendermint 提出由 Voting Power 值决定,从而避免了一直由主节点提交请求,一定程度上避免了攻击的薄弱点。但是这依然无法避免Leader节点的可预测性,导致被依次攻击,系统每轮共识无法完成。

Honey Badger 提出了基于 RBC(Reliable Broadcast)和 BA(Binary Agreement)的协议。核心在于任意节点都可以提出共识消息,通过 RBC 可靠传播到所有节点,并且为了减小广播带宽,通过 erasure code 分割消息为多份。同时所有节点都通过 BA 协议共识所有消息,BA 协议的执行会在任意情况下快速收敛到 1 或者 0,表示对共识消息的接受与否。该协议相当于每一轮,所有节点并行地提出交易、共识,最终得到交易的子集作为共识结果。所以对任意一个节点的攻击,都不会造成整个网络的崩溃,只会影响网络部分性能。而且能充分利用带宽,适合全球部署。该协议的缺点在于交易响应延时比较高,因为每轮要共识多个节点的交易。同时协议需要预先确定节点的集合,不能动态添加节点,不能支持大规模节点。

为了解决节点添加和扩充节点的问题,Algorand 提出将 VRF(Verifiable Random Function)和 BA 结合起来。无论节点数目多少,通过 VRF 和持有的代币数随机选出特定数目节点,然后节点通过 BA 相互发送交易,并对优先级最高(VRF 随机数最小)的节点发出的交易共识。为了提高安全性,共识的每一步都通过 VRF 选出新一轮共识节点,从而让攻击者无法预测下一个攻击目标。该协议的主要有点在响应时间短,缺点在于无法做到高吞吐量和窄带宽。

Dfinity 主要是通过 threshold 签名来保证 VRF 的每一轮都能确定性地收到 signature。结合Random Beacon 和 Notaries 来使每一轮的成员都随机选择,并且提交的块按照本轮随机数进行排名。但是一个潜在的经济学博弈问题是,threshold 签名可以通过多个成员的合谋的方法来预测,合谋的成员可以协同计算出群私钥,快速预测出下一轮的随机数。通过作恶 DoS 攻击下一轮的成员的目的,合谋者可以破坏网络的公平性。因为这种攻击是不容易被发现的,所以可以做到零成本收益,因而在现实世界必然会出现。