npm i -g create-elm-app
您正在查看: Surou 发布的文章
'elm-app' is not recognized as an internal or external command
'elm-install' is not recognized as an internal or external command
npm:
npm install elm-github-install -g
If you are experiencing EACCES: permission denied errors during installation using NPM then you can try:
sudo npm i -g elm-github-install --unsafe-perm=true --allow-root
EOS智能合约产生随机数
先基本记录下,稍后整理,测试,总结
1. How can I generate random numbers inside a smart contract?
if( !is_zero(prev_reveal.reveal) ) {
checksum256 result;
sha256( (char *)&game_itr->player1, sizeof(player)*2, &result);
auto prev_revealer_offer = idx.find( offer::get_commitment(prev_reveal.commitment) );
int winner = result.hash[1] < result.hash[0] ? 0 : 1;
if( winner ) {
pay_and_clean(*game_itr, *curr_revealer_offer, *prev_revealer_offer);
} else {
pay_and_clean(*game_itr, *prev_revealer_offer, *curr_revealer_offer);
}
}
2. EOSDACRandom
#include "eosdacrandom.hpp"
#include <eosiolib/system.h>
#include <eosiolib/stdlib.hpp>
#include <eosiolib/action.hpp>
#include <eosiolib/symbol.hpp>
#include "../eosdactoken/eosdactoken.hpp"
using namespace eosio;
eosdacrandom::eosdacrandom(account_name name)
: contract(name),
_seeds(_self, name),
_geters(_self, name)
{
}
eosdacrandom::~eosdacrandom()
{
}
void eosdacrandom::setsize(uint64_t size)
{
require_auth(_self);
seedconfig_table config(_self, _self);
auto existing = config.find(_self);
if (existing != config.end()) {
if (existing->hash_count == existing->target_size) {
if (existing->hash_count != existing->seed_match) {
eosio_assert(false, "do not set size during sendseed period");
}
}
config.modify(existing, _self, [&](auto& c){
c.target_size = size;
});
} else {
config.emplace(_self, [&](auto& c){
c.owner = _self;
c.target_size = size;
});
}
}
void eosdacrandom::sendseed(name owner, int64_t seed, string sym)
{
eosio_assert(is_account(owner), "Invalid account");
symbol_type symbol(string_to_symbol(4, sym.c_str()));
eosio::asset fromBalance = eosdactoken(N(eosdactoken)).get_balance(owner, symbol.name());
eosio_assert(fromBalance.amount > 0, "account has not enough OCT to do it");
eosio::asset selfBalance = eosdactoken(N(eosdactoken)).get_balance(_self, symbol.name());
eosio_assert(selfBalance.amount > 0, "contract account has not enough OCT to do it");
require_auth(owner);
seedconfig_table config(_self, _self);
auto existing = config.find(_self);
eosio_assert(existing != config.end(), "target size must set first");
const auto& cfg = *existing;
const auto& sd = _seeds.find(owner);
if (cfg.hash_count < cfg.target_size) {
if (sd != _seeds.end()) {
_seeds.erase(sd);
config.modify(cfg, _self, [&](auto& c){
c.hash_count --;
});
}
eosio_assert(false, "hash size not fulled");
}
string h = cal_sha256_str(seed);
eosio_assert(sd->seed != seed, "you have already send seed");
if (sd->hash != h) {
//SEND_INLINE_ACTION( eosdacvote, vote, {_self,N(active)}, {_self, owner, selfBalance, false} );
for (auto itr = _seeds.cbegin(); itr != _seeds.cend(); ) {
itr = _seeds.erase(itr);
}
config.modify(cfg, _self, [&](auto& c){
c.hash_count = 0;
});
return;
}
_seeds.modify(sd, _self, [&](auto& a){
a.seed = seed;
});
config.modify(cfg, _self, [&](auto& c){
c.seed_match = c.seed_match + 1;
print(c.seed_match);
});
// if all seeds match
if (seedsmatch()) {
dispatch_request(owner);
}
}
void eosdacrandom::sendhash(name owner, string hash, string sym)
{
eosio_assert(is_account(owner), "Invalid account");
seedconfig_table config(_self, _self);
auto existing = config.find(_self);
eosio_assert(existing != config.end(), "target size must set first");
const auto& cfg = *existing;
eosio_assert(cfg.hash_count < cfg.target_size, "seeds is full");
symbol_type symbol(string_to_symbol(4, sym.c_str()));
eosio::asset fromBalance = eosdactoken(N(eosdactoken)).get_balance(owner, symbol.name());
eosio_assert(fromBalance.amount > 0, "account has not enough OCT to do it");
require_auth(owner);
auto s = _seeds.find(owner);
if (s == _seeds.end()) {
_seeds.emplace(_self, [&](auto& a){
a.owner = owner;
a.hash = hash;
});
config.modify(cfg, _self, [&](auto& c){
c.hash_count++;
});
} else {
_seeds.modify(s, _self, [&](auto& a){
a.hash = hash;
});
}
}
void eosdacrandom::regrequest(name owner, uint64_t index)
{
eosio_assert(is_account(owner), "Invalid account");
uint64_t cur = current_time();
auto it = _geters.find(owner);
request_info req {index, cur};
if (it == _geters.end()) {
_geters.emplace(_self, [&](auto& a){
a.owner = owner;
a.requestinfo.push_back(req);
});
} else {
_geters.modify(it, _self, [&](auto& a){
bool same_idx = false;
for (auto ri = a.requestinfo.begin(); ri != a.requestinfo.end(); ++ri) {
if (ri->index == index) { // if index equals former index.
*ri = req;
same_idx = true;
break;
}
}
if (!same_idx) {
a.requestinfo.push_back(req);
}
});
}
}
int64_t eosdacrandom::random()
{
// use _seeds to generate random number
seedconfig_table config(_self, _self);
auto existing = config.find(_self);
eosio_assert(existing != config.end(), "target size must set first");
eosio_assert(existing->hash_count == existing->target_size, "seed is not full");
// how to generate random number?
int64_t seed = 0;
for (auto it = _seeds.cbegin(); it != _seeds.cend();) {
seed += it->seed;
it = _seeds.erase(it);
}
config.modify(existing, _self, [&](auto& c){
c.hash_count = 0;
c.seed_match = 0;
});
checksum256 cs = cal_sha256(seed);
return (((int64_t)cs.hash[0] << 56 ) & 0xFF00000000000000U)
| (((int64_t)cs.hash[1] << 48 ) & 0x00FF000000000000U)
| (((int64_t)cs.hash[2] << 40 ) & 0x0000FF0000000000U)
| (((int64_t)cs.hash[3] << 32 ) & 0x000000FF00000000U)
| ((cs.hash[4] << 24 ) & 0x00000000FF000000U)
| ((cs.hash[5] << 16 ) & 0x0000000000FF0000U)
| ((cs.hash[6] << 8 ) & 0x000000000000FF00U)
| (cs.hash[7] & 0x00000000000000FFU);
}
bool eosdacrandom::seedsmatch()
{
seedconfig_table config(_self, _self);
auto existing = config.find(_self);
eosio_assert(existing != config.end(), "target size must set first");
const auto& cfg = *existing;
if (cfg.hash_count != cfg.target_size) {
return false;
}
if (cfg.hash_count == cfg.seed_match) {
return true;
}
return false;
}
checksum256 eosdacrandom::cal_sha256(int64_t word)
{
checksum256 cs = { 0 };
char d[255] = { 0 };
snprintf(d, sizeof(d) - 1, "%lld", word);
sha256(d, strlen(d), &cs);
return cs;
}
string eosdacrandom::cal_sha256_str(int64_t word)
{
string h;
checksum256 cs = cal_sha256(word);
for (int i = 0; i < sizeof(cs.hash); ++i) {
char hex[3] = { 0 };
snprintf(hex, sizeof(hex), "%02x", static_cast<unsigned char>(cs.hash[i]));
h += hex;
}
return h;
}
void eosdacrandom::dispatch_request(name owner)
{
print("all seeds matched.");
uint64_t cur = current_time();
int64_t num = random();
static int expiraion = 3000; // ms
std::vector<std::vector<request_info>> reqs;
for (auto i = _geters.cbegin(); i != _geters.cend();) {
std:vector<request_info> tmp(i->requestinfo);
for (auto j = tmp.begin(); j != tmp.end();) {
if (cur - j->timestamp >= expiraion) {
dispatch_inline(i->owner, string_to_name("getrandom"),
{permission_level(_self, N(active))},
std::make_tuple(j->index, num));
j = tmp.erase(j);
} else {
++j;
}
}
if (tmp.size()) {
reqs.push_back(tmp);
}
i = _geters.erase(i);
}
if (reqs.size()) {
for (auto r = reqs.cbegin(); r != reqs.cend(); ++r) {
_geters.emplace(_self, [&](auto& a){
a.owner = owner;
a.requestinfo = *r;
});
}
}
}
EOSIO_ABI( eosdacrandom, (setsize) (sendseed) (sendhash) (regrequest) )
3. eoscraper
#include "scraper.hpp"
#include <set>
#include <map>
#include <vector>
#include "Proof.hh"
#include "Ecc.hh"
//count of participants for random generation (min 4)
constexpr static uint8_t participant_cnt = 10;
static const UInt256 seed_for_g = fromString("21343453542133456453212");
static const UInt256 seed_for_m = fromString("56987654354236234435425");
static const Point base_point { Secp256k1, Secp256k1.G.x, Secp256k1.G.y };
static const Point gen_g = base_point.scalarMult(seed_for_g);
static const Point gen_m = base_point.scalarMult(seed_for_m);
struct binuint256_t {
checksum256 data;
};
struct binpoint {
binuint256_t x, y;
};
struct binproof {
binpoint g,m,h,z,a,b;
binuint256_t c, r;
};
UInt256 fromBin(binuint256_t const & data) {
UInt256 x;
memcpy(x.data, data.data.hash, sizeof(data.data));
return std::move(x);
}
Point fromBin(binpoint const &data) {
Point point {Secp256k1, fromBin(data.x), fromBin(data.y)};
eosio_assert(point.isOnCurve(), "Point not in curve");
return std::move(point);
}
Proof fromBin(binproof const &data) {
return {
fromBin(data.g), fromBin(data.m),
fromBin(data.h), fromBin(data.z),
fromBin(data.a), fromBin(data.b),
fromBin(data.c), fromBin(data.r)
};
}
// @abi table
struct encshare {
uint64_t id;
account_name from;
account_name to;
binpoint data;
binpoint commitment;
binproof proof;
uint64_t dec_id;
auto primary_key() const { return id; }
EOSLIB_SERIALIZE(encshare, (id)(from)(to)(data)(commitment)(proof)(dec_id));
};
// @abi table
struct decshare {
uint64_t id;
binpoint s;
binproof proof;
auto primary_key() const { return id; }
EOSLIB_SERIALIZE(decshare, (id)(s)(proof));
};
// @abi table
struct random {
enum state : uint8_t {
wait_joins = 0,
wait_enc_shares,
wait_dec_shares,
done,
error,
};
uint64_t id;
uint8_t state;
uint8_t joined_cnt;
std::vector<account_name> participants;
uint32_t pushed_cnt;
std::vector<uint64_t> enc_ids;
std::vector<uint8_t> dec_cnts;
auto primary_key()const { return id; }
EOSLIB_SERIALIZE(random, (id)(state)(participants)(enc_ids)(dec_cnts));
};
// @abi table
struct account {
account_name owner;
binpoint pubkey;
auto primary_key()const { return owner; }
EOSLIB_SERIALIZE(account, (owner)(pubkey));
};
class scraper : public eosio::contract {
public:
scraper( account_name self ) :
contract(self),
_accounts(_self, _self),
_randoms( _self, _self),
_encshares(_self, _self),
_decshares(_self, _self)
{ }
// @abi action
void bindkey(account_name sender, binpoint pubkey) {
require_auth(sender);
auto acc = _accounts.find(sender);
if (acc != _accounts.end())
_accounts.modify(acc, sender, [&] (auto & acc) {
acc.pubkey = pubkey;
});
else
_accounts.emplace(sender, [&](auto & acc) {
acc.owner = sender;
acc.pubkey = pubkey;
});
}
// @abi action
void initrand(account_name sender) {
require_auth(sender);
auto acc = _accounts.find(sender);
eosio_assert(acc != _accounts.end(), "Need to bind public key");
_randoms.emplace(sender, [&](auto & rand) {
rand.id = _randoms.available_primary_key();
rand.state = random::state::wait_joins;
rand.participants.reserve(participant_cnt);
rand.enc_ids.reserve(participant_cnt*participant_cnt);
rand.dec_cnts.reserve(participant_cnt);
rand.participants[0] = sender;
rand.joined_cnt = 1;
rand.pushed_cnt = 0;
for(auto k = 0; k < participant_cnt * participant_cnt; ++k)
rand.enc_ids[k] = -1;
});
}
// @abi action
void joinrand(uint64_t rand_id, account_name sender) {
require_auth(sender);
auto acc = _accounts.find(sender);
eosio_assert(acc != _accounts.end(), "Need to bind public key");
auto rand_it = _randoms.find(rand_id);
eosio_assert(rand_it != _randoms.end(), "Rand not found");
eosio_assert(participantId(*rand_it, sender) != -1, "Already joinded");
eosio_assert(rand_it->state == random::state::wait_joins, "Invalid state");
_randoms.modify(rand_it, sender, [&](auto & rand) {
rand.participants[rand.joined_cnt++] = sender;
if (rand.joined_cnt == participant_cnt)
rand.state = random::state::wait_enc_shares;
});
}
// @abi action
void pushencshare(uint64_t rand_id, account_name sender, account_name receiver,
binpoint data, binpoint commitment, binproof proof)
{
require_auth(sender);
auto senderAccIt = _accounts.find(sender);
eosio_assert(senderAccIt != _accounts.end(), "Sender not found");
auto receiverAccIt = _accounts.find(receiver);
eosio_assert(receiverAccIt != _accounts.end(), "Receiver not found");
auto rand_it = _randoms.find(rand_id);
eosio_assert(rand_it != _randoms.end(), "Rand not found");
auto senderPartId = participantId(*rand_it, sender);
eosio_assert(senderPartId != -1, "Sender is not participant");
auto receiverPartId = participantId(*rand_it, receiver);
eosio_assert(receiverPartId != -1, "Receiver is not participant");
eosio_assert(rand_it->enc_ids[(uint32_t)senderPartId * participant_cnt + receiverPartId] == -1, "share already pushed");
auto pk = fromBin(receiverAccIt->pubkey);
auto pr = fromBin(proof);
eosio_assert(gen_g == pr.g, "Invalid proof (gen_g != g)");
eosio_assert(pk == pr.m, "Invalid proof (pk != m)");
eosio_assert(pr.verify(), "Proof validate failed");
uint64_t new_share_id;
_encshares.emplace(sender, [&](auto & share) {
new_share_id = _encshares.available_primary_key();
share.id = new_share_id;
share.from = sender;
share.to = receiver;
share.data = data;
share.commitment = commitment;
share.proof = proof;
share.dec_id = (uint64_t)-1;
});
_randoms.modify(rand_it, sender, [&](auto & rand) {
rand.enc_ids[(uint32_t)senderPartId * participant_cnt + receiverPartId] = new_share_id;
rand.pushed_cnt++;
if (rand.pushed_cnt == (uint32_t)participant_cnt * participant_cnt)
rand.state = random::state::wait_dec_shares;
});
}
// @abi action
void pushdecshare(uint64_t rand_id, account_name sender, account_name from,
binpoint s, binproof proof)
{
require_auth(sender);
auto senderAccIt = _accounts.find(sender);
eosio_assert(senderAccIt != _accounts.end(), "Sender not found");
auto fromAccIt = _accounts.find(from);
eosio_assert(fromAccIt != _accounts.end(), "From not found");
auto rand_it = _randoms.find(rand_id);
eosio_assert(rand_it != _randoms.end(), "Rand not found");
eosio_assert(rand_it->state == random::state::wait_dec_shares, "Invalid state");
auto senderPartId = participantId(*rand_it, from);
eosio_assert(senderPartId != -1, "Sender is not participant");
auto receiverPartId = participantId(*rand_it, sender);
eosio_assert(receiverPartId != -1, "Receiver is not participant");
auto enc_id = rand_it->enc_ids[(uint32_t)senderPartId * participant_cnt + receiverPartId];
auto encshare_it = _encshares.find(enc_id);
eosio_assert(encshare_it != _encshares.end(), "Share not found");
eosio_assert(encshare_it->dec_id == -1, "Already pushed");
auto encdata = fromBin(encshare_it->data);
auto pk = fromBin(senderAccIt->pubkey);
auto ss = fromBin(s);
auto pr = fromBin(proof);
eosio_assert(gen_g == pr.g, "Invalid proof (gen_g != g)");
eosio_assert(encdata == pr.z, "Invalid proof (encdata != g)");
eosio_assert(ss == pr.m, "Invalid proof (m != s)");
eosio_assert(pk == pr.h, "Invalid proof (pk != h)");
eosio_assert(pr.verify(), "Proof validate failed");
uint64_t new_dec_id;
_decshares.emplace(sender, [&](auto & obj) {
new_dec_id = _decshares.available_primary_key();
obj.id = new_dec_id;
obj.s = s;
obj.proof = proof;
});
_encshares.modify(encshare_it, sender, [&](auto & obj) {
obj.dec_id = new_dec_id;
});
_randoms.modify(rand_it, sender, [&](auto & rand) {
rand.dec_cnts[from]++;
});
}
private:
eosio::multi_index<N(accounts), account> _accounts;
eosio::multi_index<N(randoms), random> _randoms;
eosio::multi_index<N(encshare), encshare> _encshares;
eosio::multi_index<N(decshare), decshare> _decshares;
private:
uint8_t participantId(random const & obj, account_name acc) {
for (uint8_t i = 0; i < participant_cnt; ++i)
if (obj.participants[i] == acc)
return i;
return -1;
}
};
EOSIO_ABI( scraper, (bindkey)(initrand)(joinrand)(pushencshare)(pushdecshare))
最新文章
跨链桥跨链过程中数据变化polygon cdk aggregator 报execution reverted (0x09bde339)polygon cdk Aggregator使用SequencerPrivateKey的时机polygon da 判断DA服务是否正常polygon cdk sequence sender 发送 sequenceBatchesValidium的时机polygon cdk 查看最新提交L1batch numCDK 部署或重置后第一笔交易error: latest Synced BlockNumber (7089137) is higher than the latest Proposed block (1008) in the networkpolygon cdk 跨链桥交易处理流程分析因RPC限速导致sequence-sender异常退出
最新回复
fzd: 请问这个解决了吗
StarkWare explained: layer 2 solution provider of dYdX and iMMUTABLE R11; BitKeep News: [...]Layer 2: https://...
一文读懂 StarkWare:dYdX 和 Immutable 背后的 L2 方案 R11; BitKeep 博客: [...]Layer 2:Comparing Laye...
http://andere.strikingly.com/: Regards, Great stuff!
surou: 需要先执行提案合约申请,等待出块节点地址同意后,才会进...
heco: WARN [11-19|11:26:09.459] N...
P: 你好,我在heco链上遇到了“tx fee excee...
Peng: 楼主安装成功了吗?我正在同步区块链,一天了,差不多才同...
joyhu: 你好,请问下安装好之后如何获取到bee.yaml配置文...
kaka: 支票最终怎么提币呢?
归档
November 2024October 2024September 2024August 2024July 2024June 2024May 2024April 2024March 2024January 2024December 2023November 2023October 2023September 2023August 2023July 2023June 2023April 2023March 2023February 2023January 2023December 2022November 2022October 2022August 2022July 2022June 2022May 2022March 2022February 2022January 2022December 2021November 2021October 2021September 2021August 2021July 2021June 2021May 2021April 2021March 2021February 2021January 2021December 2020November 2020October 2020September 2020July 2020June 2020May 2020April 2020March 2020February 2020January 2020December 2019November 2019October 2019September 2019August 2019July 2019June 2019May 2019April 2019March 2019February 2019January 2019December 2018November 2018October 2018September 2018August 2018July 2018June 2018