Skip to content

Commit

Permalink
sortition_contract_tx is getting nearer to functional
Browse files Browse the repository at this point in the history
  • Loading branch information
zack-bitcoin committed Oct 3, 2019
1 parent 3088535 commit 577e17b
Show file tree
Hide file tree
Showing 12 changed files with 201 additions and 63 deletions.
2 changes: 1 addition & 1 deletion apps/amoveo_core/src/consensus/amoveo_sup.erl
Expand Up @@ -64,7 +64,7 @@ init([]) ->
tree_child(governance, 8, 4, 0, Mode, TrieSize),
tree_child(matched, HS, (HS + PS + (3 * BB div 8)), 0, Mode, TrieSize),
tree_child(unmatched, HS, (HS + PS + PS + (BB div 8)), 0, Mode, TrieSize),
tree_child(sortition_chains, HS, 161, 0, Mode, TrieSize),
tree_child(sortition_chains, HS, 195, 0, Mode, TrieSize),
tree_child(sortition_roots, HS, 100, 0, Mode, TrieSize),
tree_child(sortition_spent, HS, 101, 0, Mode, TrieSize)
],
Expand Down
3 changes: 3 additions & 0 deletions apps/amoveo_core/src/consensus/chain/block.erl
Expand Up @@ -1347,6 +1347,9 @@ sum_amounts_helper(sortition_spent, _, _, _, _) ->
sum_amounts_helper(sortition_roots, _, _, _, _) ->
0;
sum_amounts_helper(sortition_chains, SC, Dict, _, _) ->
io:fwrite("block sum_amounts_helper sortition_chains is "),
io:fwrite(packer:pack(SC)),
io:fwrite("\n"),
Closed = SC#sortition_chain.done,
case Closed of
0 -> SC#sortition_chain.amount;
Expand Down
7 changes: 5 additions & 2 deletions apps/amoveo_core/src/consensus/chain/proofs.erl
Expand Up @@ -431,10 +431,13 @@ txs_to_querys2([STx|T], Trees, Height) ->
];
sortition_root_tx ->
%gov existence
SID = Tx#sortition_root_tx.sid,
Root = Tx#sortition_root_tx.root,
RID = sortition_roots:id(SID, Root),
[
{governance, ?n2i(ex)},
{sortition_chains, Tx#sortition_root_tx.sid},
{sortition_roots, Tx#sortition_root_tx.sid},
{sortition_chains, SID},
{sortition_roots, RID},
{accounts, Tx#sortition_root_tx.from}
];
sortition_timeout_tx ->
Expand Down
35 changes: 21 additions & 14 deletions apps/amoveo_core/src/consensus/trees/sortition_chains.erl
Expand Up @@ -32,11 +32,15 @@ serialize(X) ->
true = (size(W) == PubSize),
H = X#sortition_chain.height,
N = X#sortition_chain.nonce,
OR = X#sortition_chain.operators_root,
Deposit = X#sortition_chain.deposit,
Delay = X#sortition_chain.delay,
T = X#sortition_chain.done_timer,
OR = X#sortition_chain.operators_root,
true = (size(OR) == 32),
<<C/binary, A:BalanceSize, E:HeightSize, D:8, W/binary, H:HeightSize, N:NON, OR/binary, Delay:HeightSize, T:HeightSize>>.
<<C/binary,
A:BalanceSize,
E:HeightSize,
D:8, W/binary, H:HeightSize, N:NON, OR/binary, Deposit:BalanceSize, Delay:HeightSize, T:HeightSize>>.
deserialize(X) ->
BalanceSize = constants:balance_bits(),
PubSize = constants:pubkey_size() * 8,
Expand All @@ -49,21 +53,24 @@ deserialize(X) ->
W:PubSize, %65
H:HeightSize, %4
N:NON,%4
OR:256,%4
OR:256,%32
Deposit:BalanceSize,%6
Delay:HeightSize,%4
T:HeightSize%4
>> = X,
%total of 161 bytes
#sortition_chain{creator = <<C:PubSize>>,
amount = A,
expiration = E,
done = D,
potential_winner = <<W:PubSize>>,
height = H,
nonce = N,
operators_root = <<OR:256>>,
delay = Delay,
done_timer = T}.
%total of 195 bytes
#sortition_chain{
creator = <<C:PubSize>>,
amount = A,
expiration = E,
done = D,
potential_winner = <<W:PubSize>>,
height = H,
nonce = N,
operators_root = <<OR:256>>,
deposit = Deposit,
delay = Delay,
done_timer = T}.
dict_get(Key, Dict) ->
<<_:256>> = Key,
X = dict:find({sortition_chains, Key}, Dict),
Expand Down
10 changes: 5 additions & 5 deletions apps/amoveo_core/src/consensus/trees/sortition_spent.erl
Expand Up @@ -8,7 +8,7 @@
%dict_update/4, dict_update/5, dict_delete/2,%update dict stuff
dict_update/3,
%meta_get/1,
%verify_proof/4,make_leaf/3,key_to_int/1,
verify_proof/4,make_leaf/3,key_to_int/1,
serialize/1,test/0, deserialize/1]).%common tree stuff
-define(id, sortition_spent).
-include("../../records.hrl").
Expand Down Expand Up @@ -40,7 +40,7 @@ dict_update(Key, Height, Dict) ->
#sortition_spent{height = Height}.
dict_get(Key, Dict) ->
<<_:256>> = Key,
X = dict:find({sortition_spents, Key}, Dict),
X = dict:find({sortition_spent, Key}, Dict),
case X of
error -> empty;
{ok, 0} -> empty;
Expand All @@ -49,7 +49,7 @@ dict_get(Key, Dict) ->
end.
get(ID, SortitionChains) ->
<<_:256>> = ID,
{RH, Leaf, Proof} = trie:get(key_to_int(ID), SortitionChains, sortition_spents),
{RH, Leaf, Proof} = trie:get(key_to_int(ID), SortitionChains, sortition_spent),
V = case Leaf of
empty -> empty;
L -> deserialize(leaf:value(L))
Expand All @@ -68,15 +68,15 @@ id(Pubkey, SID) ->

dict_write(SC, Dict) ->
ID = id(SC),
dict:store({sortition_spents, ID},
dict:store({sortition_spent, ID},
serialize(SC),
Dict).
%write(SC, Root) ->
% ID = hash:doit(<<SC#sortition_spent.pubkey/binary,
% SC#sortition_spent.expiration:HeightBits>>),
% M = serialize(SC),
%Shares = Channel#channel.shares,
% trie:put(key_to_int(ID), M, 0, Root, sortition_spents). %returns a pointer to the new root
% trie:put(key_to_int(ID), M, 0, Root, sortition_spent). %returns a pointer to the new root
make_leaf(Key, V, CFG) ->
leaf:new(key_to_int(Key),
V, 0, CFG).
Expand Down
6 changes: 6 additions & 0 deletions apps/amoveo_core/src/consensus/tx_pool_feeder.erl
Expand Up @@ -107,6 +107,9 @@ absorb_internal2(SignedTx, PID) ->
Height = block:height(),
{CBTX, _} = coinbase_tx:make(constants:master_pub(), F#tx_pool.block_trees),
Txs2 = [SignedTx|Txs],
%io:fwrite("now 6 "),%2000
%io:fwrite(packer:pack(now())),
%io:fwrite("\n"),
Querys = proofs:txs_to_querys([CBTX|Txs2], F#tx_pool.block_trees, Height+1),
OldDict = lookup_merkel_proofs(F#tx_pool.dict, Querys, F#tx_pool.block_trees),
MinerReward = block:miner_fees(Txs2),
Expand Down Expand Up @@ -175,6 +178,9 @@ lookup_merkel_proofs(Dict, [{oracle_bets, Key}|T], Trees) ->
end,
lookup_merkel_proofs(Dict2, T, Trees);
lookup_merkel_proofs(Dict, [{TreeID, Key}|T], Trees) ->
%io:fwrite("tx pool feeder, lookup merkle proofs\n"),
%io:fwrite(packer:pack({TreeID, Key})),
%io:fwrite("\n"),
Dict2 =
case dict:find({TreeID, Key}, Dict) of
error ->
Expand Down
94 changes: 73 additions & 21 deletions apps/amoveo_core/src/consensus/txs/sortition_contract_tx.erl
@@ -1,6 +1,6 @@
-module(sortition_contract_tx).
-export([go/4, %make/5,
make_dict/5, %is_tx/1,
make_dict/6, %is_tx/1,
from/1, %id/1,
to_prove/2, to_prove_helper/2]).
-include("../../records.hrl").
Expand All @@ -21,7 +21,7 @@ from(X) -> X#sortition_contract_tx.from.
% (testnet_sign:data(SPK))#sortition_contract.id.
is_tx(Tx) ->
is_record(Tx, sortition_contract_tx).
make_dict(From, Fee, ScriptPubkey, ScriptSig, Winner) ->
make_dict(From, Fee, SID, ScriptPubkey, ScriptSig, Winner) ->
%SPK = testnet_sign:data(ScriptPubkey),
%SID = SPK#sortition_contract.sortition_id,
%T = governance,
Expand All @@ -34,12 +34,22 @@ make_dict(From, Fee, ScriptPubkey, ScriptSig, Winner) ->
%Acc1 = channels:acc1(Channel),
%Acc2 = channels:acc2(Channel),
%Nonce = Acc#acc.nonce,
SC = trees:get(sortition_chains, SID),
D = SC#sortition_chain.deposit,
Acc = trees:get(accounts, From),
Nonce = Acc#acc.nonce,
SRH = ScriptPubkey#merkle_contract.root,
SRID = sortition_roots:id(SID, SRH),
SR = trees:get(sortition_roots, SRID),
PH = SR#sortition_root.height,
%SID = sortition_chains:id(From, Expiration),
#sortition_contract_tx{from = From, nonce = Nonce + 1,
fee = Fee, winner = Winner,
contract = ScriptPubkey,
evidence = ScriptSig}.
sortition_id = SID,
fee = Fee, winner = Winner,
contract = ScriptPubkey,
evidence = ScriptSig,
proof_height = PH,
deposit = D}.

%make(From, Fee, ScriptPubkey, ScriptSig, Trees) ->
% Governance = trees:governance(Trees),
Expand Down Expand Up @@ -77,14 +87,16 @@ unspent_pubkeys_check([From|T], Height, SID, Dict) ->
B and unspent_pubkeys_check(T, Height, SID, Dict).

go(Tx, Dict, NewHeight, _NonceCheck) ->
io:fwrite("processing sortition contract tx \n"),
F26 = forks:get(26),
true = (NewHeight > F26),
SID = Tx#sortition_contract_tx.sortition_id,
From = Tx#sortition_contract_tx.from,
Nonce = Tx#sortition_contract_tx.nonce,
Winner = Tx#sortition_contract_tx.winner,
SpentID = sortition_spent:id(Winner, SID),
empty = sortition_spent:dict_get(SpentID, Dict),%check if we have a record that this person already spent the winning part of the probability space.
SC = sortition_chain:dict_get(SID, Dict),
SC = sortition_chains:dict_get(SID, Dict),
true = SC#sortition_chain.expiration < NewHeight,
0 = SC#sortition_chain.done,
SCH = SC#sortition_chain.height,
Expand All @@ -98,27 +110,55 @@ go(Tx, Dict, NewHeight, _NonceCheck) ->
ProofHeight = Tx#sortition_contract_tx.proof_height,

%Dict2 = charge a fee.
Facc = accounts:dict_update(From, Dict, -Tx#sortition_contract_tx.fee, Nonce),
Dict2 = accounts:dict_write(Facc, Dict),

%pay a safety deposit
Deposit = Tx#sortition_contract_tx.deposit,
Deposit = SC#sortition_chain.deposit,
Facc2 = accounts:dict_update(From, Dict2, -Deposit, none),
Dict3 = accounts:dict_write(Facc2, Dict2),

%if we are overwriting someone else's attempt to settle this sortition chain, then give them a refund 100% of their safety deposit.

Dict4 = case SC#sortition_chain.potential_winner of
<<0:520>> -> Dict3;
PW ->
Wacc = accounts:dict_update(PW, Dict3, Deposit, none),
accounts:dict_write(Wacc, Dict3)
end,

%after this point, it needs to be impossible for this tx to crash. Otherwise an attacker could DDOS mining pool tx processing nodes and prevent txs from being included.
{Pubkeys, Contract2, Valid_0} =
sortition_spk:verify(Tx#sortition_contract_tx.contract, Dict),

Valid_1 = unspent_pubkeys_check(Pubkeys, NewHeight, SID, Dict), %for each of these pubkeys, we need to verify it is not in the sortition_spent tree for an earlier height

PubkeysRoot = sortition_spk:merkelize_pubkeys(Pubkeys),%we can generate a small merkel tree of these pubkeys during this tx processing. We only need to record the root. Anyone who cares can keep a merkel proof if they want.
sortition_spk:verify(Tx#sortition_contract_tx.contract, Dict4),
if
not(Valid_0) ->
io:fwrite("sortition_contract tx error: bad merkel proof\n"),
Dict2;
true ->
Valid_1 = unspent_pubkeys_check(Pubkeys, NewHeight, SID, Dict4), %for each of these pubkeys, we need to verify it is not in the sortition_spent tree for an earlier height
if
not(Valid_1) ->
io:fwrite("sortition_contract tx error: operator did not own that value at that point in time. \n"),
Dict2;
true ->
go2(Pubkeys, Contract2, SCH, ProofHeight, Winner, Tx, NewHeight, SC, Dict2, Dict4)
end
end.
go2(Pubkeys, Contract2, SCH, ProofHeight, Winner, Tx, NewHeight, SC, Dict2, Dict4) ->
OperatorsRoot = sortition_spk:merkelize_pubkeys(Pubkeys),%we can generate a small merkel tree of these pubkeys during this tx processing. We only need to record the root. Anyone who cares can keep a merkel proof if they want.

Valid_3 =
{Valid_3, ChannelNonce} =
if
(is_binary(Contract2) and (size(Contract2) == 65)) ->
((SCH > ProofHeight)
and (Winner == Contract2));
(element(1, Contract2) == sortition_channel) ->
%also verify that the state channel smart contract
Valid_2 = not(SCH < ProofHeight),
{((SCH > ProofHeight)
and (Winner == Contract2)), 1};
(SCH < ProofHeight) ->
io:fwrite("sortition_contract tx error: channel proof is for too late of a height.\n"),
{false, 1};
is_record(Contract2, sortition_channel) ->
%(element(1, Contract2) == sortition_channel) ->
%also verify that the state channel smart contract
1=2,
Evidence = Tx#sortition_contract_tx.evidence,
ProveStuff = prove_stuff(Evidence#sortition_evidence.prove),
SS = Evidence#sortition_evidence.ss,
Expand All @@ -129,13 +169,25 @@ go(Tx, Dict, NewHeight, _NonceCheck) ->
%make sure the new nonce is higher than the old nonce.
%winner is either sortition_channel.pubkey, or sortition_chain.creator
WinnerShouldBe = ok,
Valid_2 and (Winner == WinnerShouldBe)
Nonce = ok,
{(Winner == WinnerShouldBe), Nonce};
true ->
io:fwrite("sortition_contract tx error: not a pubkey or a valid sortition_channel \n"),
io:fwrite(packer:pack(Contract2)),
{false, 1}
end,
if
not(Valid_3) ->
io:fwrite("sortition_contract tx error: general failure \n"),
Dict2; % if we have already run the smart contract, then we need to include the tx and charge a fee, even if the tx turns out invalid after that point. Just don't update the state of the sortition chain. So in that case, return Dict2
true ->

%update sortition_chain for the new winner, pubkeysRoot, winning height, nonce, and done_timer.
SC2 = SC#sortition_chain{potential_winner = Winner, height = ProofHeight, nonce = ChannelNonce, operators_root = OperatorsRoot, done_timer = NewHeight},
sortition_chain:dict_write(SC2, Dict4)
end.


% if we have already run the smart contract, then we need to include the tx and charge a fee, even if the tx turns out invalid after that point. Just don't update the state of the sortition chain. So in that case, return Dict2
Dict.



Expand Down
13 changes: 9 additions & 4 deletions apps/amoveo_core/src/consensus/txs/sortition_new_tx.erl
@@ -1,6 +1,6 @@
-module(sortition_new_tx).
-export([go/4, %make/8,
make_dict/5, %spk/2,
make_dict/6, %spk/2,
%cid/1,
from/1, amount/1, expires/1]).
-include("../../records.hrl").
Expand All @@ -12,13 +12,15 @@ expires(X) -> X#sortition_new_tx.expires.
%spk(Tx, Delay) ->
% spk:new(Tx#sortition_new_tx.from, Tx#sortition_new_tx.acc2, Tx#sortition_new_tx.id,
% [], 0,0, 0, Delay).
make_dict(Acc1,Inc1,Expires, Delay, Fee) ->
make_dict(Acc1,Inc1,Expires, Delay, Deposit, Fee) ->
A = trees:get(accounts, Acc1),
Nonce = A#acc.nonce,
SID = sortition_chains:id(Acc1, Expires),
#sortition_new_tx{from = Acc1,
fee = Fee, nonce = Nonce+1, amount = Inc1,
expires = Expires, delay = Delay, sid = SID}.
deposit = Deposit,
expires = Expires, delay = Delay, sid = SID}.

%make(ID,Trees,Acc1,Acc2,Inc1,Delay, Fee) ->
% <<_:256>> = ID,
% Accounts = trees:accounts(Trees),
Expand All @@ -39,7 +41,10 @@ go(Tx, Dict, NewHeight, _) ->
Amount = Tx#sortition_new_tx.amount,
Expires = Tx#sortition_new_tx.expires,
Delay = Tx#sortition_new_tx.delay,
NewSC = #sortition_chain{done = 0, creator = Aid1, amount = Amount, expiration = Expires, delay = Delay, potential_winner = Aid1, done_timer = Expires},
Deposit = Tx#sortition_new_tx.deposit,
true = Deposit > 0,
true = is_integer(Deposit),
NewSC = #sortition_chain{done = 0, creator = Aid1, amount = Amount, expiration = Expires, delay = Delay, potential_winner = Aid1, done_timer = Expires, height = 1000000000, nonce = 0, operators_root = <<0:256>>, deposit = Deposit},
%NewSC = sortition_chains:new(Aid1, Amount, Expires),
ID = sortition_chains:id(NewSC),
ID = Tx#sortition_new_tx.sid,
Expand Down
3 changes: 3 additions & 0 deletions apps/amoveo_core/src/consensus/txs/sortition_root_tx.erl
Expand Up @@ -23,6 +23,9 @@ go(Tx, Dict, NewHeight, _) ->
Root = Tx#sortition_root_tx.root,
Prev = Tx#sortition_root_tx.prev,
SC = sortition_chains:dict_get(SortitionID, Dict),
io:fwrite("sortition root tx, SC is "),
io:fwrite(packer:pack(SC)),
io:fwrite("\n"),
From = SC#sortition_chain.creator,
%Root = SC#sortition_chain.root,
%Prev = SC#sortition_chain.prev,
Expand Down

0 comments on commit 577e17b

Please sign in to comment.