ERC-721

什么是 ERC-721?

ERC-721 是一个描述了如何在以太坊区块链上构建不可替代的或者唯一的代币的自由开放的标准。相对于多数代币都是可互相替代的(每个代币都与其他代币相同),ERC-721 代币则是独一无二的。

请把它们当成独一无二的稀有收藏品。

ERC-20:一种同质代币

ERC-721:一种非同质代币

标准

ERC-721 定义了一个智能合约需要实现最小的接口集,允许对唯一的代币进行管理、持有和交易。它不强制规定代币元数据的标准,也不限制在此上添加的附加功能。

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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*
* @title ERC721 接口
*/

contract ERC721 {
/// @dev This emits when ownership of any NFT changes by any mechanism.
/// This event emits when NFTs are created (`from` == 0) and destroyed
/// (`to` == 0). Exception: during contract creation, any number of NFTs
/// may be created and assigned without emitting Transfer. At the time of
/// any transfer, the approved address for that NFT (if any) is reset to none.
event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);

/// @dev This emits when the approved address for an NFT is changed or
/// reaffirmed. The zero address indicates there is no approved address.
/// When a Transfer event emits, this also indicates that the approved
/// address for that NFT (if any) is reset to none.
event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);

/// @dev This emits when an operator is enabled or disabled for an owner.
/// The operator can manage all NFTs of the owner.
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);

/// @notice Count all NFTs assigned to an owner
/// @dev NFTs assigned to the zero address are considered invalid, and this
/// function throws for queries about the zero address.
/// @param _owner An address for whom to query the balance
/// @return The number of NFTs owned by `_owner`, possibly zero
function balanceOf(address _owner) external view returns (uint256);

/// @notice Find the owner of an NFT
/// @param _tokenId The identifier for an NFT
/// @dev NFTs assigned to zero address are considered invalid, and queries
/// about them do throw.
/// @return The address of the owner of the NFT
function ownerOf(uint256 _tokenId) external view returns (address);

/// @notice Transfers the ownership of an NFT from one address to another address
/// @dev Throws unless `msg.sender` is the current owner, an authorized
/// operator, or the approved address for this NFT. Throws if `_from` is
/// not the current owner. Throws if `_to` is the zero address. Throws if
/// `_tokenId` is not a valid NFT. When transfer is complete, this function
/// checks if `_to` is a smart contract (code size > 0). If so, it calls
/// `onERC721Received` on `_to` and throws if the return value is not
/// `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`.
/// @param _from The current owner of the NFT
/// @param _to The new owner
/// @param _tokenId The NFT to transfer
/// @param data Additional data with no specified format, sent in call to `_to`
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;

/// @notice Transfers the ownership of an NFT from one address to another address
/// @dev This works identically to the other function with an extra data parameter,
/// except this function just sets data to ""
/// @param _from The current owner of the NFT
/// @param _to The new owner
/// @param _tokenId The NFT to transfer
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;

/// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
/// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE
/// THEY MAY BE PERMANENTLY LOST
/// @dev Throws unless `msg.sender` is the current owner, an authorized
/// operator, or the approved address for this NFT. Throws if `_from` is
/// not the current owner. Throws if `_to` is the zero address. Throws if
/// `_tokenId` is not a valid NFT.
/// @param _from The current owner of the NFT
/// @param _to The new owner
/// @param _tokenId The NFT to transfer
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;

/// @notice Set or reaffirm the approved address for an NFT
/// @dev The zero address indicates there is no approved address.
/// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
/// operator of the current owner.
/// @param _approved The new approved NFT controller
/// @param _tokenId The NFT to approve
function approve(address _approved, uint256 _tokenId) external payable;

/// @notice Enable or disable approval for a third party ("operator") to manage
/// all of `msg.sender`'s assets.
/// @dev Emits the ApprovalForAll event
/// @param _operator Address to add to the set of authorized operators.
/// @param _approved True if the operators is approved, false to revoke approval
function setApprovalForAll(address _operator, bool _approved) external;

/// @notice Get the approved address for a single NFT
/// @dev Throws if `_tokenId` is not a valid NFT
/// @param _tokenId The NFT to find the approved address for
/// @return The approved address for this NFT, or the zero address if there is none
function getApproved(uint256 _tokenId) external view returns (address);

/// @notice Query if an address is an authorized operator for another address
/// @param _owner The address that owns the NFTs
/// @param _operator The address that acts on behalf of the owner
/// @return True if `_operator` is an approved operator for `_owner`, false otherwise
function isApprovedForAll(address _owner, address _operator) external view returns (bool);

/// @notice Query if a contract implements an interface
/// @param interfaceID The interface identifier, as specified in ERC-165
/// @dev Interface identification is specified in ERC-165. This function
/// uses less than 30,000 gas.
/// @return `true` if the contract implements `interfaceID` and
/// `interfaceID` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

ERC-721 标准是由 @dete 提出的 EIP 草案,并由 Axiom Zen 首次在加密猫项目上落地。

ERC-721 已经脱离测试版并进入社区规范 v1,支持和支持了大量加密生态系统的项目。如果脱离社区成员的奉献,该 EIP 是不能实现的。特别感谢 @fulldecent 和其他为推动这一进步付出大量努力的人们。

ERC-721 测试时期构建的项目

  • CryptoCelebrities
  • CryptoKitties
  • EtherTulips

构建你自己的 ERC-721 代币

交易 ERC-721 代币

参考资料


ERC20 代币标准

原文链接:https://theethereum.wiki/w/index.php/ERC20_Token_Standard

ERC20 代币标准描述了基于以太坊代币合约的一系列待实现的方法和事件。

ERC20 代币标准接口

下面是一个适配 ERC20 标准要求的方法和事件的合约接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ----------------------------------------------------------------------------
// ERC 代币标准 #20 接口
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
// ----------------------------------------------------------------------------
contract ERC20Interface {
function totalSupply() public constant returns (uint);
function balanceOf(address tokenOwner) public constant returns (uint balance);
function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);

event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}

以太坊区块链上的多数主要的代币都是兼容 ERC20 的。GNT 是唯一一个部分兼容 ERC20 的,它没有实现 approve(...)allowance(..)transferFrom(...) 方法和 Approval(...) 事件。

部分代币包含了更多的描述信息:

1
2
3
string public constant name = "代币名称";
string public constant symbol = "SYM";
uint8 public constant decimals = 18; // 18 是小数点后最大长度

代币合约是怎么运行的?

下面是代币合约的一个片段,证明代币合约如何维护以太坊账户的代币余额的:

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
contract TokenContractFragment {

// 每个账户的余额
mapping(address => uint256) balances;

// 账户拥有者认可的向其他账户的转账
mapping(address => mapping (address => uint256)) allowed;

// 获取账户 `tokenOwner` 的代币余额
function balanceOf(address tokenOwner) public constant returns (uint balance) {
return balances[tokenOwner];
}

// 从拥有者账户转账到其他账户
function transfer(address to, uint tokens) public returns (bool success) {
balances[msg.sender] = balances[msg.sender].sub(tokens);
balances[to] = balances[to].add(tokens);
Transfer(msg.sender, to, tokens);
return true;
}

// 将 `tokens` 个代币从地址 `from` 转给 `to`
// transferFrom 方法用于提现工作流,允许合约以你的名义发送代币、
// 转让代币或者收取费用。除非 _from 账户已经通过某种机制得到了
// 发送者的授权,否则将返回失败。我们期望标准 API 如下:
function transferFrom(address from, address to, uint tokens) public returns (bool success) {
balances[from] = balances[from].sub(tokens);
allowed[from][msg.sender] = allowed[from][msg.sender].sub(tokens);
balances[to] = balances[to].add(tokens);
Transfer(from, to, tokens);
return true;
}

// 允许 `spender` 从你的账户提现多次直到达到 `tokens`。
// 方法被再次调用则会用 _value 覆盖当前值。
function approve(address spender, uint tokens) public returns (bool success) {
allowed[msg.sender][spender] = tokens;
Approval(msg.sender, spender, tokens);
return true;
}
}

代币余额

假设某个代币合约有下面两个代币持有者:

  • 0x1111 余额 100 单位
  • 0x2222 余额 200 单位

代币合约余额数据结构包含如下信息:

1
2
balances[0x1111] = 100
balances[0x2222] = 200

balanceOf(...) 方法返回如下值:

1
2
tokenContract.balanceOf(0x1111) 将返回 100
tokenContract.balanceOf(0x2222) 将返回 200

代币转账

如果 0x1111 想转给 0x2222 10 个代币,0x1111 要执行该方法:

1
tokenContract.transfer(0x2222, 10)

代币合约的 transfer(...) 方法会更新包含如下信息的 balances 数据结构:

1
2
balances[0x1111] = 90
balances[0x2222] = 210

balanceOf(...) 方法现在返回如下:

1
2
tokenContract.balanceOf(0x1111) 将返回 90
tokenContract.balanceOf(0x2222) 将返回 210

授权和转自方法

如果 0x1111 想要授权 0x2222 转一些代币给 0x22220x1111 需要执行:

1
tokenContract.approve(0x2222, 30)

授权数据结构现在包含如下信息:

1
tokenContract.allowed[0x1111][0x2222] = 30

如果 0x2222 想稍后从 0x1111 转给他自己一些代币,0x2222 要执行 transferFrom(...) 方法:

1
tokenContract.transferFrom(0x1111, 0x2222, 20)

余额数据结构将变为这样:

1
2
tokenContract.balances[0x1111] = 70
tokenContract.balances[0x2222] = 230

授权数据结构将包含如下信息:

1
tokenContract.allowed[0x1111][0x2222] = 10

0x2222 仍然可以从 0x1111 花费 10 个代币。

balanceOf(...) 方法将返回如下值:

1
2
tokenContract.balanceOf(0x1111) 将返回 70
tokenContract.balanceOf(0x2222) 将返回 230

Fixed Supply Token 合约例程

下面是 Fixed Supply Token 的合约,初始化给合约所有者 1,000,000 个单位的代币,并有最大 18 小数位限制:

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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
pragma solidity ^0.4.18;

// ----------------------------------------------------------------------------
// 'FIXED' '样例 Fixed Supply Token' 代币合约
//
// Symbol : FIXED
// Name : 样例 Fixed Supply Token
// Total supply: 1,000,000.000000000000000000
// Decimals : 18
//
// Enjoy.
//
// (c) BokkyPooBah / Bok Consulting Pty Ltd 2017. The MIT Licence.
// ----------------------------------------------------------------------------


// ----------------------------------------------------------------------------
// 安全的数学计算
// ----------------------------------------------------------------------------
library SafeMath {
function add(uint a, uint b) internal pure returns (uint c) {
c = a + b;
require(c >= a);
}
function sub(uint a, uint b) internal pure returns (uint c) {
require(b <= a);
c = a - b;
}
function mul(uint a, uint b) internal pure returns (uint c) {
c = a * b;
require(a == 0 || c / a == b);
}
function div(uint a, uint b) internal pure returns (uint c) {
require(b > 0);
c = a / b;
}
}


// ----------------------------------------------------------------------------
// ERC 代币标准 #20 接口
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
// ----------------------------------------------------------------------------
contract ERC20Interface {
function totalSupply() public constant returns (uint);
function balanceOf(address tokenOwner) public constant returns (uint balance);
function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);

event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}


// ----------------------------------------------------------------------------
// 接受授权并在一次调用中执行方法
//
// 借用自 MiniMeToken
// ----------------------------------------------------------------------------
contract ApproveAndCallFallBack {
function receiveApproval(address from, uint256 tokens, address token, bytes data) public;
}


// ----------------------------------------------------------------------------
// 所有者合约
// ----------------------------------------------------------------------------
contract Owned {
address public owner;
address public newOwner;

event OwnershipTransferred(address indexed _from, address indexed _to);

function Owned() public {
owner = msg.sender;
}

modifier onlyOwner {
require(msg.sender == owner);
_;
}

function transferOwnership(address _newOwner) public onlyOwner {
newOwner = _newOwner;
}
function acceptOwnership() public {
require(msg.sender == newOwner);
OwnershipTransferred(owner, newOwner);
owner = newOwner;
newOwner = address(0);
}
}


// ----------------------------------------------------------------------------
// ERC20 代币,包含附加的符号、名称、位数和初始化的代币
// ----------------------------------------------------------------------------
contract FixedSupplyToken is ERC20Interface, Owned {
using SafeMath for uint;

string public symbol;
string public name;
uint8 public decimals;
uint public _totalSupply;

mapping(address => uint) balances;
mapping(address => mapping(address => uint)) allowed;


// ------------------------------------------------------------------------
// 构造器
// ------------------------------------------------------------------------
function FixedSupplyToken() public {
symbol = "FIXED";
name = "Example Fixed Supply Token";
decimals = 18;
_totalSupply = 1000000 * 10**uint(decimals);
balances[owner] = _totalSupply;
Transfer(address(0), owner, _totalSupply);
}


// ------------------------------------------------------------------------
// 总额
// ------------------------------------------------------------------------
function totalSupply() public constant returns (uint) {
return _totalSupply - balances[address(0)];
}


// ------------------------------------------------------------------------
// 获取 `tokenOwner` 的余额
// ------------------------------------------------------------------------
function balanceOf(address tokenOwner) public constant returns (uint balance) {
return balances[tokenOwner];
}


// ------------------------------------------------------------------------
// 从代币所有者转给 `to`
// - 所有者账户必须有足够转账的余额
// - 允许转账金额为 0
// ------------------------------------------------------------------------
function transfer(address to, uint tokens) public returns (bool success) {
balances[msg.sender] = balances[msg.sender].sub(tokens);
balances[to] = balances[to].add(tokens);
Transfer(msg.sender, to, tokens);
return true;
}


// ------------------------------------------------------------------------
// 所有者授权 `spender` 可以从自己账户里 transferFrom(...) 转 `tokens` 个代币
//
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
// 注意这里没有检查授权的双花攻击,因为这应该由用户接口实现
// ------------------------------------------------------------------------
function approve(address spender, uint tokens) public returns (bool success) {
allowed[msg.sender][spender] = tokens;
Approval(msg.sender, spender, tokens);
return true;
}


// ------------------------------------------------------------------------
// 转 `tokens` 个代币从 `from` 到 `to`
//
// 调用该方法之前应该已经调用过 approve(...) 授权从 `from` 账户扣款并且
// - 来源用户必须有足够转账的余额
// - 消费者有足够的消耗余额
// - 允许值为 0 的交易
// ------------------------------------------------------------------------
function transferFrom(address from, address to, uint tokens) public returns (bool success) {
balances[from] = balances[from].sub(tokens);
allowed[from][msg.sender] = allowed[from][msg.sender].sub(tokens);
balances[to] = balances[to].add(tokens);
Transfer(from, to, tokens);
return true;
}


// ------------------------------------------------------------------------
// 返回所有者给目标用户授权转账的金额
// ------------------------------------------------------------------------
function allowance(address tokenOwner, address spender) public constant returns (uint remaining) {
return allowed[tokenOwner][spender];
}


// ------------------------------------------------------------------------
// 所有者可以授权给 `spender` 用 transferFrom(...) 从自己账上转 `tokens` 个代币。
// `spender` 合约方法将致谢 `receiveApproval(...)`
// ------------------------------------------------------------------------
function approveAndCall(address spender, uint tokens, bytes data) public returns (bool success) {
allowed[msg.sender][spender] = tokens;
Approval(msg.sender, spender, tokens);
ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);
return true;
}


// ------------------------------------------------------------------------
// 不支持 ETH
// ------------------------------------------------------------------------
function () public payable {
revert();
}


// ------------------------------------------------------------------------
// 所有者可以将意外发送的 ERC20 代币
// ------------------------------------------------------------------------
function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) {
return ERC20Interface(tokenAddress).transfer(owner, tokens);
}
}

参见 20 分钟在以太坊上发布你自己的代币 获取如何部署代币合约的步骤。

以太坊代币的更多信息


比特币Bitcoin源代码安装编译【转】

原文地址:http://www.cnblogs.com/wintersun/p/3813424.html

比特币 (货币符号: ฿;英文名:Bitcoin;英文缩写: BTC),是一种用于开源的P2P软件而产生的电子货币。

在这儿主要介绍Linux下的比特币Bitcoin安装,我们选择ubuntu 12.04的环境,安装相对容易得多。Windows下并不推荐,因为基于mingW配置相以繁琐。

同时也可以参考build官方文档。

先拉下源代码:

1
git clone https://github.com/bitcoin/bitcoin.git

安装Berkeley DB 4.8以上版本:

1
sudo apt-get install libdb5.1++-dev

然后进入到相关目录:

1
2
3
4
cd bitcoin

./autogen.sh
./configure

如果你遇到这样的提示:configure: error: Found Berkeley DB other than 4.8, required for portable wallets 那就可以这样:

1
./configure --with-incompatible-bdb

如查遇到到这样的提示:checking for boostlib >= 1.20.0… configure: We could not detect the boost libraries (version 1.20 or higher). 那这样:

1
sudo apt-get install libboost-all-dev

然后再次configure,如果你需要bitcoin-qt前端,那需要安装

1
sudo apt-get install libqt4-core libqt4-gui libqt4-dev

遇到configure: error: "libevent not found"解决方法:

1
2
3
4
5
6
git clone https://github.com/libevent/libevent.git
cd libevent
./autogen.sh
./configure
make
sudo make install

再次configure,这次可以了

1
make

开始编译,大约5分钟,然后安装编译好的二进制文件

1
make install

想运行前端那执行

1
bitcoin-qt

服务端是

1
bitcoind  -server –printtoconcole

接到下,是否挖矿就看您自己了。以当前时间为起点,连接testnet有9G的blockchain数据需要下载,livesite有35G的数据需要下载。 也可以从这里下载文件,以加快速度。后续会介绍关于比特币的更多内容。有兴趣可以阅读它的源代码。

资料LINK:

作者:Petter Liu 出处:http://www.cnblogs.com/wintersun/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 该文章也同时发布在我的独立博客中-Petter Liu Blog。

参考资料


Dagger Hashimoto

原文链接:https://github.com/ethereum/wiki/blob/master/Dagger-Hashimoto.md

介绍

Dagger Hashimoto 是以太坊 1.0 挖矿算法的一个规范。Dagger Hashimoto 目标是实现如下两个目标:

  1. 反电路特性: 为算法设计专用硬件的好处应当尽可能地小。理想情况下,相对于使用传统计算机的空闲 CPU 资源挖矿的用户,开发硬件电路的用户也只能有极小的加速效果而缺乏经济效益。
  2. 轻量客户端可验证性: 一个区块应当在轻量客户端上相对的容易进行验证。

另外,如果我们需要的话,也定义了如何满足第三个目标,但是相应地也会增加额外的复杂性和花销:

  1. 全量链存储: 矿主应存储整条区块链的状态。(由于以太坊状态树不规则的结构,我们期望有一些可行的剪枝,去最小化某些常用的合约操作)

Dagger Hashimoto 建立在之前两个关键的工作之上:

  • Hashimoto 是由 Thaddeus Dryja 设计的通过限制输入输出以达成反电路特性的算法,比如在挖矿进程中限制内存读取的因子。理论是,RAM 原则上是一种比计算更通用的成分,并且已经有数十亿美元的研究试图对不同的近乎随机访问模式的(由于“随机内存访问”)用例对它进行优化;因此,现有的 RAM 在评估算法时已较接近最优。Hashimoto 使用区块链作为来源数据,同时满足了上面的 (1) 和 (3)。
  • Dagger 是由 Vitalik Buterin 设计的用于在有向无环图(DAG)上实现计算上对内存难但验证对内存易的算法。核心理念是每个单独的 nonce 只需要一大棵数据树的一小部分,并且禁止矿主重新计算每个 nonce 对应的子树——因此需要存储整棵树——但是允许对单独的 nonce 进行验证。Dagger 意义在于指出了存在一种类似于 Scrypt 的对内存难算法,不仅对内存难,而且对当内存难度增加到真正安程度的验证也非常难。然而,Dagger 已经被 Sergio Lerner 证明容易受到共享内存硬件加速的影响,并转而支持其他途径的研究去了。

在 Dagger 和 Dagger Hashimoto 之间的处理不是我们本次关注的重点,包括:

  • “基于区块链的工作证明”——一种为区块链上运行的合约证明工作的方法。因为它有受到溢出攻击的漏洞所以被废弃了,攻击者可以创建分支并且用它们有的一种机密的快速“trapdoor”执行机制的合约填充来它们。
  • “随机电路”——一个由 Vlad Zamfir 开发的工作证明算法,通过对每 1000 个 nonce 生成一段新程序实现——本质上,每次选择一个新的散列算法是比重新配置 FPGA 更快。这种算法被搁置的原因在于很难看出人们可以用什么机制来产生随机的程序,这使得专门化的收益降低;然而,我们没有看到为什么这个概念不能实现的根本原因。

Dagger Hashimoto 和 Hashimoto 的区别在于,Dagger Hashimoto 没有使用区块链作为数据源,而是使用了一个自定义生成的 1GB 数据集,该数据集根据每 N 块的块数据进行更新。该数据集是使用 Dagger算法生成的,允许对每个 nonce 进行有效计算,用于轻客户端验证算法。Dagger Hashimoto 和 Dagger 的区别还在于,与原来的 Dagger 不同,用于查询块的数据集是半永久性的,只是偶尔更新(比如每周一次)。这意味着用于生成数据集的部分工作接近于零,因此 Sergio Lerner 关于共享内存速度的争论变得微不足道了。

DAG 生成

算法定义在下面的 Python 代码中。首先,我们给出 encode_int,用于将指定精度的非负整数转为字符串。它的逆算法也给出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
NUM_BITS = 512

def encode_int(x):
"将整数 x 编码为 64 字符的大端序格式"
o = ''
for _ in range(NUM_BITS / 8):
o = chr(x % 256) + o
x //= 256
return o

def decode_int(s):
"从大端序字符串解码为整数 x"
x = 0
for c in s:
x *= 256
x += ord(c)
return x

sha3 接收一个整数并输出一个整数,而 dbl_sha3 则运行了两遍 sha3;代码实现:

1
2
3
4
5
6
7
8
9
10
from pyethereum import utils
def sha3(x):
if isinstance(x, (int, long)):
x = encode_int(x)
return decode_int(utils.sha3(x))

def dbl_sha3(x):
if isinstance(x, (int, long)):
x = encode_int(x)
return decode_int(utils.sha3(utils.sha3(x)))

参数

算法需要的参数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SAFE_PRIME_512 = 2**512 - 38117     # 小于 2**512 的最大安全素数

params = {
"n": 4000055296 * 8 // NUM_BITS, # 数据集大小(4 GB);必须是 65536 的倍数
"n_inc": 65536, # 每 n 个周期增长的值;必须是 65536 的倍数
# 并且每年当 epochtime=20000 时增加 882 MB
"cache_size": 2500, # 轻客户端缓存大小(由客户端决定;非算法一部分)
"diff": 2**14, # 难度(适用于块验证)
"epochtime": 100000, # 块中每世代长度(数据集更新频率)
"k": 1, # 结点的父结点数量
"w": w, # 用于模幂运算散列
"accesses": 200, # Hashimoto 时访问数据集的次数
"P": SAFE_PRIME_512 # 用于散列和随机数生成的安全素数
}

P 是一个素数并满足 log₂(P) 略小于 512,以对应我们使用的 512 位表示的数字。注意实际上只需要存储 DAG 的后半部分,因为从 1 GB 开始的每年的内存增长就会是 441 MB。

Dagger 图构建

有向图的建立过程如下:

1
2
3
4
5
6
7
8
9
10
def produce_dag(params, seed, length):
P = params["P"]
picker = init = pow(sha3(seed), params["w"], P)
o = [init]
for i in range(1, length):
x = picker = (picker * init) % P
for _ in range(params["k"]):
x ^= o[x % i]
o.append(pow(x, params["w"], P))
return o

算法从某个随机结点开始计算 sha3(seed),在此之上依次添加其他结点。创建新结点时,会随机对小于 i 的来计算种子的模幂(用上面的 x % i),结点值还用于计算 x,然后用基于 XOR 的证明算法来生成 i 上的 x。该算法要求 DAG 是可以顺序访问的,并且只能在已知当前结点时才能访问下一个结点。最后,用模幂运算计算散列值。

算法依赖于附录描述的几个数论方面的结论。

轻量客户端验证

上述图构造的目的是通过计算仅有少量节点的子树并仅需要少量辅助存储器来重构图中的每个单独节点。注意当 k=1 时,子树仅是 DAG 首个元素后的一条链。

DAG 上的轻客户端计算方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def quick_calc(params, seed, p):
w, P = params["w"], params["P"]
cache = {}

def quick_calc_cached(p):
if p in cache:
pass
elif p == 0:
cache[p] = pow(sha3(seed), w, P)
else:
x = pow(sha3(seed), (p + 1) * w, P)
for _ in range(params["k"]):
x ^= quick_calc_cached(x % p)
cache[p] = pow(x, w, P)
return cache[p]

return quick_calc_cached(p)

本质上,这只是对上面算法的一种简写,其中删除了计算整个 DAG 值的循环,并利用记忆化递归实现结点查找。注意,k=1 时不需要缓存,进一步的优化会预先计算出 DAG 的前几千个值并缓存。请参阅附录中的实现。

DAG 的双缓冲区

In a full client, a double buffer of 2 DAGs produced by the above formula is used. The idea is that DAGs are produced every epochtime number of blocks according to the params above. The client does not use the latest DAG produced, but the previous one. The benefit of this is that it allows the DAGs to be replaced over time without needing to incorporate a step where miners must suddenly recompute all of the data. Otherwise, there is the potential for an abrupt temporary slowdown in chain processing at regular intervals and dramatically increasing centralization and thus 51% attack risks within those few minutes before all data is recomputed.

The algorithm used to generate the actual set of DAGs used to compute the work for a block is as follows:

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
def get_prevhash(n):
from pyethereum.blocks import GENESIS_PREVHASH
from pyethreum import chain_manager
if n <= 0:
return hash_to_int(GENESIS_PREVHASH)
else:
prevhash = chain_manager.index.get_block_by_number(n - 1)
return decode_int(prevhash)

def get_seedset(params, block):
seedset = {}
seedset["back_number"] = block.number - (block.number % params["epochtime"])
seedset["back_hash"] = get_prevhash(seedset["back_number"])
seedset["front_number"] = max(seedset["back_number"] - params["epochtime"], 0)
seedset["front_hash"] = get_prevhash(seedset["front_number"])
return seedset

def get_dagsize(params, block):
return params["n"] + (block.number // params["epochtime"]) * params["n_inc"]

def get_daggerset(params, block):
dagsz = get_dagsize(params, block)
seedset = get_seedset(params, block)
if seedset["front_hash"] <= 0:
# No back buffer is possible, just make front buffer
return {"front": {"dag": produce_dag(params, seedset["front_hash"], dagsz),
"block_number": 0}}
else:
return {"front": {"dag": produce_dag(params, seedset["front_hash"], dagsz),
"block_number": seedset["front_number"]},
"back": {"dag": produce_dag(params, seedset["back_hash"], dagsz),
"block_number": seedset["back_number"]}}

Hashimoto

The idea behind the original Hashimoto is to use the blockchain as a dataset, performing a computation which selects N indices from the blockchain, gathers the transactions at those indices, performs an XOR of this data, and returns the hash of the result. Thaddeus Dryja’s original algorithm, translated to Python for consistency, is as follows:

1
2
3
4
5
6
7
8
def orig_hashimoto(prev_hash, merkle_root, list_of_transactions, nonce):
hash_output_A = sha256(prev_hash + merkle_root + nonce)
txid_mix = 0
for i in range(64):
shifted_A = hash_output_A >> i
transaction = shifted_A % len(list_of_transactions)
txid_mix ^= list_of_transactions[transaction] << i
return txid_max ^ (nonce << 192)

Unfortunately, while Hashimoto is considered RAM hard, it relies on 256-bit arithmetic, which has considerable computational overhead. To address this issue, dagger hashimoto only uses the least significant 64 bits when indexing its dataset.

1
2
3
4
5
6
def hashimoto(dag, dagsize, params, header, nonce):
m = dagsize / 2
mix = sha3(encode_int(nonce) + header)
for _ in range(params["accesses"]):
mix ^= dag[m + (mix % 2**64) % m]
return dbl_sha3(mix)

The use of double sha3 allows for a form of zero-data, near-instant pre-verification, verifying only that a correct intermediate value was provided. This outer layer of PoW is highly ASIC-friendly and fairly weak, but exists to make DDoS even more difficult since that small amount of work must be done in order to produce a block that will not be rejected immediately. Here is the light-client version:

1
2
3
4
5
6
def quick_hashimoto(seed, dagsize, params, header, nonce):
m = dagsize // 2
mix = sha3(nonce + header)
for _ in range(params["accesses"]):
mix ^= quick_calc(params, seed, m + (mix % 2**64) % m)
return dbl_sha3(mix)

挖矿和验证

Now, let us put it all together into the mining algo:

1
2
3
4
5
6
7
8
9
10
11
12
def mine(daggerset, params, block):
from random import randint
nonce = randint(0, 2**64)
while 1:
result = hashimoto(daggerset, get_dagsize(params, block),
params, decode_int(block.prevhash), nonce)
if result * params["diff"] < 2**256:
break
nonce += 1
if nonce >= 2**64:
nonce = 0
return nonce

Here is the verification algorithm:

1
2
3
4
def verify(daggerset, params, block, nonce):
result = hashimoto(daggerset, get_dagsize(params, block),
params, decode_int(block.prevhash), nonce)
return result * params["diff"] < 2**256

Light-client friendly verification:

1
2
3
4
5
def light_verify(params, header, nonce):
seedset = get_seedset(params, block)
result = quick_hashimoto(seedset["front_hash"], get_dagsize(params, block),
params, decode_int(block.prevhash), nonce)
return result * params["diff"] < 2**256

Also, note that Dagger Hashimoto imposes additional requirements on the block header:

  • For two-layer verification to work, a block header must have both the nonce and the middle value pre-sha3
  • Somewhere, a block header must store the sha3 of the current seedset

附录

As noted above, the RNG used for DAG generation relies on some results from number theory. First, we provide assurance that the Lehmer RNG that is the basis for the picker variable has a wide period. Second, we show that pow(x,3,P) will not map x to 1 or P-1 provided x ∈ [2,P-2] to start. Finally, we show that pow(x,3,P) has a low collision rate when treated as a hashing function.

Lehmer 随机数生成器

While the produce_dag function does not need to produce unbiased random numbers, a potential threat is that seed**i % P only takes on a handful of values. This could provide an advantage to miners recognizing the pattern over those that do not.

To avoid this, a result from number theory is appealed to. A Safe Prime is defined to be a prime P such that (P-1)/2 is also prime. The order of a member x of the multiplicative group ℤ/nℤ is defined to be the minimal m such that

xᵐ mod P ≡ 1
Given these definitions, we have:

Observation 1. Let x be a member of the multiplicative group ℤ/Pℤ for a safe prime P. If x mod P ≠ 1 mod P and x mod P ≠ P-1 mod P, then the order of x is either P-1 or (P-1)/2.

Proof. Since P is a safe prime, then by [Lagrange’s Theorem][Lagrange] we have that the order of x is either 1, 2, (P-1)/2, or P-1.

The order of x cannot be 1, since by Fermat’s Little Theorem we have:

xP-1 mod P ≡ 1
Hence x must be a multiplicative identity of ℤ/nℤ, which is unique. Since we assumed that x ≠ 1 by assumption, this is not possible. The order of x cannot be 2 unless x = P-1, since this would violate that P is prime.
From the above proposition, we can recognize that iterating (picker * init) % P will have a cycle length of at least (P-1)/2. This is because we selected P to be a safe prime approximately equal to be a higher power of two, and init is in the interval [2,2**256+1]. Given the magnitude fo P, we should never expect a cycle from modular exponentiation. When we are assigning the first cell in the DAG (the variable labeled init), we compute pow(sha3(seed) + 2, 3, P). At first glance, this does not guarantee that the result is neither 1 nor P-1. However, since P-1 is a safe prime, we have the following additional assuance, which is a corollary of Observation 1: > Observation 2. Let x be a member of the multiplicative group ℤ/Pℤ for a safe prime P, and let w be a natural number. If x mod P ≠ 1 mod P and x mod P ≠ P-1 mod P, as well as w mod P ≠ P-1 mod P and w mod P ≠ 0 mod P, then xʷ mod P ≠ 1 mod P and xʷ mod P ≠ P-1 mod P [Lagrange]: https://en.wikipedia.org/wiki/Lagrange%27s_theorem_(group_theory) ## 以模幂运算作为散列函数 For certain values of P and w, the function pow(x, w, P) may have many collisions. For instance, pow(x,9,19) only takes on values {1,18}. Given that P is prime, then an appropriate w for a modular exponentation hashing function can be chosen using the following result: > Observation 3. Let P be a prime; w and P-1 are relatively prime if and only if for all a and b in ℤ/Pℤ:
aʷ mod P ≡ bʷ mod P if and only if a mod P ≡ b mod P

Thus, given that P is prime and w is relatively prime to P-1, we have that |{pow(x, w, P) : x ∈ ℤ}| = P, implying that the hashing function has the minimal collision rate possible.

In the special case that P is a safe prime as we have selected, then P-1 only has factors 1, 2, (P-1)/2 and P-1. Since P > 7, we know that 3 is relatively prime to P-1, hence w=3 satisfies the above proposition.

更有效的基于缓存的验证算法

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
def quick_calc(params, seed, p):
cache = produce_dag(params, seed, params["cache_size"])
return quick_calc_cached(cache, params, p)

def quick_calc_cached(cache, params, p):
P = params["P"]
if p < len(cache):
return cache[p]
else:
x = pow(cache[0], p + 1, P)
for _ in range(params["k"]):
x ^= quick_calc_cached(cache, params, x % p)
return pow(x, params["w"], P)

def quick_hashimoto(seed, dagsize, params, header, nonce):
cache = produce_dag(params, seed, params["cache_size"])
return quick_hashimoto_cached(cache, dagsize, params, header, nonce)

def quick_hashimoto_cached(cache, dagsize, params, header, nonce):
m = dagsize // 2
mask = 2**64 - 1
mix = sha3(encode_int(nonce) + header)
for _ in range(params["accesses"]):
mix ^= quick_calc_cached(cache, params, m + (mix & mask) % m)
return dbl_sha3(mix)

感谢下面的反馈:

  • Tim Hughes
  • Matthew Wampler-Doty
  • Thaddeus Dryja

Ethash 算法

原文链接:https://github.com/ethereum/wiki/wiki/Ethash

本规范版本 REVISION 23。当你实质性地(即有影响)更新了算法时,请更新本句中的修订号。同样,具体的实现中也请包含相应的修订版本号。

Ethash 基于以太坊 1.0 的 PoW 算法。它是 Dagger-Hashimoto 的最后一个版本,虽然由于两种算法在最后一个月的研究和开发后产生了巨大变化,它已经不应该再叫这个名字了。Dagger-Hashimoto 的算法可以参见这里

算法基于如下流程:

  1. 存在一个种子,可以通过扫描每个区块头部直到该点计算出来。
  2. 从种子中可以算出来一个 16 MB 伪随机缓存。轻量客户端存储该缓存。
  3. 从缓存里可以生成一个 1 GB 数据集,数据集中的每个属性都取决于缓存中的一小部分。全量客户端和矿工存储该数据集。数据集随时间线性增长。
  4. 采矿是收集数据集的随机切片并对其进行散列。验证则可以使用缓存去重新生成数据集中的特别片段,这样只需要使用较少的内存就可以完成,所以你只需要保存缓存。

大型数据集每 30000 个区块更新一次,所以大部分矿工都是去读数据集而不是去修改它。

参见 https://github.com/ethereum/wiki/wiki/Ethash-Design-Rationale 了解设计该算法的基本原则。

定义

我们采用如下定义:

1
2
3
4
5
6
7
8
9
10
11
12
WORD_BYTES = 4                    # 字长
DATASET_BYTES_INIT = 2**30 # 创世数据集大小
DATASET_BYTES_GROWTH = 2**23 # 每次数据集扩展大小
CACHE_BYTES_INIT = 2**24 # 创世缓存大小
CACHE_BYTES_GROWTH = 2**17 # 每次缓存扩展大小
CACHE_MULTIPLIER=1024 # DAG 相对于缓存的大小
EPOCH_LENGTH = 30000 # 时代跨度
MIX_BYTES = 128 # 混淆宽度
HASH_BYTES = 64 # 散列长度
DATASET_PARENTS = 256 # 数据集元素的父亲数
CACHE_ROUNDS = 3 # 产生缓存的轮数
ACCESSES = 64 # 在松本循环中的访问次数
关于本规范中 “SHA3” 的相关解释

以太坊的开发符合 SHA3 开发的标准,标准处理在最终散列算法的填充中作了一定改动,所以以太坊的 sha3_256 和 sha3_512 并不是标准的 sha3 散列算法,在其他场合里经常被称为 “Keccak-256” 和 “Keccak-512”。参见这里这里这里的讨论。

请记住这一点,下面的算法描述中也提到了 sha3 的散列算法。

参数

Ethash 缓存和数据集的参数取决于区块号。缓存大小和数据集大小都是线性增长的,但我们总是采用低于线性增长的大素数,以降低过于规律性导致散列不均匀的风险。

1
2
3
4
5
6
7
8
9
10
11
12
13
def get_cache_size(block_number):
sz = CACHE_BYTES_INIT + CACHE_BYTES_GROWTH * (block_number // EPOCH_LENGTH)
sz -= HASH_BYTES
while not isprime(sz / HASH_BYTES):
sz -= 2 * HASH_BYTES
return sz

def get_full_size(block_number):
sz = DATASET_BYTES_INIT + DATASET_BYTES_GROWTH * (block_number // EPOCH_LENGTH)
sz -= MIX_BYTES
while not isprime(sz / MIX_BYTES):
sz -= 2 * MIX_BYTES
return sz

附录提供了数据集和缓存大小值表。

缓存生成

现在,我们定义产生缓存的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def mkcache(cache_size, seed):
n = cache_size // HASH_BYTES

# 依次产生初始数据集
o = [sha3_512(seed)]
for i in range(1, n):
o.append(sha3_512(o[-1]))

# randmemohash 向下取整
for _ in range(CACHE_ROUNDS):
for i in range(n):
v = o[i][0] % n
o[i] = sha3_512(map(xor, o[(i-1+n) % n], o[v]))

return o

缓存产生过程会填满 32 MB 的内存,然后跑两边 Sergio Demian Lerner 的 RandMemoHash 算法(见严格内存硬散列函数 (2014))。输出是 524288 个 64 位字节值。

数据聚合函数

我们使用 FNV 散列 算法来处理某些不适用 XOR 的场景。注意我们乘的素数是 32 位的,FNV-1 则是每轮一个字节(8位)。

1
2
3
4
FNV_PRIME = 0x01000193

def fnv(v1, v2):
return ((v1 * FNV_PRIME) ^ v2) % 2**32

请注意,因为黄皮书定义了 fnv 就是 v1*(FNV_PRIME ^ v2),所以当前实现将一直使用上述定义。

全量数据集计算

1 GB 的全量数据集中每个 64 字节的元素都是如下计算的:

1
2
3
4
5
6
7
8
9
10
11
12
def calc_dataset_item(cache, i):
n = len(cache)
r = HASH_BYTES // WORD_BYTES
# 初始化混淆值
mix = copy.copy(cache[i % n])
mix[0] ^= i
mix = sha3_512(mix)
# 把基于 i 的随机缓存节点应用 fnv 函数
for j in range(DATASET_PARENTS):
cache_index = fnv(i ^ j, mix[j % r])
mix = map(fnv, mix, cache[cache_index % n])
return sha3_512(mix)

实际上,我们从缓存里选择了 256 个伪随机结点,散列后计算数据集结点。整个数据集是这样生成的:

1
2
def calc_dataset(full_size, cache):
return [calc_dataset_item(cache, i) for i in range(full_size // HASH_BYTES)]

主循环

现在,我们定义主的“松本”式循环。循环从全量数据集中收集数据,以产生特定头部和一次性随机数的最终值。下面代码中的 headerRLP 用 SHA3-256 _散列_ 算出的截断区块头,不包括 mixHashnoncenonce 是大端序的 8 字节 64 位无符号整数,所以 nonce[::-1] 就是小端序的表示了:

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
def hashimoto(header, nonce, full_size, dataset_lookup):
n = full_size / HASH_BYTES
w = MIX_BYTES // WORD_BYTES
mixhashes = MIX_BYTES / HASH_BYTES
# 把 header+nonce 转为 64 字节种子
s = sha3_512(header + nonce[::-1])
# 用一堆 s 填充 mix
mix = []
for _ in range(MIX_BYTES / HASH_BYTES):
mix.extend(s)
# 随机数据集结点的 mix
for i in range(ACCESSES):
p = fnv(i ^ s[0], mix[i % w]) % (n // mixhashes) * mixhashes
newdata = []
for j in range(MIX_BYTES / HASH_BYTES):
newdata.extend(dataset_lookup(p + j))
mix = map(fnv, mix, newdata)
# 压缩 mix
cmix = []
for i in range(0, len(mix), 4):
cmix.append(fnv(fnv(fnv(mix[i], mix[i+1]), mix[i+2]), mix[i+3]))
return {
"mix digest": serialize_hash(cmix),
"result": serialize_hash(sha3_256(s+cmix))
}

def hashimoto_light(full_size, cache, header, nonce):
return hashimoto(header, nonce, full_size, lambda x: calc_dataset_item(cache, x))

def hashimoto_full(full_size, dataset, header, nonce):
return hashimoto(header, nonce, full_size, lambda x: dataset[x])

实际上,我们维护一个 128 字节宽的 mix,并反复依次从全量数据集中获取 128 字节,用 fnv 函数来合并 mix。128 字节的顺序访问,每轮都从内存里获取一个完整的页,从而最大程度地减少集成电路的缓存失效。

如果算法输入低于预期目标,则 nonce 有效。注意最后 sha3_256 的扩展应用保证了存在一个中间值,用以证明最小工作量。这个快速的外部 PoW 验证可以用于防止 DDOS 的目的。它也提供统计功能,结果是一个无偏的 256 位数字。

挖矿

挖矿算法如下定义:

1
2
3
4
5
6
7
def mine(full_size, dataset, header, difficulty):
target = zpad(encode_int(2**256 // difficulty), 64)[::-1]
from random import randint
nonce = randint(0, 2**64)
while hashimoto_full(full_size, dataset, header, nonce) > target:
nonce = (nonce + 1) % 2**64
return nonce

定义种子散列

为了计算种子散列,需要对给定的区块进行挖掘,算法如下:

1
2
3
4
5
def get_seedhash(block):
s = '\x00' * 32
for i in range(block.number // EPOCH_LENGTH):
s = serialize_hash(sha3_256(s))
return s

注意,为了顺利挖掘和验证,我们建议在另一个线程里预先计算好种子散列和数据集分配表。

附录

如果你有兴趣在 Python 上实现请把下面的代码加在前面:

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
import sha3, copy

# 假设为小端序(Intel 体系)
def decode_int(s):
return int(s[::-1].encode('hex'), 16) if s else 0

def encode_int(s):
a = "%x" % s
return '' if s == 0 else ('0' * (len(a) % 2) + a).decode('hex')[::-1]

def zpad(s, length):
return s + '\x00' * max(0, length - len(s))

def serialize_hash(h):
return ''.join([zpad(encode_int(x), 4) for x in h])

def deserialize_hash(h):
return [decode_int(h[i:i+WORD_BYTES]) for i in range(0, len(h), WORD_BYTES)]

def hash_words(h, sz, x):
if isinstance(x, list):
x = serialize_hash(x)
y = h(x)
return deserialize_hash(y)

def serialize_cache(ds):
return ''.join([serialize_hash(h) for h in ds])

serialize_dataset = serialize_cache

# sha3 散列函数,输出 64 字节
def sha3_512(x):
return hash_words(lambda v: sha3.sha3_512(v).digest(), 64, x)

def sha3_256(x):
return hash_words(lambda v: sha3.sha3_256(v).digest(), 32, x)

def xor(a, b):
return a ^ b

def isprime(x):
for i in range(2, int(x**0.5)):
if x % i == 0:
return False
return True

数据大小

下面的表提供了约 2048 个数据集大小和缓存大小的时代值,我们可以用 Mathematica 生成:

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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
def get_datasize(block_number):
return data_sizes[block_number // EPOCH_LENGTH]

def get_cachesize(block_number):
return cache_sizes[block_number // EPOCH_LENGTH]

data_sizes = [
1073739904, 1082130304, 1090514816, 1098906752, 1107293056,
1115684224, 1124070016, 1132461952, 1140849536, 1149232768,
1157627776, 1166013824, 1174404736, 1182786944, 1191180416,
1199568512, 1207958912, 1216345216, 1224732032, 1233124736,
1241513344, 1249902464, 1258290304, 1266673792, 1275067264,
1283453312, 1291844992, 1300234112, 1308619904, 1317010048,
1325397376, 1333787776, 1342176128, 1350561664, 1358954368,
1367339392, 1375731584, 1384118144, 1392507008, 1400897408,
1409284736, 1417673344, 1426062464, 1434451072, 1442839168,
1451229056, 1459615616, 1468006016, 1476394112, 1484782976,
1493171584, 1501559168, 1509948032, 1518337664, 1526726528,
1535114624, 1543503488, 1551892096, 1560278656, 1568669056,
1577056384, 1585446272, 1593831296, 1602219392, 1610610304,
1619000192, 1627386752, 1635773824, 1644164224, 1652555648,
1660943488, 1669332608, 1677721216, 1686109312, 1694497664,
1702886272, 1711274624, 1719661184, 1728047744, 1736434816,
1744829056, 1753218944, 1761606272, 1769995904, 1778382464,
1786772864, 1795157888, 1803550592, 1811937664, 1820327552,
1828711552, 1837102976, 1845488768, 1853879936, 1862269312,
1870656896, 1879048064, 1887431552, 1895825024, 1904212096,
1912601216, 1920988544, 1929379456, 1937765504, 1946156672,
1954543232, 1962932096, 1971321728, 1979707264, 1988093056,
1996487552, 2004874624, 2013262208, 2021653888, 2030039936,
2038430848, 2046819968, 2055208576, 2063596672, 2071981952,
2080373632, 2088762752, 2097149056, 2105539712, 2113928576,
2122315136, 2130700672, 2139092608, 2147483264, 2155872128,
2164257664, 2172642176, 2181035392, 2189426048, 2197814912,
2206203008, 2214587264, 2222979712, 2231367808, 2239758208,
2248145024, 2256527744, 2264922752, 2273312128, 2281701248,
2290086272, 2298476672, 2306867072, 2315251072, 2323639168,
2332032128, 2340420224, 2348808064, 2357196416, 2365580416,
2373966976, 2382363008, 2390748544, 2399139968, 2407530368,
2415918976, 2424307328, 2432695424, 2441084288, 2449472384,
2457861248, 2466247808, 2474637184, 2483026816, 2491414144,
2499803776, 2508191872, 2516582272, 2524970368, 2533359232,
2541743488, 2550134144, 2558525056, 2566913408, 2575301504,
2583686528, 2592073856, 2600467328, 2608856192, 2617240448,
2625631616, 2634022016, 2642407552, 2650796416, 2659188352,
2667574912, 2675965312, 2684352896, 2692738688, 2701130624,
2709518464, 2717907328, 2726293376, 2734685056, 2743073152,
2751462016, 2759851648, 2768232832, 2776625536, 2785017728,
2793401984, 2801794432, 2810182016, 2818571648, 2826959488,
2835349376, 2843734144, 2852121472, 2860514432, 2868900992,
2877286784, 2885676928, 2894069632, 2902451584, 2910843008,
2919234688, 2927622784, 2936011648, 2944400768, 2952789376,
2961177728, 2969565568, 2977951616, 2986338944, 2994731392,
3003120256, 3011508352, 3019895936, 3028287104, 3036675968,
3045063808, 3053452928, 3061837696, 3070228352, 3078615424,
3087003776, 3095394944, 3103782272, 3112173184, 3120562048,
3128944768, 3137339264, 3145725056, 3154109312, 3162505088,
3170893184, 3179280256, 3187669376, 3196056704, 3204445568,
3212836736, 3221224064, 3229612928, 3238002304, 3246391168,
3254778496, 3263165824, 3271556224, 3279944576, 3288332416,
3296719232, 3305110912, 3313500032, 3321887104, 3330273152,
3338658944, 3347053184, 3355440512, 3363827072, 3372220288,
3380608384, 3388997504, 3397384576, 3405774208, 3414163072,
3422551936, 3430937984, 3439328384, 3447714176, 3456104576,
3464493952, 3472883584, 3481268864, 3489655168, 3498048896,
3506434432, 3514826368, 3523213952, 3531603584, 3539987072,
3548380288, 3556763264, 3565157248, 3573545344, 3581934464,
3590324096, 3598712704, 3607098752, 3615488384, 3623877248,
3632265856, 3640646528, 3649043584, 3657430144, 3665821568,
3674207872, 3682597504, 3690984832, 3699367808, 3707764352,
3716152448, 3724541056, 3732925568, 3741318016, 3749706368,
3758091136, 3766481536, 3774872704, 3783260032, 3791650432,
3800036224, 3808427648, 3816815488, 3825204608, 3833592704,
3841981568, 3850370432, 3858755968, 3867147904, 3875536256,
3883920512, 3892313728, 3900702592, 3909087872, 3917478784,
3925868416, 3934256512, 3942645376, 3951032192, 3959422336,
3967809152, 3976200064, 3984588416, 3992974976, 4001363584,
4009751168, 4018141312, 4026530432, 4034911616, 4043308928,
4051695488, 4060084352, 4068472448, 4076862848, 4085249408,
4093640576, 4102028416, 4110413696, 4118805632, 4127194496,
4135583104, 4143971968, 4152360832, 4160746112, 4169135744,
4177525888, 4185912704, 4194303616, 4202691968, 4211076736,
4219463552, 4227855488, 4236246656, 4244633728, 4253022848,
4261412224, 4269799808, 4278184832, 4286578048, 4294962304,
4303349632, 4311743104, 4320130432, 4328521088, 4336909184,
4345295488, 4353687424, 4362073472, 4370458496, 4378852736,
4387238528, 4395630208, 4404019072, 4412407424, 4420790656,
4429182848, 4437571456, 4445962112, 4454344064, 4462738048,
4471119232, 4479516544, 4487904128, 4496289664, 4504682368,
4513068416, 4521459584, 4529846144, 4538232704, 4546619776,
4555010176, 4563402112, 4571790208, 4580174464, 4588567936,
4596957056, 4605344896, 4613734016, 4622119808, 4630511488,
4638898816, 4647287936, 4655675264, 4664065664, 4672451968,
4680842624, 4689231488, 4697620352, 4706007424, 4714397056,
4722786176, 4731173248, 4739562368, 4747951744, 4756340608,
4764727936, 4773114496, 4781504384, 4789894784, 4798283648,
4806667648, 4815059584, 4823449472, 4831835776, 4840226176,
4848612224, 4857003392, 4865391488, 4873780096, 4882169728,
4890557312, 4898946944, 4907333248, 4915722368, 4924110976,
4932499328, 4940889728, 4949276032, 4957666432, 4966054784,
4974438016, 4982831488, 4991221376, 4999607168, 5007998848,
5016386432, 5024763776, 5033164672, 5041544576, 5049941888,
5058329728, 5066717056, 5075107456, 5083494272, 5091883904,
5100273536, 5108662144, 5117048192, 5125436032, 5133827456,
5142215296, 5150605184, 5158993024, 5167382144, 5175769472,
5184157568, 5192543872, 5200936064, 5209324928, 5217711232,
5226102656, 5234490496, 5242877312, 5251263872, 5259654016,
5268040832, 5276434304, 5284819328, 5293209728, 5301598592,
5309986688, 5318374784, 5326764416, 5335151488, 5343542144,
5351929472, 5360319872, 5368706944, 5377096576, 5385484928,
5393871232, 5402263424, 5410650496, 5419040384, 5427426944,
5435816576, 5444205952, 5452594816, 5460981376, 5469367936,
5477760896, 5486148736, 5494536832, 5502925952, 5511315328,
5519703424, 5528089984, 5536481152, 5544869504, 5553256064,
5561645696, 5570032768, 5578423936, 5586811264, 5595193216,
5603585408, 5611972736, 5620366208, 5628750464, 5637143936,
5645528192, 5653921408, 5662310272, 5670694784, 5679082624,
5687474048, 5695864448, 5704251008, 5712641408, 5721030272,
5729416832, 5737806208, 5746194304, 5754583936, 5762969984,
5771358592, 5779748224, 5788137856, 5796527488, 5804911232,
5813300608, 5821692544, 5830082176, 5838468992, 5846855552,
5855247488, 5863636096, 5872024448, 5880411008, 5888799872,
5897186432, 5905576832, 5913966976, 5922352768, 5930744704,
5939132288, 5947522432, 5955911296, 5964299392, 5972688256,
5981074304, 5989465472, 5997851008, 6006241408, 6014627968,
6023015552, 6031408256, 6039796096, 6048185216, 6056574848,
6064963456, 6073351808, 6081736064, 6090128768, 6098517632,
6106906496, 6115289216, 6123680896, 6132070016, 6140459648,
6148849024, 6157237376, 6165624704, 6174009728, 6182403712,
6190792064, 6199176064, 6207569792, 6215952256, 6224345216,
6232732544, 6241124224, 6249510272, 6257899136, 6266287744,
6274676864, 6283065728, 6291454336, 6299843456, 6308232064,
6316620928, 6325006208, 6333395584, 6341784704, 6350174848,
6358562176, 6366951296, 6375337856, 6383729536, 6392119168,
6400504192, 6408895616, 6417283456, 6425673344, 6434059136,
6442444672, 6450837376, 6459223424, 6467613056, 6476004224,
6484393088, 6492781952, 6501170048, 6509555072, 6517947008,
6526336384, 6534725504, 6543112832, 6551500672, 6559888768,
6568278656, 6576662912, 6585055616, 6593443456, 6601834112,
6610219648, 6618610304, 6626999168, 6635385472, 6643777408,
6652164224, 6660552832, 6668941952, 6677330048, 6685719424,
6694107776, 6702493568, 6710882176, 6719274112, 6727662976,
6736052096, 6744437632, 6752825984, 6761213824, 6769604224,
6777993856, 6786383488, 6794770816, 6803158144, 6811549312,
6819937664, 6828326528, 6836706176, 6845101696, 6853491328,
6861880448, 6870269312, 6878655104, 6887046272, 6895433344,
6903822208, 6912212864, 6920596864, 6928988288, 6937377152,
6945764992, 6954149248, 6962544256, 6970928768, 6979317376,
6987709312, 6996093824, 7004487296, 7012875392, 7021258624,
7029652352, 7038038912, 7046427776, 7054818944, 7063207808,
7071595136, 7079980928, 7088372608, 7096759424, 7105149824,
7113536896, 7121928064, 7130315392, 7138699648, 7147092352,
7155479168, 7163865728, 7172249984, 7180648064, 7189036672,
7197424768, 7205810816, 7214196608, 7222589824, 7230975104,
7239367552, 7247755904, 7256145536, 7264533376, 7272921472,
7281308032, 7289694848, 7298088832, 7306471808, 7314864512,
7323253888, 7331643008, 7340029568, 7348419712, 7356808832,
7365196672, 7373585792, 7381973888, 7390362752, 7398750592,
7407138944, 7415528576, 7423915648, 7432302208, 7440690304,
7449080192, 7457472128, 7465860992, 7474249088, 7482635648,
7491023744, 7499412608, 7507803008, 7516192384, 7524579968,
7532967296, 7541358464, 7549745792, 7558134656, 7566524032,
7574912896, 7583300992, 7591690112, 7600075136, 7608466816,
7616854912, 7625244544, 7633629824, 7642020992, 7650410368,
7658794112, 7667187328, 7675574912, 7683961984, 7692349568,
7700739712, 7709130368, 7717519232, 7725905536, 7734295424,
7742683264, 7751069056, 7759457408, 7767849088, 7776238208,
7784626816, 7793014912, 7801405312, 7809792128, 7818179968,
7826571136, 7834957184, 7843347328, 7851732352, 7860124544,
7868512384, 7876902016, 7885287808, 7893679744, 7902067072,
7910455936, 7918844288, 7927230848, 7935622784, 7944009344,
7952400256, 7960786048, 7969176704, 7977565312, 7985953408,
7994339968, 8002730368, 8011119488, 8019508096, 8027896192,
8036285056, 8044674688, 8053062272, 8061448832, 8069838464,
8078227328, 8086616704, 8095006592, 8103393664, 8111783552,
8120171392, 8128560256, 8136949376, 8145336704, 8153726848,
8162114944, 8170503296, 8178891904, 8187280768, 8195669632,
8204058496, 8212444544, 8220834176, 8229222272, 8237612672,
8246000768, 8254389376, 8262775168, 8271167104, 8279553664,
8287944064, 8296333184, 8304715136, 8313108352, 8321497984,
8329885568, 8338274432, 8346663296, 8355052928, 8363441536,
8371828352, 8380217984, 8388606592, 8396996224, 8405384576,
8413772672, 8422161536, 8430549376, 8438939008, 8447326592,
8455715456, 8464104832, 8472492928, 8480882048, 8489270656,
8497659776, 8506045312, 8514434944, 8522823808, 8531208832,
8539602304, 8547990656, 8556378752, 8564768384, 8573154176,
8581542784, 8589933952, 8598322816, 8606705024, 8615099264,
8623487872, 8631876992, 8640264064, 8648653952, 8657040256,
8665430656, 8673820544, 8682209152, 8690592128, 8698977152,
8707374464, 8715763328, 8724151424, 8732540032, 8740928384,
8749315712, 8757704576, 8766089344, 8774480768, 8782871936,
8791260032, 8799645824, 8808034432, 8816426368, 8824812928,
8833199488, 8841591424, 8849976448, 8858366336, 8866757248,
8875147136, 8883532928, 8891923328, 8900306816, 8908700288,
8917088384, 8925478784, 8933867392, 8942250368, 8950644608,
8959032704, 8967420544, 8975809664, 8984197504, 8992584064,
9000976256, 9009362048, 9017752448, 9026141312, 9034530688,
9042917504, 9051307904, 9059694208, 9068084864, 9076471424,
9084861824, 9093250688, 9101638528, 9110027648, 9118416512,
9126803584, 9135188096, 9143581312, 9151969664, 9160356224,
9168747136, 9177134464, 9185525632, 9193910144, 9202302848,
9210690688, 9219079552, 9227465344, 9235854464, 9244244864,
9252633472, 9261021824, 9269411456, 9277799296, 9286188928,
9294574208, 9302965888, 9311351936, 9319740032, 9328131968,
9336516736, 9344907392, 9353296768, 9361685888, 9370074752,
9378463616, 9386849408, 9395239808, 9403629184, 9412016512,
9420405376, 9428795008, 9437181568, 9445570688, 9453960832,
9462346624, 9470738048, 9479121536, 9487515008, 9495903616,
9504289664, 9512678528, 9521067904, 9529456256, 9537843584,
9546233728, 9554621312, 9563011456, 9571398784, 9579788672,
9588178304, 9596567168, 9604954496, 9613343104, 9621732992,
9630121856, 9638508416, 9646898816, 9655283584, 9663675776,
9672061312, 9680449664, 9688840064, 9697230464, 9705617536,
9714003584, 9722393984, 9730772608, 9739172224, 9747561088,
9755945344, 9764338816, 9772726144, 9781116544, 9789503872,
9797892992, 9806282624, 9814670464, 9823056512, 9831439232,
9839833984, 9848224384, 9856613504, 9865000576, 9873391232,
9881772416, 9890162816, 9898556288, 9906940544, 9915333248,
9923721088, 9932108672, 9940496512, 9948888448, 9957276544,
9965666176, 9974048384, 9982441088, 9990830464, 9999219584,
10007602816, 10015996544, 10024385152, 10032774016, 10041163648,
10049548928, 10057940096, 10066329472, 10074717824, 10083105152,
10091495296, 10099878784, 10108272256, 10116660608, 10125049216,
10133437312, 10141825664, 10150213504, 10158601088, 10166991232,
10175378816, 10183766144, 10192157312, 10200545408, 10208935552,
10217322112, 10225712768, 10234099328, 10242489472, 10250876032,
10259264896, 10267656064, 10276042624, 10284429184, 10292820352,
10301209472, 10309598848, 10317987712, 10326375296, 10334763392,
10343153536, 10351541632, 10359930752, 10368318592, 10376707456,
10385096576, 10393484672, 10401867136, 10410262144, 10418647424,
10427039104, 10435425664, 10443810176, 10452203648, 10460589952,
10468982144, 10477369472, 10485759104, 10494147712, 10502533504,
10510923392, 10519313536, 10527702656, 10536091264, 10544478592,
10552867712, 10561255808, 10569642368, 10578032768, 10586423168,
10594805632, 10603200128, 10611588992, 10619976064, 10628361344,
10636754048, 10645143424, 10653531776, 10661920384, 10670307968,
10678696832, 10687086464, 10695475072, 10703863168, 10712246144,
10720639616, 10729026688, 10737414784, 10745806208, 10754190976,
10762581376, 10770971264, 10779356288, 10787747456, 10796135552,
10804525184, 10812915584, 10821301888, 10829692288, 10838078336,
10846469248, 10854858368, 10863247232, 10871631488, 10880023424,
10888412032, 10896799616, 10905188992, 10913574016, 10921964672,
10930352768, 10938742912, 10947132544, 10955518592, 10963909504,
10972298368, 10980687488, 10989074816, 10997462912, 11005851776,
11014241152, 11022627712, 11031017344, 11039403904, 11047793024,
11056184704, 11064570752, 11072960896, 11081343872, 11089737856,
11098128256, 11106514816, 11114904448, 11123293568, 11131680128,
11140065152, 11148458368, 11156845696, 11165236864, 11173624192,
11182013824, 11190402688, 11198790784, 11207179136, 11215568768,
11223957376, 11232345728, 11240734592, 11249122688, 11257511296,
11265899648, 11274285952, 11282675584, 11291065472, 11299452544,
11307842432, 11316231296, 11324616832, 11333009024, 11341395584,
11349782656, 11358172288, 11366560384, 11374950016, 11383339648,
11391721856, 11400117376, 11408504192, 11416893568, 11425283456,
11433671552, 11442061184, 11450444672, 11458837888, 11467226752,
11475611776, 11484003968, 11492392064, 11500780672, 11509169024,
11517550976, 11525944448, 11534335616, 11542724224, 11551111808,
11559500672, 11567890304, 11576277376, 11584667008, 11593056128,
11601443456, 11609830016, 11618221952, 11626607488, 11634995072,
11643387776, 11651775104, 11660161664, 11668552576, 11676940928,
11685330304, 11693718656, 11702106496, 11710496128, 11718882688,
11727273088, 11735660416, 11744050048, 11752437376, 11760824704,
11769216128, 11777604736, 11785991296, 11794381952, 11802770048,
11811157888, 11819548544, 11827932544, 11836324736, 11844713344,
11853100928, 11861486464, 11869879936, 11878268032, 11886656896,
11895044992, 11903433088, 11911822976, 11920210816, 11928600448,
11936987264, 11945375872, 11953761152, 11962151296, 11970543488,
11978928512, 11987320448, 11995708288, 12004095104, 12012486272,
12020875136, 12029255552, 12037652096, 12046039168, 12054429568,
12062813824, 12071206528, 12079594624, 12087983744, 12096371072,
12104759936, 12113147264, 12121534592, 12129924992, 12138314624,
12146703232, 12155091584, 12163481216, 12171864704, 12180255872,
12188643968, 12197034112, 12205424512, 12213811328, 12222199424,
12230590336, 12238977664, 12247365248, 12255755392, 12264143488,
12272531584, 12280920448, 12289309568, 12297694592, 12306086528,
12314475392, 12322865024, 12331253632, 12339640448, 12348029312,
12356418944, 12364805248, 12373196672, 12381580928, 12389969024,
12398357632, 12406750592, 12415138432, 12423527552, 12431916416,
12440304512, 12448692352, 12457081216, 12465467776, 12473859968,
12482245504, 12490636672, 12499025536, 12507411584, 12515801728,
12524190592, 12532577152, 12540966272, 12549354368, 12557743232,
12566129536, 12574523264, 12582911872, 12591299456, 12599688064,
12608074624, 12616463488, 12624845696, 12633239936, 12641631616,
12650019968, 12658407296, 12666795136, 12675183232, 12683574656,
12691960192, 12700350592, 12708740224, 12717128576, 12725515904,
12733906816, 12742295168, 12750680192, 12759071872, 12767460736,
12775848832, 12784236928, 12792626816, 12801014656, 12809404288,
12817789312, 12826181504, 12834568832, 12842954624, 12851345792,
12859732352, 12868122496, 12876512128, 12884901248, 12893289088,
12901672832, 12910067584, 12918455168, 12926842496, 12935232896,
12943620736, 12952009856, 12960396928, 12968786816, 12977176192,
12985563776, 12993951104, 13002341504, 13010730368, 13019115392,
13027506304, 13035895168, 13044272512, 13052673152, 13061062528,
13069446272, 13077838976, 13086227072, 13094613632, 13103000192,
13111393664, 13119782528, 13128157568, 13136559232, 13144945024,
13153329536, 13161724288, 13170111872, 13178502784, 13186884736,
13195279744, 13203667072, 13212057472, 13220445824, 13228832128,
13237221248, 13245610624, 13254000512, 13262388352, 13270777472,
13279166336, 13287553408, 13295943296, 13304331904, 13312719488,
13321108096, 13329494656, 13337885824, 13346274944, 13354663808,
13363051136, 13371439232, 13379825024, 13388210816, 13396605056,
13404995456, 13413380224, 13421771392, 13430159744, 13438546048,
13446937216, 13455326848, 13463708288, 13472103808, 13480492672,
13488875648, 13497269888, 13505657728, 13514045312, 13522435712,
13530824576, 13539210112, 13547599232, 13555989376, 13564379008,
13572766336, 13581154432, 13589544832, 13597932928, 13606320512,
13614710656, 13623097472, 13631477632, 13639874944, 13648264064,
13656652928, 13665041792, 13673430656, 13681818496, 13690207616,
13698595712, 13706982272, 13715373184, 13723762048, 13732150144,
13740536704, 13748926592, 13757316224, 13765700992, 13774090112,
13782477952, 13790869376, 13799259008, 13807647872, 13816036736,
13824425344, 13832814208, 13841202304, 13849591424, 13857978752,
13866368896, 13874754688, 13883145344, 13891533184, 13899919232,
13908311168, 13916692096, 13925085056, 13933473152, 13941866368,
13950253696, 13958643584, 13967032192, 13975417216, 13983807616,
13992197504, 14000582272, 14008973696, 14017363072, 14025752192,
14034137984, 14042528384, 14050918016, 14059301504, 14067691648,
14076083584, 14084470144, 14092852352, 14101249664, 14109635968,
14118024832, 14126407552, 14134804352, 14143188608, 14151577984,
14159968384, 14168357248, 14176741504, 14185127296, 14193521024,
14201911424, 14210301824, 14218685056, 14227067264, 14235467392,
14243855488, 14252243072, 14260630144, 14269021568, 14277409408,
14285799296, 14294187904, 14302571392, 14310961792, 14319353728,
14327738752, 14336130944, 14344518784, 14352906368, 14361296512,
14369685376, 14378071424, 14386462592, 14394848128, 14403230848,
14411627392, 14420013952, 14428402304, 14436793472, 14445181568,
14453569664, 14461959808, 14470347904, 14478737024, 14487122816,
14495511424, 14503901824, 14512291712, 14520677504, 14529064832,
14537456768, 14545845632, 14554234496, 14562618496, 14571011456,
14579398784, 14587789184, 14596172672, 14604564608, 14612953984,
14621341312, 14629724288, 14638120832, 14646503296, 14654897536,
14663284864, 14671675264, 14680061056, 14688447616, 14696835968,
14705228416, 14713616768, 14722003328, 14730392192, 14738784128,
14747172736, 14755561088, 14763947648, 14772336512, 14780725376,
14789110144, 14797499776, 14805892736, 14814276992, 14822670208,
14831056256, 14839444352, 14847836032, 14856222848, 14864612992,
14872997504, 14881388672, 14889775744, 14898165376, 14906553472,
14914944896, 14923329664, 14931721856, 14940109696, 14948497024,
14956887424, 14965276544, 14973663616, 14982053248, 14990439808,
14998830976, 15007216768, 15015605888, 15023995264, 15032385152,
15040768384, 15049154944, 15057549184, 15065939072, 15074328448,
15082715008, 15091104128, 15099493504, 15107879296, 15116269184,
15124659584, 15133042304, 15141431936, 15149824384, 15158214272,
15166602368, 15174991232, 15183378304, 15191760512, 15200154496,
15208542592, 15216931712, 15225323392, 15233708416, 15242098048,
15250489216, 15258875264, 15267265408, 15275654528, 15284043136,
15292431488, 15300819584, 15309208192, 15317596544, 15325986176,
15334374784, 15342763648, 15351151744, 15359540608, 15367929728,
15376318336, 15384706432, 15393092992, 15401481856, 15409869952,
15418258816, 15426649984, 15435037568, 15443425664, 15451815296,
15460203392, 15468589184, 15476979328, 15485369216, 15493755776,
15502146944, 15510534272, 15518924416, 15527311232, 15535699072,
15544089472, 15552478336, 15560866688, 15569254528, 15577642624,
15586031488, 15594419072, 15602809472, 15611199104, 15619586432,
15627975296, 15636364928, 15644753792, 15653141888, 15661529216,
15669918848, 15678305152, 15686696576, 15695083136, 15703474048,
15711861632, 15720251264, 15728636288, 15737027456, 15745417088,
15753804928, 15762194048, 15770582656, 15778971008, 15787358336,
15795747712, 15804132224, 15812523392, 15820909696, 15829300096,
15837691264, 15846071936, 15854466944, 15862855808, 15871244672,
15879634816, 15888020608, 15896409728, 15904799104, 15913185152,
15921577088, 15929966464, 15938354816, 15946743424, 15955129472,
15963519872, 15971907968, 15980296064, 15988684928, 15997073024,
16005460864, 16013851264, 16022241152, 16030629248, 16039012736,
16047406976, 16055794816, 16064181376, 16072571264, 16080957824,
16089346688, 16097737856, 16106125184, 16114514816, 16122904192,
16131292544, 16139678848, 16148066944, 16156453504, 16164839552,
16173236096, 16181623424, 16190012032, 16198401152, 16206790528,
16215177344, 16223567744, 16231956352, 16240344704, 16248731008,
16257117824, 16265504384, 16273898624, 16282281856, 16290668672,
16299064192, 16307449216, 16315842176, 16324230016, 16332613504,
16341006464, 16349394304, 16357783168, 16366172288, 16374561664,
16382951296, 16391337856, 16399726208, 16408116352, 16416505472,
16424892032, 16433282176, 16441668224, 16450058624, 16458448768,
16466836864, 16475224448, 16483613056, 16492001408, 16500391808,
16508779648, 16517166976, 16525555328, 16533944192, 16542330752,
16550719616, 16559110528, 16567497088, 16575888512, 16584274816,
16592665472, 16601051008, 16609442944, 16617832064, 16626218624,
16634607488, 16642996096, 16651385728, 16659773824, 16668163712,
16676552576, 16684938112, 16693328768, 16701718144, 16710095488,
16718492288, 16726883968, 16735272832, 16743661184, 16752049792,
16760436608, 16768827008, 16777214336, 16785599104, 16793992832,
16802381696, 16810768768, 16819151744, 16827542656, 16835934848,
16844323712, 16852711552, 16861101952, 16869489536, 16877876864,
16886265728, 16894653056, 16903044736, 16911431296, 16919821696,
16928207488, 16936592768, 16944987776, 16953375616, 16961763968,
16970152832, 16978540928, 16986929536, 16995319168, 17003704448,
17012096896, 17020481152, 17028870784, 17037262208, 17045649536,
17054039936, 17062426496, 17070814336, 17079205504, 17087592064,
17095978112, 17104369024, 17112759424, 17121147776, 17129536384,
17137926016, 17146314368, 17154700928, 17163089792, 17171480192,
17179864192, 17188256896, 17196644992, 17205033856, 17213423488,
17221811072, 17230198912, 17238588032, 17246976896, 17255360384,
17263754624, 17272143232, 17280530048, 17288918912, 17297309312,
17305696384, 17314085504, 17322475136, 17330863744, 17339252096,
17347640192, 17356026496, 17364413824, 17372796544, 17381190016,
17389583488, 17397972608, 17406360704, 17414748544, 17423135872,
17431527296, 17439915904, 17448303232, 17456691584, 17465081728,
17473468288, 17481857408, 17490247552, 17498635904, 17507022464,
17515409024, 17523801728, 17532189824, 17540577664, 17548966016,
17557353344, 17565741184, 17574131584, 17582519168, 17590907008,
17599296128, 17607687808, 17616076672, 17624455808, 17632852352,
17641238656, 17649630848, 17658018944, 17666403968, 17674794112,
17683178368, 17691573376, 17699962496, 17708350592, 17716739968,
17725126528, 17733517184, 17741898112, 17750293888, 17758673024,
17767070336, 17775458432, 17783848832, 17792236928, 17800625536,
17809012352, 17817402752, 17825785984, 17834178944, 17842563968,
17850955648, 17859344512, 17867732864, 17876119424, 17884511872,
17892900224, 17901287296, 17909677696, 17918058112, 17926451072,
17934843776, 17943230848, 17951609216, 17960008576, 17968397696,
17976784256, 17985175424, 17993564032, 18001952128, 18010339712,
18018728576, 18027116672, 18035503232, 18043894144, 18052283264,
18060672128, 18069056384, 18077449856, 18085837184, 18094225792,
18102613376, 18111004544, 18119388544, 18127781248, 18136170368,
18144558976, 18152947328, 18161336192, 18169724288, 18178108544,
18186498944, 18194886784, 18203275648, 18211666048, 18220048768,
18228444544, 18236833408, 18245220736]

cache_sizes = [
16776896, 16907456, 17039296, 17170112, 17301056, 17432512, 17563072,
17693888, 17824192, 17955904, 18087488, 18218176, 18349504, 18481088,
18611392, 18742336, 18874304, 19004224, 19135936, 19267264, 19398208,
19529408, 19660096, 19791424, 19922752, 20053952, 20184896, 20315968,
20446912, 20576576, 20709184, 20840384, 20971072, 21102272, 21233216,
21364544, 21494848, 21626816, 21757376, 21887552, 22019392, 22151104,
22281536, 22412224, 22543936, 22675264, 22806464, 22935872, 23068096,
23198272, 23330752, 23459008, 23592512, 23723968, 23854912, 23986112,
24116672, 24247616, 24378688, 24509504, 24640832, 24772544, 24903488,
25034432, 25165376, 25296704, 25427392, 25558592, 25690048, 25820096,
25951936, 26081728, 26214208, 26345024, 26476096, 26606656, 26737472,
26869184, 26998208, 27131584, 27262528, 27393728, 27523904, 27655744,
27786688, 27917888, 28049344, 28179904, 28311488, 28441792, 28573504,
28700864, 28835648, 28966208, 29096768, 29228608, 29359808, 29490752,
29621824, 29752256, 29882816, 30014912, 30144448, 30273728, 30406976,
30538432, 30670784, 30799936, 30932672, 31063744, 31195072, 31325248,
31456192, 31588288, 31719232, 31850432, 31981504, 32110784, 32243392,
32372672, 32505664, 32636608, 32767808, 32897344, 33029824, 33160768,
33289664, 33423296, 33554368, 33683648, 33816512, 33947456, 34076992,
34208704, 34340032, 34471744, 34600256, 34734016, 34864576, 34993984,
35127104, 35258176, 35386688, 35518528, 35650624, 35782336, 35910976,
36044608, 36175808, 36305728, 36436672, 36568384, 36699968, 36830656,
36961984, 37093312, 37223488, 37355072, 37486528, 37617472, 37747904,
37879232, 38009792, 38141888, 38272448, 38403392, 38535104, 38660672,
38795584, 38925632, 39059264, 39190336, 39320768, 39452096, 39581632,
39713984, 39844928, 39974848, 40107968, 40238144, 40367168, 40500032,
40631744, 40762816, 40894144, 41023552, 41155904, 41286208, 41418304,
41547712, 41680448, 41811904, 41942848, 42073792, 42204992, 42334912,
42467008, 42597824, 42729152, 42860096, 42991552, 43122368, 43253696,
43382848, 43515712, 43646912, 43777088, 43907648, 44039104, 44170432,
44302144, 44433344, 44564288, 44694976, 44825152, 44956864, 45088448,
45219008, 45350464, 45481024, 45612608, 45744064, 45874496, 46006208,
46136768, 46267712, 46399424, 46529344, 46660672, 46791488, 46923328,
47053504, 47185856, 47316928, 47447872, 47579072, 47710144, 47839936,
47971648, 48103232, 48234176, 48365248, 48496192, 48627136, 48757312,
48889664, 49020736, 49149248, 49283008, 49413824, 49545152, 49675712,
49807168, 49938368, 50069056, 50200256, 50331584, 50462656, 50593472,
50724032, 50853952, 50986048, 51117632, 51248576, 51379904, 51510848,
51641792, 51773248, 51903296, 52035136, 52164032, 52297664, 52427968,
52557376, 52690112, 52821952, 52952896, 53081536, 53213504, 53344576,
53475776, 53608384, 53738816, 53870528, 54000832, 54131776, 54263744,
54394688, 54525248, 54655936, 54787904, 54918592, 55049152, 55181248,
55312064, 55442752, 55574336, 55705024, 55836224, 55967168, 56097856,
56228672, 56358592, 56490176, 56621888, 56753728, 56884928, 57015488,
57146816, 57278272, 57409216, 57540416, 57671104, 57802432, 57933632,
58064576, 58195264, 58326976, 58457408, 58588864, 58720192, 58849984,
58981696, 59113024, 59243456, 59375552, 59506624, 59637568, 59768512,
59897792, 60030016, 60161984, 60293056, 60423872, 60554432, 60683968,
60817216, 60948032, 61079488, 61209664, 61341376, 61471936, 61602752,
61733696, 61865792, 61996736, 62127808, 62259136, 62389568, 62520512,
62651584, 62781632, 62910784, 63045056, 63176128, 63307072, 63438656,
63569216, 63700928, 63831616, 63960896, 64093888, 64225088, 64355392,
64486976, 64617664, 64748608, 64879424, 65009216, 65142464, 65273792,
65402816, 65535424, 65666752, 65797696, 65927744, 66060224, 66191296,
66321344, 66453056, 66584384, 66715328, 66846656, 66977728, 67108672,
67239104, 67370432, 67501888, 67631296, 67763776, 67895104, 68026304,
68157248, 68287936, 68419264, 68548288, 68681408, 68811968, 68942912,
69074624, 69205568, 69337024, 69467584, 69599168, 69729472, 69861184,
69989824, 70122944, 70253888, 70385344, 70515904, 70647232, 70778816,
70907968, 71040832, 71171648, 71303104, 71432512, 71564992, 71695168,
71826368, 71958464, 72089536, 72219712, 72350144, 72482624, 72613568,
72744512, 72875584, 73006144, 73138112, 73268672, 73400128, 73530944,
73662272, 73793344, 73924544, 74055104, 74185792, 74316992, 74448832,
74579392, 74710976, 74841664, 74972864, 75102784, 75233344, 75364544,
75497024, 75627584, 75759296, 75890624, 76021696, 76152256, 76283072,
76414144, 76545856, 76676672, 76806976, 76937792, 77070016, 77200832,
77331392, 77462464, 77593664, 77725376, 77856448, 77987776, 78118336,
78249664, 78380992, 78511424, 78642496, 78773056, 78905152, 79033664,
79166656, 79297472, 79429568, 79560512, 79690816, 79822784, 79953472,
80084672, 80214208, 80346944, 80477632, 80608576, 80740288, 80870848,
81002048, 81133504, 81264448, 81395648, 81525952, 81657536, 81786304,
81919808, 82050112, 82181312, 82311616, 82443968, 82573376, 82705984,
82835776, 82967744, 83096768, 83230528, 83359552, 83491264, 83622464,
83753536, 83886016, 84015296, 84147776, 84277184, 84409792, 84540608,
84672064, 84803008, 84934336, 85065152, 85193792, 85326784, 85458496,
85589312, 85721024, 85851968, 85982656, 86112448, 86244416, 86370112,
86506688, 86637632, 86769344, 86900672, 87031744, 87162304, 87293632,
87424576, 87555392, 87687104, 87816896, 87947968, 88079168, 88211264,
88341824, 88473152, 88603712, 88735424, 88862912, 88996672, 89128384,
89259712, 89390272, 89521984, 89652544, 89783872, 89914816, 90045376,
90177088, 90307904, 90438848, 90569152, 90700096, 90832832, 90963776,
91093696, 91223744, 91356992, 91486784, 91618496, 91749824, 91880384,
92012224, 92143552, 92273344, 92405696, 92536768, 92666432, 92798912,
92926016, 93060544, 93192128, 93322816, 93453632, 93583936, 93715136,
93845056, 93977792, 94109504, 94240448, 94371776, 94501184, 94632896,
94764224, 94895552, 95023424, 95158208, 95287744, 95420224, 95550016,
95681216, 95811904, 95943872, 96075328, 96203584, 96337856, 96468544,
96599744, 96731072, 96860992, 96992576, 97124288, 97254848, 97385536,
97517248, 97647808, 97779392, 97910464, 98041408, 98172608, 98303168,
98434496, 98565568, 98696768, 98827328, 98958784, 99089728, 99220928,
99352384, 99482816, 99614272, 99745472, 99876416, 100007104,
100138048, 100267072, 100401088, 100529984, 100662592, 100791872,
100925248, 101056064, 101187392, 101317952, 101449408, 101580608,
101711296, 101841728, 101973824, 102104896, 102235712, 102366016,
102498112, 102628672, 102760384, 102890432, 103021888, 103153472,
103284032, 103415744, 103545152, 103677248, 103808576, 103939648,
104070976, 104201792, 104332736, 104462528, 104594752, 104725952,
104854592, 104988608, 105118912, 105247808, 105381184, 105511232,
105643072, 105774784, 105903296, 106037056, 106167872, 106298944,
106429504, 106561472, 106691392, 106822592, 106954304, 107085376,
107216576, 107346368, 107478464, 107609792, 107739712, 107872192,
108003136, 108131392, 108265408, 108396224, 108527168, 108657344,
108789568, 108920384, 109049792, 109182272, 109312576, 109444928,
109572928, 109706944, 109837888, 109969088, 110099648, 110230976,
110362432, 110492992, 110624704, 110755264, 110886208, 111017408,
111148864, 111279296, 111410752, 111541952, 111673024, 111803456,
111933632, 112066496, 112196416, 112328512, 112457792, 112590784,
112715968, 112852672, 112983616, 113114944, 113244224, 113376448,
113505472, 113639104, 113770304, 113901376, 114031552, 114163264,
114294592, 114425536, 114556864, 114687424, 114818624, 114948544,
115080512, 115212224, 115343296, 115473472, 115605184, 115736128,
115867072, 115997248, 116128576, 116260288, 116391488, 116522944,
116652992, 116784704, 116915648, 117046208, 117178304, 117308608,
117440192, 117569728, 117701824, 117833024, 117964096, 118094656,
118225984, 118357312, 118489024, 118617536, 118749632, 118882112,
119012416, 119144384, 119275328, 119406016, 119537344, 119668672,
119798464, 119928896, 120061376, 120192832, 120321728, 120454336,
120584512, 120716608, 120848192, 120979136, 121109056, 121241408,
121372352, 121502912, 121634752, 121764416, 121895744, 122027072,
122157632, 122289088, 122421184, 122550592, 122682944, 122813888,
122945344, 123075776, 123207488, 123338048, 123468736, 123600704,
123731264, 123861952, 123993664, 124124608, 124256192, 124386368,
124518208, 124649024, 124778048, 124911296, 125041088, 125173696,
125303744, 125432896, 125566912, 125696576, 125829056, 125958592,
126090304, 126221248, 126352832, 126483776, 126615232, 126746432,
126876608, 127008704, 127139392, 127270336, 127401152, 127532224,
127663552, 127794752, 127925696, 128055232, 128188096, 128319424,
128449856, 128581312, 128712256, 128843584, 128973632, 129103808,
129236288, 129365696, 129498944, 129629888, 129760832, 129892288,
130023104, 130154048, 130283968, 130416448, 130547008, 130678336,
130807616, 130939456, 131071552, 131202112, 131331776, 131464384,
131594048, 131727296, 131858368, 131987392, 132120256, 132250816,
132382528, 132513728, 132644672, 132774976, 132905792, 133038016,
133168832, 133299392, 133429312, 133562048, 133692992, 133823296,
133954624, 134086336, 134217152, 134348608, 134479808, 134607296,
134741056, 134872384, 135002944, 135134144, 135265472, 135396544,
135527872, 135659072, 135787712, 135921472, 136052416, 136182848,
136313792, 136444864, 136576448, 136707904, 136837952, 136970048,
137099584, 137232064, 137363392, 137494208, 137625536, 137755712,
137887424, 138018368, 138149824, 138280256, 138411584, 138539584,
138672832, 138804928, 138936128, 139066688, 139196864, 139328704,
139460032, 139590208, 139721024, 139852864, 139984576, 140115776,
140245696, 140376512, 140508352, 140640064, 140769856, 140902336,
141032768, 141162688, 141294016, 141426496, 141556544, 141687488,
141819584, 141949888, 142080448, 142212544, 142342336, 142474432,
142606144, 142736192, 142868288, 142997824, 143129408, 143258944,
143392448, 143523136, 143653696, 143785024, 143916992, 144045632,
144177856, 144309184, 144440768, 144570688, 144701888, 144832448,
144965056, 145096384, 145227584, 145358656, 145489856, 145620928,
145751488, 145883072, 146011456, 146144704, 146275264, 146407232,
146538176, 146668736, 146800448, 146931392, 147062336, 147193664,
147324224, 147455936, 147586624, 147717056, 147848768, 147979456,
148110784, 148242368, 148373312, 148503232, 148635584, 148766144,
148897088, 149028416, 149159488, 149290688, 149420224, 149551552,
149683136, 149814976, 149943616, 150076352, 150208064, 150338624,
150470464, 150600256, 150732224, 150862784, 150993088, 151125952,
151254976, 151388096, 151519168, 151649728, 151778752, 151911104,
152042944, 152174144, 152304704, 152435648, 152567488, 152698816,
152828992, 152960576, 153091648, 153222976, 153353792, 153484096,
153616192, 153747008, 153878336, 154008256, 154139968, 154270912,
154402624, 154533824, 154663616, 154795712, 154926272, 155057984,
155188928, 155319872, 155450816, 155580608, 155712064, 155843392,
155971136, 156106688, 156237376, 156367424, 156499264, 156630976,
156761536, 156892352, 157024064, 157155008, 157284416, 157415872,
157545536, 157677248, 157810496, 157938112, 158071744, 158203328,
158334656, 158464832, 158596288, 158727616, 158858048, 158988992,
159121216, 159252416, 159381568, 159513152, 159645632, 159776192,
159906496, 160038464, 160169536, 160300352, 160430656, 160563008,
160693952, 160822208, 160956352, 161086784, 161217344, 161349184,
161480512, 161611456, 161742272, 161873216, 162002752, 162135872,
162266432, 162397888, 162529216, 162660032, 162790976, 162922048,
163052096, 163184576, 163314752, 163446592, 163577408, 163707968,
163839296, 163969984, 164100928, 164233024, 164364224, 164494912,
164625856, 164756672, 164887616, 165019072, 165150016, 165280064,
165412672, 165543104, 165674944, 165805888, 165936832, 166067648,
166198336, 166330048, 166461248, 166591552, 166722496, 166854208,
166985408, 167116736, 167246656, 167378368, 167508416, 167641024,
167771584, 167903168, 168034112, 168164032, 168295744, 168427456,
168557632, 168688448, 168819136, 168951616, 169082176, 169213504,
169344832, 169475648, 169605952, 169738048, 169866304, 169999552,
170131264, 170262464, 170393536, 170524352, 170655424, 170782016,
170917696, 171048896, 171179072, 171310784, 171439936, 171573184,
171702976, 171835072, 171966272, 172097216, 172228288, 172359232,
172489664, 172621376, 172747712, 172883264, 173014208, 173144512,
173275072, 173407424, 173539136, 173669696, 173800768, 173931712,
174063424, 174193472, 174325696, 174455744, 174586816, 174718912,
174849728, 174977728, 175109696, 175242688, 175374272, 175504832,
175636288, 175765696, 175898432, 176028992, 176159936, 176291264,
176422592, 176552512, 176684864, 176815424, 176946496, 177076544,
177209152, 177340096, 177470528, 177600704, 177731648, 177864256,
177994816, 178126528, 178257472, 178387648, 178518464, 178650176,
178781888, 178912064, 179044288, 179174848, 179305024, 179436736,
179568448, 179698496, 179830208, 179960512, 180092608, 180223808,
180354752, 180485696, 180617152, 180748096, 180877504, 181009984,
181139264, 181272512, 181402688, 181532608, 181663168, 181795136,
181926592, 182057536, 182190016, 182320192, 182451904, 182582336,
182713792, 182843072, 182976064, 183107264, 183237056, 183368384,
183494848, 183631424, 183762752, 183893824, 184024768, 184154816,
184286656, 184417984, 184548928, 184680128, 184810816, 184941248,
185072704, 185203904, 185335616, 185465408, 185596352, 185727296,
185859904, 185989696, 186121664, 186252992, 186383552, 186514112,
186645952, 186777152, 186907328, 187037504, 187170112, 187301824,
187429184, 187562048, 187693504, 187825472, 187957184, 188087104,
188218304, 188349376, 188481344, 188609728, 188743616, 188874304,
189005248, 189136448, 189265088, 189396544, 189528128, 189660992,
189791936, 189923264, 190054208, 190182848, 190315072, 190447424,
190577984, 190709312, 190840768, 190971328, 191102656, 191233472,
191364032, 191495872, 191626816, 191758016, 191888192, 192020288,
192148928, 192282176, 192413504, 192542528, 192674752, 192805952,
192937792, 193068608, 193198912, 193330496, 193462208, 193592384,
193723456, 193854272, 193985984, 194116672, 194247232, 194379712,
194508352, 194641856, 194772544, 194900672, 195035072, 195166016,
195296704, 195428032, 195558592, 195690304, 195818176, 195952576,
196083392, 196214336, 196345792, 196476736, 196607552, 196739008,
196869952, 197000768, 197130688, 197262784, 197394368, 197523904,
197656384, 197787584, 197916608, 198049472, 198180544, 198310208,
198442432, 198573632, 198705088, 198834368, 198967232, 199097792,
199228352, 199360192, 199491392, 199621696, 199751744, 199883968,
200014016, 200146624, 200276672, 200408128, 200540096, 200671168,
200801984, 200933312, 201062464, 201194944, 201326144, 201457472,
201588544, 201719744, 201850816, 201981632, 202111552, 202244032,
202374464, 202505152, 202636352, 202767808, 202898368, 203030336,
203159872, 203292608, 203423296, 203553472, 203685824, 203816896,
203947712, 204078272, 204208192, 204341056, 204472256, 204603328,
204733888, 204864448, 204996544, 205125568, 205258304, 205388864,
205517632, 205650112, 205782208, 205913536, 206044736, 206176192,
206307008, 206434496, 206569024, 206700224, 206831168, 206961856,
207093056, 207223616, 207355328, 207486784, 207616832, 207749056,
207879104, 208010048, 208141888, 208273216, 208404032, 208534336,
208666048, 208796864, 208927424, 209059264, 209189824, 209321792,
209451584, 209582656, 209715136, 209845568, 209976896, 210106432,
210239296, 210370112, 210501568, 210630976, 210763712, 210894272,
211024832, 211156672, 211287616, 211418176, 211549376, 211679296,
211812032, 211942592, 212074432, 212204864, 212334016, 212467648,
212597824, 212727616, 212860352, 212991424, 213120832, 213253952,
213385024, 213515584, 213645632, 213777728, 213909184, 214040128,
214170688, 214302656, 214433728, 214564544, 214695232, 214826048,
214956992, 215089088, 215219776, 215350592, 215482304, 215613248,
215743552, 215874752, 216005312, 216137024, 216267328, 216399296,
216530752, 216661696, 216790592, 216923968, 217054528, 217183168,
217316672, 217448128, 217579072, 217709504, 217838912, 217972672,
218102848, 218233024, 218364736, 218496832, 218627776, 218759104,
218888896, 219021248, 219151936, 219281728, 219413056, 219545024,
219675968, 219807296, 219938624, 220069312, 220200128, 220331456,
220461632, 220592704, 220725184, 220855744, 220987072, 221117888,
221249216, 221378368, 221510336, 221642048, 221772736, 221904832,
222031808, 222166976, 222297536, 222428992, 222559936, 222690368,
222820672, 222953152, 223083968, 223213376, 223345984, 223476928,
223608512, 223738688, 223869376, 224001472, 224132672, 224262848,
224394944, 224524864, 224657344, 224788288, 224919488, 225050432,
225181504, 225312704, 225443776, 225574592, 225704768, 225834176,
225966784, 226097216, 226229824, 226360384, 226491712, 226623424,
226754368, 226885312, 227015104, 227147456, 227278528, 227409472,
227539904, 227669696, 227802944, 227932352, 228065216, 228196288,
228326464, 228457792, 228588736, 228720064, 228850112, 228981056,
229113152, 229243328, 229375936, 229505344, 229636928, 229769152,
229894976, 230030272, 230162368, 230292416, 230424512, 230553152,
230684864, 230816704, 230948416, 231079616, 231210944, 231342016,
231472448, 231603776, 231733952, 231866176, 231996736, 232127296,
232259392, 232388672, 232521664, 232652608, 232782272, 232914496,
233043904, 233175616, 233306816, 233438528, 233569984, 233699776,
233830592, 233962688, 234092224, 234221888, 234353984, 234485312,
234618304, 234749888, 234880832, 235011776, 235142464, 235274048,
235403456, 235535936, 235667392, 235797568, 235928768, 236057152,
236190272, 236322752, 236453312, 236583616, 236715712, 236846528,
236976448, 237108544, 237239104, 237371072, 237501632, 237630784,
237764416, 237895232, 238026688, 238157632, 238286912, 238419392,
238548032, 238681024, 238812608, 238941632, 239075008, 239206336,
239335232, 239466944, 239599168, 239730496, 239861312, 239992384,
240122816, 240254656, 240385856, 240516928, 240647872, 240779072,
240909632, 241040704, 241171904, 241302848, 241433408, 241565248,
241696192, 241825984, 241958848, 242088256, 242220224, 242352064,
242481856, 242611648, 242744896, 242876224, 243005632, 243138496,
243268672, 243400384, 243531712, 243662656, 243793856, 243924544,
244054592, 244187072, 244316608, 244448704, 244580032, 244710976,
244841536, 244972864, 245104448, 245233984, 245365312, 245497792,
245628736, 245759936, 245889856, 246021056, 246152512, 246284224,
246415168, 246545344, 246675904, 246808384, 246939584, 247070144,
247199552, 247331648, 247463872, 247593536, 247726016, 247857088,
247987648, 248116928, 248249536, 248380736, 248512064, 248643008,
248773312, 248901056, 249036608, 249167552, 249298624, 249429184,
249560512, 249692096, 249822784, 249954112, 250085312, 250215488,
250345792, 250478528, 250608704, 250739264, 250870976, 251002816,
251133632, 251263552, 251395136, 251523904, 251657792, 251789248,
251919424, 252051392, 252182464, 252313408, 252444224, 252575552,
252706624, 252836032, 252968512, 253099712, 253227584, 253361728,
253493056, 253623488, 253754432, 253885504, 254017216, 254148032,
254279488, 254410432, 254541376, 254672576, 254803264, 254933824,
255065792, 255196736, 255326528, 255458752, 255589952, 255721408,
255851072, 255983296, 256114624, 256244416, 256374208, 256507712,
256636096, 256768832, 256900544, 257031616, 257162176, 257294272,
257424448, 257555776, 257686976, 257818432, 257949632, 258079552,
258211136, 258342464, 258473408, 258603712, 258734656, 258867008,
258996544, 259127744, 259260224, 259391296, 259522112, 259651904,
259784384, 259915328, 260045888, 260175424, 260308544, 260438336,
260570944, 260700992, 260832448, 260963776, 261092672, 261226304,
261356864, 261487936, 261619648, 261750592, 261879872, 262011968,
262143424, 262274752, 262404416, 262537024, 262667968, 262799296,
262928704, 263061184, 263191744, 263322944, 263454656, 263585216,
263716672, 263847872, 263978944, 264108608, 264241088, 264371648,
264501184, 264632768, 264764096, 264895936, 265024576, 265158464,
265287488, 265418432, 265550528, 265681216, 265813312, 265943488,
266075968, 266206144, 266337728, 266468032, 266600384, 266731072,
266862272, 266993344, 267124288, 267255616, 267386432, 267516992,
267648704, 267777728, 267910592, 268040512, 268172096, 268302784,
268435264, 268566208, 268696256, 268828096, 268959296, 269090368,
269221312, 269352256, 269482688, 269614784, 269745856, 269876416,
270007616, 270139328, 270270272, 270401216, 270531904, 270663616,
270791744, 270924736, 271056832, 271186112, 271317184, 271449536,
271580992, 271711936, 271843136, 271973056, 272105408, 272236352,
272367296, 272498368, 272629568, 272759488, 272891456, 273022784,
273153856, 273284672, 273415616, 273547072, 273677632, 273808448,
273937088, 274071488, 274200896, 274332992, 274463296, 274595392,
274726208, 274857536, 274988992, 275118656, 275250496, 275382208,
275513024, 275643968, 275775296, 275906368, 276037184, 276167872,
276297664, 276429376, 276560576, 276692672, 276822976, 276955072,
277085632, 277216832, 277347008, 277478848, 277609664, 277740992,
277868608, 278002624, 278134336, 278265536, 278395328, 278526784,
278657728, 278789824, 278921152, 279052096, 279182912, 279313088,
279443776, 279576256, 279706048, 279838528, 279969728, 280099648,
280230976, 280361408, 280493632, 280622528, 280755392, 280887104,
281018176, 281147968, 281278912, 281411392, 281542592, 281673152,
281803712, 281935552, 282066496, 282197312, 282329024, 282458816,
282590272, 282720832, 282853184, 282983744, 283115072, 283246144,
283377344, 283508416, 283639744, 283770304, 283901504, 284032576,
284163136, 284294848, 284426176, 284556992, 284687296, 284819264,
284950208, 285081536]

PSR-4: 自动加载

原文: https://www.php-fig.org/psr/psr-4/

RFC 2119中的必须(MUST)、不能(MUST NOT)、应当(SHOULD)、不应(SHOULD NOT)、可以(MAY)等术语将在本节用来做一些解释性的描述。

1. 概况

这个 PSR 描述的是通过文件路径自动加载类的指南,是对 PSR-0 的补充。根据这个指导如何规范存放文件以便自动加载。

2. 说明

  1. 术语“类”是一个泛称,它包含类、接口、特性(trait)以及其他类似的结构。

  2. 完全限定类名应该类似如下范例:

    \<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>

    1. 完全限定类名必须有一个顶级命名空间(Vendor Name);
    2. 完全限定类名可以有多个子命名空间;
    3. 完全限定类名应当有一个终止类名;
    4. 下划线在完全限定类名中是没有特殊含义的;
    5. 字母在完全限定类名中可以是任何大小写的组合;
    6. 所有类名必须以大小写敏感的方式引用。
  3. 当从完全限定类名载入文件时:

    1. 在完全限定类名中,连续的一个或几个子命名空间构成的命名空间前缀(不包括顶级命名空间的分隔符),至少对应着至少一个基础目录。
    2. 在“命名空间前缀”后的连续子命名空间名称对应一个“基础目录”下的子目录,其中的命名空间分隔符表示目录分隔符。子目录名称必须和子命名空间名大小写匹配;
    3. 终止类名对应一个以 .php 结尾的文件。文件名必须和终止类名大小写匹配。
  4. 自动加载器的实现不能抛出任何异常,不能引发任何等级的错误,也不应返回任何值。

3. 范例

如下表格展示的是与完全限定类名、命名空间前缀和基础目录相对应的文件路径:

完全限定类名 命名空间前缀 基础目录 实际的文件路径
\Acme\Log\Writer\File_Writer Acme\Log\Writer ./acme-log-writer/lib/ ./acme-log-writer/lib/File_Writer.php
\Aura\Web\Response\Status Aura\Web /path/to/aura-web/src/ /path/to/aura-web/src/Response/Status.php
\Symfony\Core\Request Symfony\Core ./vendor/Symfony/Core/ ./vendor/Symfony/Core/Request.php
\Zend\Acl Zend /usr/includes/Zend/ /usr/includes/Zend/Acl.php

例子中的自动加载器非常适合这个指南,请参照 示例文件。由于示例可能随时变更,不能作为指南的一部分。


PSR-3: 日志接口

原文: https://www.php-fig.org/psr/psr-3/

本文档描述了日志类库的通用接口。

主要目标是让类库获得一个Psr\Log\LoggerInterface对象并能通过简单通用的方式来写日志。有自定义需求的框架和CMS可以根据情况扩展这个接口,但应当保持和该文档的兼容性,以确保应用中使用到的第三方库能将日志集中写到应用日志里。

RFC 2119中的必须(MUST)、不能(MUST NOT)、应当(SHOULD)、不应(SHOULD NOT)、可以(MAY)等术语将在本节用来做一些解释性的描述。

术语开发者(implementor)在这个文档被解释为:在日志相关的库或框架实现LoggerInterface接口的开发人员。使用这些开发者开发出来的类库的人都被称作用户(user)。

1. 规范

1.1 基础

  • LoggerInterface暴露八个接口用来记录八个等级(debug, info, notice, warning, error, critical, alert, emergency)的日志。

  • 第九个方法是log,接受日志等级作为第一个参数。用一个日志等级常量来调用这个方法必须和直接调用指定等级方法的结果一致。用一个本规范中未定义且不为具体实现所知的日志等级来调用该方法必须抛出一个Psr\Log\InvalidArgumentException不应使用自定义的日志等级,除非你非常确定当前类库对其有所支持。

1.2 消息

  • 每个方法都接受一个字符串,或者一个有__toString方法的对象作为message参数。开发者可以对传入的对象有特殊的处理。如果没有,开发者必须将它转换成字符串。

  • message参数中可以包含一些可以context参数的数值所替换的占位符。

    占位符名字必须context数组类型参数的键名对应。

    占位符名字必须使用一对花括号来作为分隔符。在占位符和分隔符之间不能有任何空格。

    占位符名字应当只能由A-Za-z0-9、下划线_和句号.组成。其它的字符作为以后占位符规范的保留字。

    开发者可以使用占位符来实现不同的转义和翻译日志成文。因为用户并不知道上下文数据会是什么,所以不应提前转义占位符。

    下面提供一个占位符替换的例子,仅作为参考:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <?php
    /**
    * 占位符替换方法
    */
    function interpolate($message, array $context = array())
    {
    // 创建替换数组,元素用大括号包起来
    $replace = array();
    foreach ($context as $key => $val) {
    $replace['{' . $key . '}'] = $val;
    }

    // 替换 message 然后返回
    return strtr($message, $replace);
    }

    // 准备一个待替换的字符串
    $message = "User {username} created";

    // 准备替换数组,格式为 查找值 => 替换值
    $context = array('username' => 'bolivar');

    // 显示 "Username bolivar created"
    echo interpolate($message, $context);

1.3 上下文

  • 每个方法接受一个数组作为context参数,用来存储不适合在字符串中填充的信息。数组可以包括任何东西。开发者必须确保他们尽可能包容的对context参数进行处理。一个context参数的给定值不能导致抛出异常,也不能产生任何PHP错误,警告或者提醒。

  • 如果在context参数中传入了一个Exception对象,它必须以exception作为键名。记录异常轨迹是通用的模式,并且可以在日志系统支持的情况下从异常中提取出整个调用栈。开发者在将exception当做Exception对象来使用之前必须去验证它是不是一个Exception对象,因为它可以包含着任何东西。

1.4 助手类和接口

  • Psr\Log\AbstractLogger类可以让你通过继承它并实现通用的log方法来方便的实现LoggerInterface接口。而其他八个方法将会把消息和上下文转发给log方法。

  • 类似的,使用Psr\Log\LoggerTrait只需要你实现通用的log方法。注意特性是不能用来实现接口的,所以你依然需要在你的类中实现LoggerInterface

  • Psr\Log\NullLogger是和接口一起提供的。它在没有可用的日志记录器时,可以为使用日志接口的用户们提供一个后备的“黑洞”。但是,当context参数的构建非常耗时的时候,直接判断是否需要记录日志可能是个更好的选择。

  • Psr\Log\LoggerAwareInterface只有一个setLogger(LoggerInterface $logger)方法,它可以在框架中用来随意设置一个日志记录器。

  • Psr\Log\LoggerAwareTrait特性可以被用来在各个类中轻松实现相同的接口。通过它可以访问到$this->logger

  • Psr\Log\LogLevel类拥有八个日志等级的常量。

2. 包

psr/log中提供了上文描述过的接口和类,以及相关的异常类,还有一组用来验证你的实现的单元测试。

3. Psr\Log\LoggerInterface

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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<?php

namespace Psr\Log;

/**
* 描述一个日志处理实例
*
* message 必须是字符串,或者实现了 __toString() 方法。
*
* message 可以包含占位符,如 {foo} 会用 context 里以 "foo" 为下标的值给替换掉。
*
* context 数组可以随便包含一些数据,唯一的限制是异常的下标必须是 "exception"。
*
* 参见 https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
* 获取接口说明全文。
*/
interface LoggerInterface
{
/**
* 系统不可用
*
* @param string $message
* @param array $context
* @return null
*/
public function emergency($message, array $context = array());

/**
* 操作将立即执行
*
* 如:网站瘫痪、数据库崩溃等。
* 这种情况应该给你发个短信把你叫醒起来处理。
*
* @param string $message
* @param array $context
* @return null
*/
public function alert($message, array $context = array());

/**
* 紧急情况
*
* 如:应用组件不可用、未预料的异常。
*
* @param string $message
* @param array $context
* @return null
*/
public function critical($message, array $context = array());

/**
* 运行时错误。不需要立即处理,但应记录并监控。
*
* @param string $message
* @param array $context
* @return null
*/
public function error($message, array $context = array());

/**
* 不是错误的异常
*
* 如:使用过时的 API、API 使用不当,以及虽然不该发生但并不是错误的情况。
*
* @param string $message
* @param array $context
* @return null
*/
public function warning($message, array $context = array());

/**
* 正常但需要注意
*
* @param string $message
* @param array $context
* @return null
*/
public function notice($message, array $context = array());

/**
* 有趣的事件
*
* 如:用户登录、SQL 日志。
*
* @param string $message
* @param array $context
* @return null
*/
public function info($message, array $context = array());

/**
* 详细的调试信息
*
* @param string $message
* @param array $context
* @return null
*/
public function debug($message, array $context = array());

/**
* 任意等级的日志
*
* @param mixed $level
* @param string $message
* @param array $context
* @return null
*/
public function log($level, $message, array $context = array());
}

4. Psr\Log\LoggerAwareInterface

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

namespace Psr\Log;

/**
* 描述日志助手类实例
*/
interface LoggerAwareInterface
{
/**
* 为对象设置日志实例
*
* @param LoggerInterface $logger
* @return null
*/
public function setLogger(LoggerInterface $logger);
}

5. Psr\Log\LogLevel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php

namespace Psr\Log;

/**
* 描述日志等级
*/
class LogLevel
{
const EMERGENCY = 'emergency';
const ALERT = 'alert';
const CRITICAL = 'critical';
const ERROR = 'error';
const WARNING = 'warning';
const NOTICE = 'notice';
const INFO = 'info';
const DEBUG = 'debug';
}

PSR-2: 代码风格指南

原文: https://www.php-fig.org/psr/psr-2/

本手册是基础代码规范(PSR-1)的继承和扩展。

为了尽可能的提升阅读其他人代码时的效率,下面例举了一系列的通用规则,特别是有关于PHP代码风格的。

各个成员项目间的共性组成了这组代码规范。当开发者们在多个项目中合作时,本指南将会成为所有这些项目中共用的一组代码规范。 因此,本指南的益处不在于这些规则本身,而在于在所有项目中共用这些规则。

RFC 2119中的必须(MUST)、不能(MUST NOT)、应当(SHOULD)、不应(SHOULD NOT)、可以(MAY)等术语将在本节用来做一些解释性的描述。

1. 概述

  • 代码必须遵守“基础代码规范” PSR-1

  • 代码必须使用4个空格来进行缩进,而不是用制表符。

  • 一行代码的长度不能有强制限制;非强制限制必须为120个字符,每行代码应当有80个字符或者更少。

  • namespace的声明下面必须有一行空行,并且在use的声明下面也必须有一行空行。

  • 类的左花括号必须放到其声明下面自成一行,右花括号则必须放到类主体下面自成一行。

  • 方法的左花括号必须放到其声明下面自成一行,右花括号则必须放到方法主体的下一行。

  • 所有的属性和方法必须有可见性声明;abstractfinal声明必须在可见性声明之前;而static声明必须在可见性声明之后。

  • 在控制结构关键字的后面必须有一个空格;而方法和函数的关键字的后面不能有空格。

  • 控制结构的左花括号必须跟其放在同一行,右花括号必须放在该控制结构代码主体的下一行。

  • 控制结构的左括号之后不能有空格,右括号之前也不能有空格。

1.1. 示例

这个示例中简单展示了上文中提到的一些规则:

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
<?php
namespace Vendor\Package;

use FooInterface;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class Foo extends Bar implements FooInterface
{
public function sampleFunction($a, $b = null)
{
if ($a === $b) {
bar();
} elseif ($a > $b) {
$foo->bar($arg1);
} else {
BazClass::bar($arg2, $arg3);
}
}

final public static function bar()
{
// 方法体
}
}

2. 通则

2.1 基础代码规范

代码必须遵守 PSR-1 中的所有规则。

2.2 源文件

所有的PHP源文件必须使用Unix LF(换行)作为行结束符。

所有PHP源文件必须以一个空行结束。

纯PHP代码源文件的关闭标签 ?> 必须省略。

2.3. 行

行长度不能有强制限制。

行长度的非强制限制必须是120个字符;对于非强制限制,代码风格检查器必须警告但不能报错。

一行代码的长度不应超过80个字符;较长的行应当拆分成多个不超过80个字符的子行。

在非空行后面不能有空格。

空行可以用来增强可读性和区分相关代码块。

一行不能多于一个语句。

2.4. 缩进

代码必须使用4个空格,且不能使用制表符来作为缩进。

注意:代码中只使用空格,且不和制表符混合使用,将会对避免代码差异、补丁、历史和注解中的一些问题有帮助。空格的使用还可以使通过调整细微的缩进来改进行间对齐变得更加的简单。

2.5. 关键字和 True/False/Null

PHP关键字(keywords)必须使用小写字母。

PHP常量truefalsenull 必须使用小写字母。

3. 命名空间和导入声明

命名空间(namespace)的声明后面必须有一行空行。

所有的导入(use)声明必须放在命名空间(namespace)声明的下面。

一句声明中,必须只有一个导入(use)关键字。

在导入(use)声明代码块后面必须有一行空行。

例如:

1
2
3
4
5
6
7
8
<?php
namespace Vendor\Package;

use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

// ... 其它PHP代码 ...

4. 类、属性和方法

术语“类”指所有的类、接口和特性。

4.1. 继承和实现

一个类的继承(extends)和实现(implement)术语必须和类名在同一行。

类的左花括号必须放在下面自成一行;右花括号必须放在类主体的后面自成一行。

1
2
3
4
5
6
7
8
9
10
11
<?php
namespace Vendor\Package;

use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class ClassName extends ParentClass implements \ArrayAccess, \Countable
{
// 常量、属性、方法
}

实现(implement)列表可以被拆分为多个缩进了一次的子行。如果要拆成多个子行,列表的第一项必须要放在下一行,并且每行必须只有一个接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
namespace Vendor\Package;

use FooClass;
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass;

class ClassName extends ParentClass implements
\ArrayAccess,
\Countable,
\Serializable
{
// 常量、属性、方法
}

4.2. 属性

所有的属性都必须声明其可见性。

关键字var不能用来声明一个属性。

一条语句不能声明多个属性。

属性名不应用单个下划线作为前缀来表明其保护或私有的可见性。

一个属性声明看起来应该像下面这样。

1
2
3
4
5
6
7
<?php
namespace Vendor\Package;

class ClassName
{
public $foo = null;
}

4.3. 方法

所有的方法都必须声明其可见性。

方法名不应用单个下划线作为前缀来表明其保护或私有的可见性。

方法名在其声明后面不能有空格跟随。其左花括号必须放在下面自成一行,且右花括号必须放在方法主体的下面自成一行。左括号后面不能有空格,且右括号前面也不能有空格。

一个方法声明看来应该像下面这样。 注意括号、逗号、空格和花括号的位置:

1
2
3
4
5
6
7
8
9
10
<?php
namespace Vendor\Package;

class ClassName
{
public function fooBarBaz($arg1, &$arg2, $arg3 = [])
{
// 方法主体部分
}
}

4.4. 方法参数

在参数列表中,逗号之前不能有空格,而逗号之后则必须要有一个空格。

方法中有默认值的参数必须放在参数列表的最后面。

1
2
3
4
5
6
7
8
9
10
<?php
namespace Vendor\Package;

class ClassName
{
public function foo($arg1, &$arg2, $arg3 = [])
{
// 方法体
}
}

参数列表可以被拆分为多个缩进了一次的子行。如果要拆分成多个子行,参数列表的第一项必须放在下一行,并且每行必须只有一个参数。

当参数列表被拆分成多个子行,右括号和左花括号之间必须有一个空格并且自成一行。

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
namespace Vendor\Package;

class ClassName
{
public function aVeryLongMethodName(
ClassTypeHint $arg1,
&$arg2,
array $arg3 = []
) {
// 方法体
}
}

4.5. 抽象、终结和静态

当用到抽象(abstract)和终结(final)来做类声明时,它们必须放在可见性声明的前面。

而当用到静态(static)来做类声明时,则必须放在可见性声明的后面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
namespace Vendor\Package;

abstract class ClassName
{
protected static $foo;

abstract protected function zim();

final public static function bar()
{
// 方法体
}
}

4.6. 调用方法和函数

调用一个方法或函数时,在方法名或者函数名和左括号之间不能有空格,左括号之后不能有空格,右括号之前也不能有空格。参数列表中,逗号之前不能有空格,逗号之后则必须有一个空格。

1
2
3
4
<?php
bar();
$foo->bar($arg1);
Foo::bar($arg2, $arg3);

参数列表可以被拆分成多个缩进了一次的子行。如果拆分成子行,列表中的第一项必须放在下一行,并且每一行必须只能有一个参数。

1
2
3
4
5
6
<?php
$foo->bar(
$longArgument,
$longerArgument,
$muchLongerArgument
);

5. 控制结构

下面是对于控制结构代码风格的概括:

  • 控制结构的术语之后必须有一个空格。
  • 控制结构的左括号之后不能有空格。
  • 控制结构的右括号之前不能有空格。
  • 控制结构的右括号和左花括号之间必须有一个空格。
  • 控制结构的代码主体必须进行一次缩进。
  • 控制结构的右花括号必须主体的下一行。

每个控制结构的代码主体必须被括在花括号里。这样可是使代码看上去更加标准化,并且加入新代码的时候还可以因此而减少引入错误的可能性。

5.1. ifelseifelse

下面是一个if条件控制结构的示例,注意其括号、空格和花括号的位置。同时注意elseelseif要和前一个条件控制结构的右花括号在同一行。

1
2
3
4
5
6
7
8
<?php
if ($expr1) {
// if body
} elseif ($expr2) {
// elseif body
} else {
// else body;
}

应当elseif来替代else if,以保持所有的条件控制关键字看起来像是一个单词。

5.2. switchcase

下面是一个switch条件控制结构的示例,注意其中括号、空格和花括号的位置。case语句必须要缩进一级,而break关键字(或其他中止关键字)必须case结构的代码主体在同一个缩进层级。如果一个有主体代码的case结构故意的继续向下执行则必须要有一个类似于// no break的注释。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
switch ($expr) {
case 0:
echo 'First case, with a break';
break;
case 1:
echo 'Second case, which falls through';
// no break
case 2:
case 3:
case 4:
echo 'Third case, return instead of break';
return;
default:
echo 'Default case';
break;
}

5.3. whiledo while

下面是一个while循环控制结构的示例,注意其括号、空格和花括号的位置。

1
2
3
4
<?php
while ($expr) {
// 结构体
}

下面是一个do while循环控制结构的示例,注意其括号、空格和花括号的位置。

1
2
3
4
<?php
do {
// 结构体
} while ($expr);

5.4. for

下面是一个for循环控制结构的示例,注意其括号、空格和花括号的位置。

1
2
3
4
<?php
for ($i = 0; $i < 10; $i++) {
// 循环体
}

5.5. foreach

下面是一个foreach循环控制结构的示例,注意其括号、空格和花括号的位置。

1
2
3
4
<?php
foreach ($iterable as $key => $value) {
// 循环体
}

5.6. trycatch

下面是一个try catch异常处理控制结构的示例,注意其括号、空格和花括号的位置。

1
2
3
4
5
6
7
8
<?php
try {
// try body
} catch (FirstExceptionType $e) {
// catch body
} catch (OtherExceptionType $e) {
// catch body
}

6. 闭包

声明闭包时所用的function关键字之后必须要有一个空格,而use关键字的前后都要有一个空格。

闭包的左花括号必须跟其在同一行,而右花括号必须在闭包主体的下一行。

闭包的参数列表和变量列表的左括号后面不能有空格,右括号的前面也不能有空格。

闭包的参数列表和变量列表中逗号前面不能有空格,而逗号后面则必须有空格。

闭包的参数列表中带默认值的参数必须放在参数列表的结尾部分。

下面是一个闭包的示例。注意括号、空格和花括号的位置。

1
2
3
4
5
6
7
8
<?php
$closureWithArgs = function ($arg1, $arg2) {
// body
};

$closureWithArgsAndVars = function ($arg1, $arg2) use ($var1, $var2) {
// body
};

参数列表和变量列表可以被拆分成多个缩进了一级的子行。如果要拆分成多个子行,列表中的第一项必须放在下一行,并且每一行必须只放一个参数或变量。

当列表(不管是参数还是变量)最终被拆分成多个子行,右括号和左花括号之间必须要有一个空格并且自成一行。

下面是一个参数列表和变量列表被拆分成多个子行的示例。

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
<?php
$longArgs_noVars = function (
$longArgument,
$longerArgument,
$muchLongerArgument
) {
// body
};

$noArgs_longVars = function () use (
$longVar1,
$longerVar2,
$muchLongerVar3
) {
// body
};

$longArgs_longVars = function (
$longArgument,
$longerArgument,
$muchLongerArgument
) use (
$longVar1,
$longerVar2,
$muchLongerVar3
) {
// body
};

$longArgs_shortVars = function (
$longArgument,
$longerArgument,
$muchLongerArgument
) use ($var1) {
// body
};

$shortArgs_longVars = function ($arg) use (
$longVar1,
$longerVar2,
$muchLongerVar3
) {
// body
};

把闭包作为一个参数在函数或者方法中调用时,依然要遵守上述规则。

1
2
3
4
5
6
7
8
<?php
$foo->bar(
$arg1,
function ($arg2) use ($var1) {
// body
},
$arg3
);

7. 结论

本指南有意的省略了许多元素的代码风格。主要包括:

  • 全局变量和全局常量的声明

  • 函数声明

  • 操作符和赋值

  • 行间对齐

  • 注释和文档块

  • 类名的前缀和后缀

  • 最佳实践

以后的代码规范中可能会修正或扩展本指南中规定的代码风格。

附录A 调查

为了写这个风格指南,我们调查了各个项目以最终确定通用的代码风格。并把这次调查在这里公布出来。

A.1. 调查数据

url,http://www.horde.org/apps/horde/docs/CODING_STANDARDS,http://pear.php.net/manual/en/standards.php,http://solarphp.com/manual/appendix-standards.style,http://framework.zend.com/manual/en/coding-standard.html,http://symfony.com/doc/2.0/contributing/code/standards.html,http://www.ppi.io/docs/coding-standards.html,https://github.com/ezsystems/ezp-next/wiki/codingstandards,http://book.cakephp.org/2.0/en/contributing/cakephp-coding-conventions.html,https://github.com/UnionOfRAD/lithium/wiki/Spec%3A-Coding,http://drupal.org/coding-standards,http://code.google.com/p/sabredav/,http://area51.phpbb.com/docs/31x/coding-guidelines.html,https://docs.google.com/a/zikula.org/document/edit?authkey=CPCU0Us&hgd=1&id=1fcqb93Sn-hR9c0mkN6m_tyWnmEvoswKBtSc0tKkZmJA,http://www.chisimba.com,n/a,https://github.com/Respect/project-info/blob/master/coding-standards-sample.php,n/a,Object Calisthenics for PHP,http://doc.nette.org/en/coding-standard,http://flow3.typo3.org,https://github.com/propelorm/Propel2/wiki/Coding-Standards,http://developer.joomla.org/coding-standards.html
voting,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,no,no,no,?,yes,no,yes
indent_type,4,4,4,4,4,tab,4,tab,tab,2,4,tab,4,4,4,4,4,4,tab,tab,4,tab
line_length_limit_soft,75,75,75,75,no,85,120,120,80,80,80,no,100,80,80,?,?,120,80,120,no,150
line_length_limit_hard,85,85,85,85,no,no,no,no,100,?,no,no,no,100,100,?,120,120,no,no,no,no
class_names,studly,studly,studly,studly,studly,studly,studly,studly,studly,studly,studly,lower_under,studly,lower,studly,studly,studly,studly,?,studly,studly,studly
class_brace_line,next,next,next,next,next,same,next,same,same,same,same,next,next,next,next,next,next,next,next,same,next,next
constant_names,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper,upper
true_false_null,lower,lower,lower,lower,lower,lower,lower,lower,lower,upper,lower,lower,lower,upper,lower,lower,lower,lower,lower,upper,lower,lower
method_names,camel,camel,camel,camel,camel,camel,camel,camel,camel,camel,camel,lower_under,camel,camel,camel,camel,camel,camel,camel,camel,camel,camel
method_brace_line,next,next,next,next,next,same,next,same,same,same,same,next,next,same,next,next,next,next,next,same,next,next
control_brace_line,same,same,same,same,same,same,next,same,same,same,same,next,same,same,next,same,same,same,same,same,same,next
control_space_after,yes,yes,yes,yes,yes,no,yes,yes,yes,yes,no,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes,yes
always_use_control_braces,yes,yes,yes,yes,yes,yes,no,yes,yes,yes,no,yes,yes,yes,yes,no,yes,yes,yes,yes,yes,yes
else_elseif_line,same,same,same,same,same,same,next,same,same,next,same,next,same,next,next,same,same,same,same,same,same,next
case_break_indent_from_switch,0/1,0/1,0/1,1/2,1/2,1/2,1/2,1/1,1/1,1/2,1/2,1/1,1/2,1/2,1/2,1/2,1/2,1/2,0/1,1/1,1/2,1/2
function_space_after,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no
closing_php_tag_required,no,no,no,no,no,no,no,no,yes,no,no,no,no,yes,no,no,no,no,no,yes,no,no
line_endings,LF,LF,LF,LF,LF,LF,LF,LF,?,LF,?,LF,LF,LF,LF,?,,LF,?,LF,LF,LF
static_or_visibility_first,static,?,static,either,either,either,visibility,visibility,visibility,either,static,either,?,visibility,?,?,either,either,visibility,visibility,static,?
control_space_parens,no,no,no,no,no,no,yes,no,no,no,no,no,no,yes,?,no,no,no,no,no,no,no
blank_line_after_php,no,no,no,no,yes,no,no,no,no,yes,yes,no,no,yes,?,yes,yes,no,yes,no,yes,no
class_method_control_brace,next/next/same,next/next/same,next/next/same,next/next/same,next/next/same,same/same/same,next/next/next,same/same/same,same/same/same,same/same/same,same/same/same,next/next/next,next/next/same,next/same/same,next/next/next,next/next/same,next/next/same,next/next/same,next/next/same,same/same/same,next/next/same,next/next/next

A.2. 调查说明

indent_type: 缩进类型。 tab = “使用制表符”,2 or 4 = “空格数量”

line_length_limit_soft: 行长度的“软”限制,用字符。 ? = 不表示或者数字 no 意为不限制.

line_length_limit_hard: 行长度的”硬”限制,用字符。 ? = 不表示或者数字, no 意为不限制.

class_names: 类名如何命名 lower = 只是小写, lower_under = 小写加下划线, studly = 骆驼型.

class_brace_line: 类的左花括号是放在同(same)一行还是在下(next)一行?

constant_names: 类常量如何命名?upper = 大写加下划线分隔符。

true_false_null: 全小写或者全大写?

method_names: 方法名如何命名?camel = 驼峰式, lower_under = 小写加下划线分隔符。

method_brace_line: 方法的左花括号在同(same)一行还是在下(next)一行?

control_brace_line: 控制结构的左花括号在同(same)一行还是在下(next)一行?

control_space_after: 控制结构术语后是否有空格?

always_use_control_braces: 控制结构总是使用花括号?

else_elseif_line: 当使用elseelseif,是否放在同(same)一行还是在下(next)一行?

case_break_indent_from_switch: casebreak分别从swith语句处缩进多少次?

function_space_after: 函数调用的函数名和左括号是否有空格?

closing_php_tag_required: 如过是纯PHP文件,关闭标签?>是否需要?

line_endings: 使用何种的行结束符?

static_or_visibility_first: 在定义方法的时候static和可见性谁在前面?

control_space_parens: 在控制结构表达式中,左括号后面和右括号前面是否要有一个空格?yes = if ( $expr ), no = if ($expr).

blank_line_after_php: PHP的开始标签后面是否需要一个空行?

class_method_control_brace: 左花括号在类,方法和控制结构中的位置。

A.3. 调查结果

indent_type:
    tab: 7
    2: 1
    4: 14
line_length_limit_soft:
    ?: 2
    no: 3
    75: 4
    80: 6
    85: 1
    100: 1
    120: 4
    150: 1
line_length_limit_hard:
    ?: 2
    no: 11
    85: 4
    100: 3
    120: 2
class_names:
    ?: 1
    lower: 1
    lower_under: 1
    studly: 19
class_brace_line:
    next: 16
    same: 6
constant_names:
    upper: 22
true_false_null:
    lower: 19
    upper: 3
method_names:
    camel: 21
    lower_under: 1
method_brace_line:
    next: 15
    same: 7
control_brace_line:
    next: 4
    same: 18
control_space_after:
    no: 2
    yes: 20
always_use_control_braces:
    no: 3
    yes: 19
else_elseif_line:
    next: 6
    same: 16
case_break_indent_from_switch:
    0/1: 4
    1/1: 4
    1/2: 14
function_space_after:
    no: 22
closing_php_tag_required:
    no: 19
    yes: 3
line_endings:
    ?: 5
    LF: 17
static_or_visibility_first:
    ?: 5
    either: 7
    static: 4
    visibility: 6
control_space_parens:
    ?: 1
    no: 19
    yes: 2
blank_line_after_php:
    ?: 1
    no: 13
    yes: 8
class_method_control_brace:
    next/next/next: 4
    next/next/same: 11
    next/same/same: 1
    same/same/same: 6

PSR-1: 基本代码规范

原文: https://www.php-fig.org/psr/psr-1/

本节我们将会讨论一些基本的代码规范问题,以此作为将来讨论更高级别的代码分享和技术互用的基础。

RFC 2119中的必须(MUST)、不能(MUST NOT)、应当(SHOULD)、不应(SHOULD NOT)、可以(MAY)等术语将在本节用来做一些解释性的描述。

1. 概述

  • 源文件必须只使用 <?php<?= 这两种标签。
  • 源文件中PHP代码的编码格式必须只使用不带字节顺序标记(BOM)的UTF-8。
  • 一个源文件应当只用来做声明(类、函数、常量等)或者只用来做一些引起副作用的操作(如输出信息、修改.ini配置等),但不应同时做这两件事。
  • 命名空间和类必须遵守关于自动加载的PSR标准:[PSR-0, PSR-4]。
  • 类名必须使用StulyCaps写法。
  • 类中的常量必须只由大写字母和下划线组成。
  • 方法名必须使用camelCase写法。

2. 文件

2.1. PHP标签

PHP代码必须只使用长标签<?php ?>或者短输出式标签<?= ?>,而不能使用其他标签。

2.2. 字符编码

PHP代码的编码格式必须只使用不带字节顺序标记(BOM)的UTF-8。

2.3. 副作用

一个源文件应当只用来做声明(类、函数、常量等)或者只用来做一些引起副作用的操作(如输出信息、修改.ini配置等),但不应同时做这两件事。

短语“副作用”的意思是在包含文件时所执行的逻辑与所声明的类、函数、常量等没有直接的关系。

“副作用”包括但不限于:产生输出,显式地使用requireinclude,连接外部服务,修改ini配置,触发错误或异常,修改全局或者静态变量,读取或修改文件等等。

下面是一个既包含声明又有副作用的示例文件;即应避免的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
// 副作用:修改了ini配置
ini_set('error_reporting', E_ALL);

// 副作用:载入了文件
include "file.php";

// 副作用:产生了输出
echo "<html>\n";

// 声明
function foo()
{
// 函数体
}

下面是一个仅包含声明的示例文件;即应提倡的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
// 声明
function foo()
{
// 函数体
}

// 条件式声明*不*算做是副作用
if (! function_exists('bar')) {
function bar()
{
// 函数体
}
}

3. 命名空间和类名

命名空间和类必须遵守关于自动加载的PSR标准:[PSR-0, PSR-4]。

这意味着一个源文件中只能有一个类,并且每个类至少要有一级空间名,即一个顶级的组织名。

类名必须使用StulyCaps写法。

PHP5.3之后的代码必须使用正式的命名空间。

例如:

1
2
3
4
5
6
7
<?php
// PHP 5.3 及之后:
namespace Vendor\Model;

class Foo
{
}

PHP5.2.x和之前的代码应当用伪命名空间Vendor_作为类名的前缀:

1
2
3
4
5
<?php
// PHP 5.2.x 及之前:
class Vendor_Model_Foo
{
}

4. 类的常量、属性和方法

术语“类”指所有的类、接口和特性。

4.1. 常量

类常量必须只由大写字母和下划线组成。

例如:

1
2
3
4
5
6
7
8
<?php
namespace Vendor\Model;

class Foo
{
const VERSION = '1.0';
const DATE_APPROVED = '2012-06-01';
}

4.2. 属性

本指南中故意不对$StulyCaps$camelCase$unser_score中的某一种风格作特别推荐,完全由读者依据个人喜好决定属性名的命名风格。

但是不管你如何定义属性名,应当在一个合理的范围内保持一致。这个范围可能是组织级别的、包级别的、类级别的或者方法级别的。

4.3. 方法

方法名则必须使用camelCase()风格来声明。


PHP中PSR-[0-4]代码规范【转】

原文链接: http://www.cnblogs.com/52php/p/5852572.html

PHP-FIG

在说啥是PSR-[0-4]规范的之前,我觉得我们有必要说下它的发明者和规范者:PHP-FIG,它的网站是:https://www.php-fig.org 。就是这个联盟组织发明和创造了PSR-[0-4]规范,膜拜吧,屌丝们!

FIG 是 Framework Interoperability Group(框架可互用性小组)的缩写,由几位开源框架的开发者成立于 2009 年,从那开始也选取了很多其他成员进来,虽然不是 “官方” 组织,但也代表了社区中不小的一块。组织的目的在于:以最低程度的限制,来统一各个项目的编码规范,避免各家自行发展的风格阻碍了程序设计师开发的困扰,于是大伙发明和总结了PSR,PSR是Proposing a Standards Recommendation(提出标准建议)的缩写,截止到目前为止,总共有5套PSR规范,分别是:

  • PSR-0 (Autoloading Standard) 自动加载标准
  • PSR-1 (Basic Coding Standard) 基础编码标准
  • PSR-2 (Coding Style Guide) 编码风格向导
  • PSR-3 (Logger Interface) 日志接口
  • PSR-4 (Improved Autoloading) 自动加载的增强版,可以替换掉PSR-0了。

接下来的篇目,我们会针对这5套,深入了解下。仔细学习下受万千PHPer热捧的这5套规范到底有啥出众之处。

PSR-0 规范

PRS-0规范是他们出的第1套规范,主要是制定了一些自动加载标准(Autoloading Standard),如果你英文比较好,可以直接看官网的这个:PSR-0,很短。我们打开PSR-0的主页时,发现多了一个警告:

Deprecated - As of 2014-10-21 PSR-0 has been marked as deprecated. [PSR-4](http://www.php-fig.org/psr/psr-4/) is now recommended as an alternative.

大概意思:

不推荐使用 - 在2014年10月21日PSR-0已被标记为过时。PSR-4现在推荐作为替代。

那么也就是说PSR-0已!经!过!时!了!,别哭,PHP代码狗。虽说已经过时,但是我们也可以看看嘛,这不影响我们的学习,好了。废话不说了,开始吧:

PSR-0强制性要求几点:

  1. 一个完全合格的namespace和class必须符合这样的结构:\<Vendor Name>(<Namespace>)*<Class Name>
  2. 每个namespace必须有一个顶层的namespace(”Vendor Name”提供者名字)
  3. 每个namespace可以有多个子namespace
  4. 当从文件系统中加载时,每个namespace的分隔符(/)要转换成 DIRECTORY_SEPARATOR(操作系统路径分隔符)
  5. 在类名中,每个下划线(_)符号要转换成DIRECTORY_SEPARATOR(操作系统路径分隔符)。在namespace中,下划线(_)符号是没有(特殊)意义的。
  6. 当从文件系统中载入时,合格的namespace和class一定是以 .php 结尾的
  7. verdor name,namespaces,class名可以由大小写字母组合而成(大小写敏感的)

是不是有点看不懂啊。什么namespace啊,什么autoloading啊。所以,如果你对命名空间还不是特别懂的话,可以google下namespace 和 自动加载相关的php知识。或者看下一篇,我专门来讲讲他们:namespace 和 autoloading

好,我们接着一条条举例来分析下:

第1条

比如我的文件 /Doctrine/Common/IsolatedClassLoader.php 这样子的一个类文件,那么你的namespace命名就必须声明称这样:

1
2
声明:namespace \Doctrine\Common\
调用:\Doctrine\Common\IsolatedClassLoader

其中,Doctrine 表示一个模块目录 Vendor name, Common就是namesapce, IsolatedClassLoader是class name。这样一看就知道这个文件的目录层次,一目了然。

再比如:/path/to/project/lib/vendor/Symfony/Core/Request.php 文件:

1
2
声明:namespace \Symfony\Core
调用:\Symfony\Core\Request

第2,3条

1
2
namespace \Zend\Acl => /path/to/project/lib/vendor/Zend/Acl.php
namespace \Zend\Mail\Message => /path/to/project/lib/vendor/Zend/Mail/Message.php

必须有一个顶级的zend的namespace, zend 下面可以有message子命名空间。

第4条

看这个例子,我们需要new 一个这样的类

1
new \Symfony\Core\Request

那么我再加载这个类文件时候,就要将分隔符 \ 转换成 目录,也就是去 Vendor -> Symfony->Core->Request.php 一层层的目录找到这个文件。其实也就是和第1,2,3是反过来的对应关系。

第5条

第5条是说namespace命名中的这个 _ 符号 没有任何用处,就是用来表示目录分隔符的,但是注意在PRS-4中已经取消了这个_ ,那么我们还是看一下,这个过时的规定是怎么样的:

1
2
\namespace\package\Class_Name => /path/to/project/lib/vendor/namespace/package/Class/Name.php
\namespace\package_name\Class_Name => /path/to/project/lib/vendor/namespace/package_name/Class/Name.php

以上2个namespace中的 _ 其实是目录分隔符。并不是class name就是那样的。现在PSR-4出来后,确实觉得这样的规定有点不好。怪怪的。

第6条

第6条不用多说。既然你用php,文件名当然是得用.php 后缀结尾。这个规定的原因,我大致猜一下,估计是有人用 .php3 后缀的。好吧。这个是个神话了。因为在apache的配置文件中是允许的:

1
2
3
<IfModule dir_module>
DirectoryIndex index.php index.php3 index.html index.htm
</IfModule>

所以,老老实实的用.php作为后缀名吧。

第7条

文件大小写的问题,这个其实是很重要的。因为Linux系统下是区分文件名和目录名大小写的,而在Windows下是不区分的。所以就会经常出现问题,比如:

1
namespace  \Doctrine\Common\IsolatedClassLoader

在Linux下就去严格按照大小写去找目录和文件了。但是如果你在Windows下开发,全是小写也不会报错,你一发布到Linux上就悲剧了,提示找不到文件。所以,大小写太重要了。

PSR-1 规范

还是那句话,如果你英文比较好,可以直接看官网的这个:PSR-1,也不长,基本能看懂。但是如果你英语不好,那么还是请继续往下看

  1. PHP源文件必须只使用 <?php<?= 这两种标签。
  2. 源文件中php代码的编码格式必须是不带字节顺序标记(BOM)的UTF-8。
  3. 一个源文件建议只用来做声明(类(class),函数(function),常量(constant)等)或者只用来做一些引起副作用的操作(例如:输出信息,修改.ini配置等),但不建议同时做这两件事。
  4. 命名空间(namespace)和类(class) 必须遵守PSR-0标准。
  5. 类名(class name) 必须使用骆驼式(StudlyCaps)写法 (注:驼峰式(cameCase)的一种变种,后文将直接用StudlyCaps表示)。
  6. 类(class)中的常量必须只由大写字母和下划线(_)组成。
  7. 方法名(method name) 必须使用驼峰式(cameCase)写法。 好,就是上面的基本7大点,有些很简单,就不过多说明,第3点需要仔细说下。

第1条

这个基本都是大家都懂得的,PHP代码必须只使用长标签(<?php ?>)或者短输出式标签(<?= ?>);而不要使用其他标签。

之所以说这个,是因为我们在学习PHP的时候,一般的教材都告诉我们说,php有4种标记风格:php的4种标记风格 所以,很多人就乱来了。特别是asp风格的简直是折磨好么!!!

第2条

这个不多说,保存的时候格式必须是无BOM的UTF-8格式,否则会出现很多无法解释的千奇百怪的问题。千万别傻逼的用Windows下的text文本编辑器保存文件啊

第3条

这个通俗的说呢。就是别把一些输出和修改的操作(副作用) 和 类文件混合在一起,专注一点,这个文件专门来声明Class, 那个文件专门来修改配置文件,别混在一起写:

所以,以下的这个文件是有问题的,最好不要这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 副作用:修改了ini配置
ini_set('error_reporting', E_ALL);

// 副作用:载入了文件
include "file.php";

// 副作用:产生了输出
echo "<html>\n";

// 声明 function
function foo()
{
// 函数体
}

你看上面看起来多乱啊。最好全部分开来写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace Lib;

class Name
{
public function __construct()
{
echo __NAMESPACE__ . "<br>";
}

public static function test()
{
echo __NAMESPACE__ . ' static function test <br>';
}
}

修改ini:

1
ini_set('error_reporting', E_ALL);

require 文件:

1
2
3
require DIR . '/loading.php';

spl_autoload_register("\\AutoLoading\\loading::autoload");

你看是不是整齐好看多了。当然这个是很难约束的。自己仔细划分。

第4条

第4条是约束namespace的,前面已经说过,不多说。值得说的是名字要是驼峰方式来

第5条

类名用大驼峰:

1
2
3
class UserInfo
{
}

第6条

是规定类中的常量名(const)声明必须要全部大写,如果有多个单词,就用_分开:

1
2
3
4
5
6
7
8
9
10
11
12
13
class UserInfo
{
// 全部大写
const NAME = 'phper';

// 用_隔开
const HOUSE_INFO = '已经深圳买房';

public function getUserName()
{
//
}
}​

第7条

方法名用小驼峰:

1
2
3
4
5
6
7
class UserInfo
{
public function getUserName()
{
//
}
}

PSR-2 规范

PSR-2 规范的官网链接在此:PSR-2 这一规范主要是约束代码风格的,可是说是所有里面最关键最重要的,也是需要好好规范和共同遵守的。

我们一个个来看下,只能我大略的写一些比较重要的,或者说平时用的最多的。

1、源文件

  1. 文件末尾必须空一行。
  2. 必须使用Unix LF(换行)作为行结束符。
  3. 纯PHP代码源文件的关闭标签?>必须省略。 第3点其实是蛮重要的,我之前还老写闭合,现在不写了。这可以避免在 PHP 结束标记之后万一意外加入了空格或者换行符,会导致 PHP 开始输出这些空白,而脚本中此时并无输出的意图。

2、缩进

必须使用4个空格来缩进,不能使用Tab键。当然你如果把Tab在编辑器里手动设置为4个空格也可以。这样的目的是因为:每个人的机器上的Tab键都不一样,有些是4个空格,有些是8个空格,在你的机器上看着很爽的代码,在别人机器上了就各种恶心了。所以,统一搞成4个空格,不管在哪里打开都是美观的。

3、行

一行推荐的是最多写80个字符,多于这个字符就应该换行了,一般的编辑器是可以设置的。

4、关键字和 True/False/Null

php的关键字,必须小写,boolean值:truefalsenull 也必须小写

下面是php的keyword,必须小写。

'__halt_compiler', 'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface', 'isset', 'list', 'namespace', 'new', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once', 'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor'

5、命名空间(Namespace)和导入(Use)声明

先简单文字描述下:

  1. 命名空间(namespace)的声明后面必须有一行空行。
  2. 所有的导入(use)声明必须放在命名空间(namespace)声明的下面。
  3. 一句声明中,必须只有一个导入(use)关键字。
  4. 在导入(use)声明代码块后面必须有一行空行。 用代码来说明下:
    1
    2
    3
    4
    5
    6
    <?php
    namespace Lib\Databases; // 下面必须空格一行

    class Mysql
    {
    }

namespace下空一行,才能使用use,再空一行,才能声明class

1
2
3
4
5
6
7
8
9
10
<?php
namespace Lib\Databases; // 下面必须空格一行

use FooInterface; // use 必须在namespace 后面声明
use BarClass as Bar;
use OtherVendor\OtherPackage\BazClass; // 下面必须空格一行

class Mysql
{
}

6、类(class),属性(property)和方法(method)

(1)、继承(extends) 和实现(implement) 必须和 class name 写在一行,切花括号要换行写。

1
2
3
4
5
6
7
<?php
namespace Lib\Databaes;

class Mysql extends ParentClass implements \PDO, \DB // 写一行
{ // 换行写{

}

(2)、属性(property)必须声明其可见性,到底是 public 还是 protected 还是 private,不能省略,也不能使用var, var是php老版本中的什么方式,等用于public。

1
2
3
4
5
6
7
8
9
<?php
namespace Lib\Databaes;

class Mysql extends ParentClass implements \PDO, \DB // 写一行
{
public $foo = null;
private $name = 'yangyi';
protected $age = '17';
}

(3)、方法(method),必须 声明其可见性,到底是 public 还是 protected 还是 private,不能省略。并且,花括号{必须换行写。如果有多个参数,第一个参数后紧接, ,再加个空格,且函数name和( 之间必须要有个空格:function_name ($par, $par2, $pa3), 如果参数有默认值,也要用左右空格分开。

1
2
3
4
5
6
7
8
9
<?php
namespace Lib\Databaes;

class Mysql extends ParentClass implements \PDO, \DB // 写一行
{
public getInfo ($name, $age, $gender = 1) // 函数名getInfo和(之间有个空格,参数之间也要有空格。默认参数也要左右都有空格
{ // 必须换行写 {
}
}

(4)、当用到抽象(abstract)和终结(final)来做类声明时,它们必须放在可见性声明 (public 还是protected还是private)的前面。而当用到静态(static)来做类声明时,则必须放在可见性声明的后面。

直接上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
namespace Vendor\Package;

abstract class ClassName
{
protected static $foo; // static放后面

abstract protected function zim(); // abstract放前面

final public static function bar() // final放前面,static放最后。
{
// 方法主体部分
}
}

7、控制结构

控制接口,就是 if else while switch等。这一类的写法规范也是经常容易出现问题的,也要规范一下。

(1)、if,elseif,else写法,直接上规范代码吧:

1
2
3
4
5
6
7
8
<?php
if ($expr1) { // 左右空格
// if body
} elseif ($expr2) { // elesif 连着写
// elseif body
} else {
// else body;
}

(2)、switch,case 注意左右空格和换行,还是直接上规范代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
switch ($expr) { // 左右空格
case 0:
echo 'First case, with a break'; // 对齐
break; // 换行写break,也对齐。
case 1:
echo 'Second case, which falls through';
// no break
case 2:
case 3:
case 4:
echo 'Third case, return instead of break';
return;
default:
echo 'Default case';
break;
}

(3)、while,do while 的写法也是类似,要左右空格,上代码:

1
2
3
4
5
6
7
8
<?php
while ($expr) { // 左右空格
// structure body
}

do {
// structure body; // 左右空格
} while ($expr);

(4)、for的写法

1
2
3
4
<?php
for ($i = 0; $i < 10; $i++) { // 注意几个参数之间的空格
// for body
}

(5)、foreach的写法

1
2
3
4
<?php
foreach ($iterable as $key => $value) { // 还是空格问题
// foreach body
}

(6)、try catch的写法

1
2
3
4
5
6
7
8
<?php
try {
// try body
} catch (FirstExceptionType $e) { // 同样也是注意空格。
// catch body
} catch (OtherExceptionType $e) {
// catch body
}

基本用到的就是这些了,其他什么闭包啥的用的不多就不过多的累述了。

PSR-3 规范

PSR-3规范主要是来规范日志接口(Logger Interface)的,老实讲,其实平常接触的不是特别多,所以就不说了,可以去看官网的PSR-3

PSR-4 规范

PSR-4规范是刚出没多久的一条新的规范,它也是规范 自动加载(autoload)的,是对PSR-0的修改,属于补充规范,

我简单说下,主要是以下几点:

  1. 废除了PSR-0中_就是目录分割符的写法,_下划线在完全限定类名中是没有特殊含义了。
  2. 类文件名要以 .php 结尾。
  3. 类名必须要和对应的文件名要一模一样,大小写也要一模一样。

参考: