操作系統(tǒng):MAC OS 10.13.x荔燎,EOSIO版本:1.1.3
在EOS側(cè)鏈的開發(fā)過程中捕犬,必然需要側(cè)鏈與主鏈之間的通訊米死。請先看我們的系列文章:EOS跨鏈轉(zhuǎn)賬 - 簡書具垫。
1.過程
在“EOS跨鏈轉(zhuǎn)賬”中欺冀,主鏈的同步節(jié)點(同步鏈)在確認(rèn)賬戶A到合約賬號M的轉(zhuǎn)賬不可撤銷后,通過http向測鏈節(jié)點發(fā)送一個action萨脑。
void send_transaction(const block_state_ptr& irb) {
auto& chain = chain_plug->chain();
auto& db = chain.db();
const auto& trmi = db.get_index<transaction_reversible_multi_index, by_block_num>();
auto itr = trmi.begin();
while( itr != trmi.end()) {
if (itr->block_num <= irb->block_num) {
auto data = fc::raw::unpack<cactus_transfer>(itr->data);
// need to validate ?
// send propose or approve
string datastr = DATA_FORMAT(_peer_chain_account, string(itr->trx_id), string(data.to), data.quantity.to_string());
vector<string> permissions = {_peer_chain_account};
try {
app().find_plugin<client_plugin>()->get_client_apis().push_action(_peer_chain_address, _peer_chain_constract,"msigtrans", datastr, permissions);
} catch (...) {
wlog("send transaction failed");
}
// remove or move to other table ?
db.remove(*itr);
}
++ itr;
}
}
上述send_transaction
中隐轩,app().find_plugin()->get_client_apis().push_action(_peer_chain_address, _peer_chain_constract, "msigtrans", datastr, permissions);
即為client_plugin提供的push_action方法。入?yún)⑴cEOSIO的命令行cleos push action account action data
類似渤早,增加了一個url职车,此url為側(cè)鏈上的一個節(jié)點地址如:http://192.168.31.91:8888。
2.實現(xiàn)
為了實現(xiàn)主鏈同步節(jié)點在同步過程中向側(cè)鏈查詢或者發(fā)送交易的功能鹊杖,我們寫了一個client_plugin悴灵,專門負(fù)責(zé)處理發(fā)送http請求。
client_plugin中push_action與EOSIO中的program/cleos/main 的push_action類似骂蓖,這為后續(xù)擴展其他查詢/http請求提供方便积瞒。具體代碼如下
void client_cactus::push_action(const std::string& url, string contract_account, string action, string data, const vector<string>& tx_permission ){
fc::variant action_args_var;
if( !data.empty() ) {
try {
action_args_var = json_from_file_or_string(data, fc::json::relaxed_parser);
} EOS_RETHROW_EXCEPTIONS(action_type_exception, "Fail to parse action JSON data='${data}'", ("data", data))
}
auto arg= fc::mutable_variant_object
("code", contract_account)
("action", action)
("args", action_args_var);
auto result = call(url, json_to_bin_func, arg);
auto accountPermissions = get_account_permissions(tx_permission);
send_actions(url, {eosio::chain::action{accountPermissions, contract_account, action, result.get_object()["binargs"].as<bytes>()}});
}
void client_cactus::send_actions(const std::string& url, std::vector<chain::action>&& actions, int32_t extra_kcpu, packed_transaction::compression_type compression) {
auto result = push_actions( url, move(actions), extra_kcpu, compression);
std::cout << fc::json::to_pretty_string( result ) << std::endl;
}
fc::variant client_cactus::push_actions(const std::string& url, std::vector<chain::action>&& actions, int32_t extra_kcpu, packed_transaction::compression_type compression) {
signed_transaction trx;
trx.actions = std::forward<decltype(actions)>(actions);
return push_transaction(url, trx, extra_kcpu, compression);
}
fc::variant client_cactus::push_transaction( const std::string& url, signed_transaction& trx, int32_t extra_kcpu, packed_transaction::compression_type compression) {
auto info = get_info(url);
trx.expiration = info.head_block_time + tx_expiration;
// Set tapos, default to last irreversible block
trx.set_reference_block(info.last_irreversible_block_id);
trx.max_cpu_usage_ms = tx_max_net_usage;
trx.max_net_usage_words = (tx_max_net_usage + 7)/8;
sign_transaction_local(trx, client_prikey, info.chain_id);//本地對交易簽名,沒有使用錢包登下!后續(xù)可以使用錢包來對交易簽名
return call(url, push_txn_func, packed_transaction(trx, compression));
}
不使用錢包茫孔,本地簽名實現(xiàn):
chain_id_type& chain_id) {
optional<signature_type> sig = private_key.sign(trx.sig_digest(chain_id, trx.context_free_data));
if (sig) {
trx.signatures.push_back(*sig);
}
}
使用EOSIO的call實現(xiàn)do_http_call( )請求
template<typename T>
fc::variant client_cactus::call( const std::string& url,
const std::string& path,
const T& v ) {
static http_context context = create_http_context();
auto urlpath = parse_url(url) + path;
connection_param *cp = new connection_param(context, urlpath, false);
return do_http_call( *cp, fc::variant(v), false, false );
}
3. 啟動client_plugin
需要配置如下參數(shù):
client-private-key
見證人的私鑰
--client-private-key 5K8MzDTmBKfGWE5wDpTcpmMimHH2SzFADjmSkvJe47RWHv3nbke
具體演示結(jié)果見EOS跨鏈轉(zhuǎn)賬 - 簡書