

原文地址:https://steemit.com/eos/@dan/eos-developer-log-stardate-201707-7
这周我们取得了两个重大突破:提炼了EOS的架构,定义了开发者API。具体地说,我们定义了一个编程模型,这个模型提供了并行处理能力,并且使代码更容易使用也更清晰。
更新示例合约
关注我们github的人可能已经注意到,我们开始整合一些示例合约,用这些示例合约来测试我们的架构,同时保证我们能覆盖到我们想要的用例。
今天的一个简单的货币合约大概是这样的:
* Transfer requires that the sender and receiver be the first two
* accounts notified and that the sender has provided authorization.
*/
struct Transfer {
AccountName from;
AccountName to;
uint64_t amount = 0;
char memo[]; /// extra bytes are treated as a memo and ignored by logic
};
struct CurrencyAccount {
CurrencyAccount( uint64_t b = 0 ):balance(b){}
uint64_t balance = 0;
/** used as a hint to Db::store to tell it which table name within the current
* scope to use. Data is stored in tables under a structure like
*
* scope/code/table/key->value
*
* In this case the "singleton" table is designed for constant named keys that
* refer to a unique object type. User account balances are stored here:
*
* username/currency/singleton/account -> CurrencyAccount
*/
static Name tableId() { return NAME("singleton"); }
};
void apply_currency_transfer() {
const auto& transfer = currentMessage<Transfer>();
/** will call apply_currency_transfer() method in code defined by transfer.to and transfer.from */
requireNotice( transfer.to, transfer.from );
requireAuth( transfer.from );
static CurrencyAccount from_account;
static CurrencyAccount to_account;
Db::get( transfer.from, NAME("account"), from_account );
Db::get( transfer.to, NAME("account"), to_account );
assert( from_account.balance >= transfer.amount, "insufficient funds" );
from_account.balance -= transfer.amount;
to_account.balance += transfer.amount;
if( from_account.balance == 0 )
Db::remove<CurrencyAccount>( transfer.from, NAME("account") );
else
Db::store( transfer.from, NAME("account"), from_account );
Db::store( transfer.to, NAME("account"), to_account );
}
这个货币合约有几个值得注意的方面:
1 它看起来像是普通的时序代码
2 但是它能并行地在两对用户间转账
这意味着什么呢?这意味着当alice给bob转账的同时,sam也可以给jill转账。这个货币合约的性能不再受限与单线程的性能。而单线程性能是当前货币合约的主要束缚。
开始交易所合约
我们也实现了一个简单的交易所合约,可以从两个不同的货币合约中存款和取款。
uint64_t a = 0;
uint64_t b = 0;
int open_orders = 0;
bool isEmpty()const { return !(a|b|open_orders); }
/**
* Balance records for all exchange users are stored here
* exchange/exchange/balance/username -> Balance
*/
static Name tableId() { return Name("balance"); }
};
/**
* This method is called after the "transfer" action of code
* "currencya" is called and "exchange" is listed in the notifiers.
*/
void apply_currencya_transfer() {
const auto& transfer = currentMessage<Transfer>();
if( transfer.to == "exchange" ) {
static Balance to_balance;
Db::get( transfer.from, to_balance );
to_balance.a += transfer.amount;
Db::store( transfer.from, to_balance );
} else if( transfer.from == "exchange" ) {
requireAuth( transfer.to ); /// require the reciever of funds (account owner) to authorize this transfer
static Balance to_balance;
auto balance = Db::get( transfer.to, to_balance );
assert( balance.a >= transfer.amount, "insufficient funds to withdraw" );
balance.a -= transfer.amount;
if( balance.isEmpty() )
Db::remove<Balance>( transfer.to );
else
Db::store( transfer.to, to_balance );
} else {
assert( false, "notified on transfer that is not relevant to this exchange" );
}
}
/**
* This method is called after the "transfer" action of code
* "currencya" is called and "exchange" is listed in the notifiers.
*/
void apply_currencyb_transfer() {
const auto& transfer = currentMessage<Transfer>();
if( transfer.to == "exchange" ) {
static Balance to_balance;
Db::get( transfer.from, to_balance );
to_balance.b += transfer.amount;
Db::store( transfer.from, to_balance );
} else if( transfer.from == "exchange" ) {
requireAuth( transfer.to ); /// require the reciever of funds (account owner) to authorize this transfer
static Balance to_balance;
auto balance = Db::get( transfer.to, to_balance );
assert( balance.b >= transfer.amount, "insufficient funds to withdraw" );
balance.b -= transfer.amount;
if( balance.isEmpty() )
Db::remove<Balance>( transfer.to );
else
Db::store( transfer.to, to_balance );
} else {
assert( false, "notified on transfer that is not relevant to this exchange" );
}
}
这个实现中有意思的一点是,存款和取款发生后不需要异步回调,或者其他的复杂的挂起。
与其让用户叫交易所通过货币合约去提取资金,不如让交易所批准每个人都能从交易所转账,只需要加上说明:交易所处理转账既包括存款也包括取款。如果一个用户通过交易所合约提款,但是账上却不够钱,那么交易所合约处理器将会拒绝此次转账请求。
交易所合约存款和取款这一部分,我们还没怎么实现工作测试,但是这已经安排到下周的工作日程中了。我们还会实现一个基础的社交媒体应用,以此证明我们覆盖了所有存在的用例。
同步调用
本周在架构方面最大的进展就是,允许紧密相连的应用间可以同步调用,同时保留了并行处理的好处。以后会发blog对内存和并行执行架构进行详细介绍。
存储成本
有些人表达过一种担忧:如果代币市值达到300亿美金时,而存储能力却只有1TB的话,那么存储的成本将会非常高。我已经准备了一篇文章,在这篇文章中我会解释我们怎么处理这个问题,把存储的成本从代币价格上独立出来。
Eos.io 的开发取得了重大突破。