2018年终总结

2018年的年度总结最让我纠结,这一年几乎什么正经事都没做成。

这年去了两次日本,参加了东山1st武道馆和Pyxis的演唱会,去了偶活5th,各种拼盘包括BML和KSL也得以让我有缘见到许许多多的偶像声优。去年还让我心疼不已的石原夏织,今年也成功举办了1st LIVE,可以说各方面都没什么遗憾了。今年还复出了三次着ぐるみ,一次WF和两次CP。去歌魂、纯k也数不胜数,也因为雀魂终于开始日麻了。在娱乐上,我觉得已经到了极致。

由于冲动,年初不得已辞了工作去了杭州,跟闪总搞区块链。本以为能在杭州有所发展的我,却不停地在上海和杭州之间奔波,原因竟然是去看LIVE。在年末区块链大跌的趋势下,我还是最终离开了杭州。杭州虽好,但不适合我。一年换了两次工作,虽然数量和2017年一样,但性质却完全不同:从郑州到上海是升级,从上海到杭州确是降级了。但实际上这四次换工作,也是一种历史的小轮回。

这年我给一汉字——,意为露气、大水,用它的原因仅仅是“沪”“杭”二字的结合而已,但看来我这稍微出头的露气,却不得不卷在历史的大水里了。

日历

  1. 1月3日。浅水湾。
    • 2018柏木由纪上海Live
  2. 1月20日。静安新体育中心。
    • ラブライブ!サンシャイン!! Aqours クラブ活動 LIVE & FAN MEETING 上海公演
  3. 1月21日。天宴秀。
    • [上海]Love Live! Sunshine!! Showtime”企划展”
  4. 2月1日-13日。日本。
    • 东京羽田入。乐桃十连坐。SKYTREE。
    • 北海道。有珠山、洞爷湖。东北新干线。
    • 大阪关西出。
  5. 2月3日。东京。ディファ有明。伊藤美来丰田萌绘
    • Pyxis Live 2018 “Pyxis Party” ~Pop-up Dream Match~
  6. 2月3日。东京。
    • 東山奈央 1st LIVE at 日本武道館
  7. 2月4日。东京。新宿BLAZE。
    • 伊藤かな恵 LIVE TOUR 2018 “デアエタケシキ”
  8. 2月11日。九州。ハウステンボス ロッテルダム会場。
    • がんばろう!九州 BanG Dream!×ミルキィホームズ×けものフレンズ Huis Ten Bosch Special Live 2018
    • 三森铃子徳井青空尾崎由香爱美伊藤彩沙明坂聪美等。
  9. 2月12日。川崎。カルッツ川崎。
    • i☆Ris&Wake Up,Girls! バレンタインLIVE!!
  10. 2月15日-21日。安阳。过年。
  11. 3月4日。上海长城假日酒店。
    • 浅倉杏美 & 原由実 上海见面会
  12. 3月31日。新国际。暴走YU人节。
  13. 4月6日-7日。新国际。
    • Wonder Festival 2018上海[Pre Stage]。
    • DAY2。天真·珈百璃·怀特
  14. 4月8日。杭。
  15. 4月24日。下杭。
    • 当天入职。
    • 开始定居杭州
  16. 4月27日-29日。杭沪往返。搬家。
  17. 5月5日-6日。杭沪往返。搬家。
  18. 5月19日-20日。沪。国家会展中心。
    • CP22。DAY1。虹野梦
    • 歌魂。
  19. 6月16日。杭州国际博览中心。
    • 萤火虫动漫游戏嘉年华·杭州站01
  20. 6月17日-18日。沪。
    • FRONTIER CHiCO with HoneyWorks×绫野真白×晓月凛 上海演唱会
  21. 7月21日-22日。沪。梅奔。
    • BILIBILI MACRO LINK
    • BILIBILI WORLD 2018
    • 田所梓大桥彩香山崎遥Machico木户衣吹大空直美黑泽朋世爱美等。
  22. 7月28日-29日。沪。
  23. 8月10日-13日。广州。保利世贸。
    • 2018广州麽多动漫嘉年华
    • 山本希望 见面会。
    • 植田佳奈 见面会。
    • 日麻。
  24. 8月26日-27日。沪。静安新体育中心。
    • LiSA “LiVE is Smile Always ~ASiA TOUR 2018~[eN] Shanghai”。
  25. 9月7日-13日。日本。
    • 东京羽田出入。
    • 长野、原村。东日本周游券。
  26. 9月7日。池袋サンシャインシティ噴水広場。
    • Kleissis Chaos」発売記念イベント ミニライブ&特典会
  27. 9月8日-9日。幕張メッセ イベントホール。
    • アイカツ!シリーズ 5thフェスティバル!!
    • 诸星堇下地紫野富田美忧村上奈津実宮本侑芽石原夏织秋奈高田忧希日笠阳子等。
    • STAR☆ANIS、AIKATSU☆STARS!、BEST FRIENDS!
  28. 9月24日。沪。
  29. 10月4日-6日。沪。
    • 日麻。歌魂。
  30. 10月8日。24岁生日。
  31. 10月13日。浅水湾。
    • 铃木このみ Asia Tour 2018 上海
  32. 10月13日-15日。沪。梅奔。
    • KING SUPER LIVE 2018 上海站。
    • 水树奈奈小仓唯上坂堇等。
  33. 10月21日。返沪。
    • 重新定居上海
    • 次日入职。
  34. 10月26日-28日。杭。搬家。
  35. 11月10日。国家会展中心。
    • 首届中国国际进口博览会
  36. 11月18日。浅水湾。
    • May’n中国大陆巡演2018 「音乐包子♡」上海站。
  37. 11月25日。杭。搬家。
  38. 12月15日-16日。新国际。
    • CP23。DAY2。天江衣。雀魂。
  39. 12月31日。
    • DAM-K 跨年活动。

今年计划完成情况

  1. 【完成】完成日本旅行,考察和研究留日计划。
  2. 【完成】尽可能地参加上海本地的见面会和LIVE。
  3. 【一半】读完《绎史》《资治通鉴》《续通鉴》,略读明清民国现代史。
  4. 深扎Web开发,技术方面心无旁骛。
  5. 学习英语,通过托福。
  6. 复习国内文科高考内容。
  7. 学习日本留学生考试内容。
  8. 每周略读一本社会科学类的经典书籍。
  9. 锻炼身体,保证脑力。

明年计划

  1. 定好中年奋斗目标。
  2. 参加至少一场考试。
  3. 读书。
  4. 存钱。
  5. 锻炼身体。
  6. 办下日本三年签证。

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()风格来声明。