From 3088535474fea0493c4a1dd02d7b84fede476fca Mon Sep 17 00:00:00 2001 From: zack-bitcoin Date: Wed, 2 Oct 2019 00:22:25 -0400 Subject: [PATCH] more details of the sortition contract tx --- .../src/consensus/chain/proofs.erl | 10 ++-- .../consensus/txs/sortition_contract_tx.erl | 54 +++++++++---------- .../src/consensus/txs/sortition_spk.erl | 4 +- apps/amoveo_core/src/consensus/txs/spk.erl | 6 +-- apps/amoveo_core/src/records.hrl | 2 +- 5 files changed, 41 insertions(+), 35 deletions(-) diff --git a/apps/amoveo_core/src/consensus/chain/proofs.erl b/apps/amoveo_core/src/consensus/chain/proofs.erl index 1f6d9b45f..1958cc23d 100644 --- a/apps/amoveo_core/src/consensus/chain/proofs.erl +++ b/apps/amoveo_core/src/consensus/chain/proofs.erl @@ -406,20 +406,24 @@ txs_to_querys2([STx|T], Trees, Height) -> SID = Tx#sortition_contract_tx.sortition_id, From = Tx#sortition_contract_tx.from, SpentID = sortition_spent:id(From, SID), - %there are a list of pubkeys we need to look up unspent for. - %{ProofHeight, Pubkeys, Contract} = sortition_spk:verify(Tx#sortition_contract_tx.contract), + Contract = Tx#sortition_contract_tx.contract, + SRHash = Contract#merkle_contract.root, + SRID = sortition_roots:id(SID, SRHash), + {Pubkeys, true} = sortition_spk:verify_merkle(SRHash, Contract#merkle_contract.contracts),%look up unspent for all these pubkeys, + Children0 = lists:map(fun(K) -> {sortition_spent, sortition_spent:id(K, SID)} end, Pubkeys), %we need to have consensus state for all the binary merkel contracts. %if there is a channel contract, we need the consensus state for that too. [ {sortition_spent, SpentID}, {sortition_chains, SID}, + {sortition_roots, SRID}, {accounts, From}, {governance, ?n2i(csc)}, {governance, ?n2i(time_gas)}, {governance, ?n2i(space_gas)}, {governance, ?n2i(fun_limit)}, {governance, ?n2i(var_limit)} - ]; + ] ++ Children0; sortition_slash_tx -> 1=2, [ diff --git a/apps/amoveo_core/src/consensus/txs/sortition_contract_tx.erl b/apps/amoveo_core/src/consensus/txs/sortition_contract_tx.erl index dba1579c7..f162b09b8 100644 --- a/apps/amoveo_core/src/consensus/txs/sortition_contract_tx.erl +++ b/apps/amoveo_core/src/consensus/txs/sortition_contract_tx.erl @@ -1,10 +1,8 @@ -module(sortition_contract_tx). -export([go/4, %make/5, - make_dict/4, %is_tx/1, + make_dict/5, %is_tx/1, from/1, %id/1, to_prove/2, to_prove_helper/2]). -%-record(cs, {from, nonce, fee = 0, -% scriptpubkey, scriptsig}). -include("../../records.hrl"). to_prove(X, Height) -> to_prove_helper(X#sortition_contract_tx.evidence, Height). @@ -23,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) -> +make_dict(From, Fee, ScriptPubkey, ScriptSig, Winner) -> %SPK = testnet_sign:data(ScriptPubkey), %SID = SPK#sortition_contract.sortition_id, %T = governance, @@ -39,7 +37,7 @@ make_dict(From, Fee, ScriptPubkey, ScriptSig) -> Acc = trees:get(accounts, From), Nonce = Acc#acc.nonce, #sortition_contract_tx{from = From, nonce = Nonce + 1, - fee = Fee, + fee = Fee, winner = Winner, contract = ScriptPubkey, evidence = ScriptSig}. @@ -83,7 +81,8 @@ go(Tx, Dict, NewHeight, _NonceCheck) -> true = (NewHeight > F26), SID = Tx#sortition_contract_tx.sortition_id, From = Tx#sortition_contract_tx.from, - SpentID = sortition_spent:id(From, SID), + 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), true = SC#sortition_chain.expiration < NewHeight, @@ -93,27 +92,32 @@ go(Tx, Dict, NewHeight, _NonceCheck) -> SortitionRootHash = Contract#merkle_contract.root, SRID = sortition_roots:id(SID, SortitionRootHash), - SR = sortition_root:dict_get(SRID, Dict), + SR = sortition_roots:dict_get(SRID, Dict), SortitionRootHash = SR#sortition_root.root, ProofHeight = SR#sortition_root.height, + ProofHeight = Tx#sortition_contract_tx.proof_height, + + %Dict2 = charge a fee. + + %pay a safety deposit + + %if we are overwriting someone else's attempt to settle this sortition chain, then give them a refund 100% of their safety deposit. %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), + {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),%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. + 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. - {Valid_3, ok} = - case element(1, Contract2) of - sortition_child -> - Valid_2 = (SCH > ProofHeight), - NextOperator = Contract2#sortition_child.pubkey, - NextSID = Contract2#sortition_child.sid, - %it is a sortition chain inside a sortition chain. - ok; - sortition_channel -> - %also verify that the state channel smart contract + Valid_3 = + 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), Evidence = Tx#sortition_contract_tx.evidence, ProveStuff = prove_stuff(Evidence#sortition_evidence.prove), @@ -123,18 +127,14 @@ go(Tx, Dict, NewHeight, _NonceCheck) -> CID = Contract2#sortition_channel.cid, %it is a state channel inside a sortition chain %make sure the new nonce is higher than the old nonce. - ok + %winner is either sortition_channel.pubkey, or sortition_chain.creator + WinnerShouldBe = ok, + Valid_2 and (Winner == WinnerShouldBe) end, - %pay a safety deposit - - %if we are overwriting someone else's attempt to settle this sortition chain, then give them a refund 100% of their safety deposit. - - % 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. - %update sortition_chain for the new winner, pubkeysRoot, winning height, nonce, and done_timer. - %if any of the tests are invalid, don't update the sortition_chain, but do charge the fee. + % 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. diff --git a/apps/amoveo_core/src/consensus/txs/sortition_spk.erl b/apps/amoveo_core/src/consensus/txs/sortition_spk.erl index ff32e0ae2..5d218f5e3 100644 --- a/apps/amoveo_core/src/consensus/txs/sortition_spk.erl +++ b/apps/amoveo_core/src/consensus/txs/sortition_spk.erl @@ -1,5 +1,5 @@ -module(sortition_spk). --export([verify/2, hash/1]). +-export([verify/2, hash/1, merkelize_pubkeys/1]). -include("../../records.hrl"). serialize_sortition_child(SSC) -> @@ -37,3 +37,5 @@ verify(Contract, Dict) -> %Contract2 is either state_channel or sortition_child, or the winner's pubkey. {Pubkeys, Contract2, Valid0 and Valid1}. +merkelize_pubkeys(Pubkeys) -> + ok. diff --git a/apps/amoveo_core/src/consensus/txs/spk.erl b/apps/amoveo_core/src/consensus/txs/spk.erl index 34683c364..3c565af37 100644 --- a/apps/amoveo_core/src/consensus/txs/spk.erl +++ b/apps/amoveo_core/src/consensus/txs/spk.erl @@ -336,9 +336,9 @@ dict_run3(SS, Bet, OpGas, RamGas, Funs, Vars, State, Dict) -> end, C = Bet#bet.code, Code = <>, - io:fwrite("spk proved facts \n"), - disassembler:doit(Code), - io:fwrite("\n"), + %io:fwrite("spk proved facts \n"), + %disassembler:doit(Code), + %io:fwrite("\n"), Data = data_maker(OpGas, RamGas, Vars, Funs, ScriptSig, Code, State, constants:hash_size(), Height), {Amount0, Nonce, Delay, Data2} = chalang_error_handling(ScriptSig, Code, Data), CGran = constants:channel_granularity(), diff --git a/apps/amoveo_core/src/records.hrl b/apps/amoveo_core/src/records.hrl index 7c890d518..53f8518c4 100644 --- a/apps/amoveo_core/src/records.hrl +++ b/apps/amoveo_core/src/records.hrl @@ -169,7 +169,7 @@ -record(sortition_spent, {sortition_id, pubkey, height}). %txs -record(sortition_new_tx, {from, nonce, fee, amount, sid, expires, delay}). --record(sortition_contract_tx, {from, nonce, fee, sortition_id, contract, evidence}). +-record(sortition_contract_tx, {from, nonce, fee, winner, sortition_id, contract, evidence, proof_height}). -record(sortition_timeout_tx, {from, nonce, fee, sid, winner, amount}). -record(sortition_root_tx, {from, nonce, fee, sid, root, prev}). %other