Pages:
Author

Topic: Atomic swaps using cut and choose - page 7. (Read 12138 times)

legendary
Activity: 1176
Merit: 1132
February 16, 2016, 03:12:48 PM
#10
latest revision with all the "poll" events

Code:
   s = instantdex_statecreate(s,n,"BTC_cleanup",BTC_cleanupfunc,0,0,0,0); // from states without any commits
   
    s = instantdex_statecreate(s,n,"BOB_reclaim",BOB_reclaimfunc,0,0,0,0); // Bob's gets his deposit back
    instantdex_addevent(s,*n,"BOB_reclaim","brcfound","poll","BTC_cleanup");
    instantdex_addevent(s,*n,"BOB_reclaim","poll","poll","BOB_reclaim");

    s = instantdex_statecreate(s,n,"ALICE_reclaim",ALICE_reclaimfunc,0,0,0,0); // Alice retrieves alt payment
    instantdex_addevent(s,*n,"ALICE_reclaim","arcfound","poll","BTC_cleanup");
    instantdex_addevent(s,*n,"ALICE_reclaim","poll","poll","ALICE_reclaim");

    s = instantdex_statecreate(s,n,"ALICE_claimedbtc",ALICE_claimbtcfunc,0,0,0,0); // mainstream cases
    instantdex_addevent(s,*n,"ALICE_claimedbtc","aclfound","poll","BTC_cleanup");
    instantdex_addevent(s,*n,"ALICE_claimedbtc","poll","poll","ALICE_claimedbtc");
   
    s = instantdex_statecreate(s,n,"BOB_claimedalt",BOB_claimaltfunc,0,0,0,0);
    instantdex_addevent(s,*n,"BOB_claimedalt","bclfound","poll","BTC_cleanup");
    instantdex_addevent(s,*n,"BOB_claimedalt","poll","poll","BOB_claimedalt");

    // need to create states before they can be referred to, that way a one pass FSM compile is possible
    s = instantdex_statecreate(s,n,"BOB_sentprivs",BTC_waitprivsfunc,0,"BTC_cleanup",0,0);
    s = instantdex_statecreate(s,n,"BOB_waitfee",BOB_waitfeefunc,0,"BTC_cleanup",0,0);
    s = instantdex_statecreate(s,n,"BOB_sentdeposit",BOB_waitBTCalttxfunc,0,"BOB_reclaim",0,0);
    s = instantdex_statecreate(s,n,"BOB_altconfirm",BOB_waitaltconfirmfunc,0,"BOB_reclaim",0,0);
    s = instantdex_statecreate(s,n,"BOB_sentpayment",BOB_waitprivMfunc,0,"BOB_reclaim",0,0);
    s = instantdex_statecreate(s,n,"ALICE_sentprivs",BTC_waitprivsfunc,0,"BTC_cleanup",0,0);
    s = instantdex_statecreate(s,n,"Alice_waitfee",ALICE_waitfeefunc,0,"BTC_cleanup",0,0);
    s = instantdex_statecreate(s,n,"ALICE_waitdeposit",ALICE_waitdepositfunc,0,"BTC_cleanup",0,0);
    s = instantdex_statecreate(s,n,"ALICE_sentalt",ALICE_waitBTCpaytxfunc,0,"ALICE_reclaim",0,0);
    s = instantdex_statecreate(s,n,"ALICE_waitconfirms",ALICE_waitpayconf_or_bobreclaimfunc,0,"ALICE_reclaim",0,0);

    // events instantdex_addevent(s,*n,,,,)
    if ( 0 ) // following are implicit states and events handled externally to setup datastructures
    {
        //s = instantdex_statecreate(s,n,"BOB_idle",BTC_idlefunc,0,0,0);
        //s = instantdex_statecreate(s,n,"ALICE_idle",BTC_idlefunc,0,0,0);
        instantdex_addevent(s,*n,"BOB_idle","usrorder","BTCoffer","BOB_sentoffer"); // send deck
        instantdex_addevent(s,*n,"ALICE_idle","usrorder","BTCoffer","ALICE_sentoffer");
        instantdex_addevent(s,*n,"BOB_idle","BTCoffer","BTCdeckC","BOB_gotoffer"); // send deck + Chose
        instantdex_addevent(s,*n,"ALICE_idle","BTCoffer","BTCdeckC","ALICE_gotoffer");
    }
    // after offer is sent, wait for other side to choose and sent their deck, then send privs
    s = instantdex_statecreate(s,n,"BOB_sentoffer",BTC_waitdeckCfunc,0,"BTC_cleanup",0,1);
    s = instantdex_statecreate(s,n,"ALICE_sentoffer",BTC_waitdeckCfunc,0,"BTC_cleanup",0,1);
    instantdex_addevent(s,*n,"BOB_sentoffer","BTCdeckC","BTCprivC","BOB_sentprivs"); // send privs + Chose
    instantdex_addevent(s,*n,"ALICE_sentoffer","BTCdeckC","BTCprivC","ALICE_sentprivs");
   
    // gotoffer states have received deck and sent BTCdeckC already (along with deck)
    s = instantdex_statecreate(s,n,"BOB_gotoffer",BTC_waitprivCfunc,0,"BTC_cleanup",0,1);
    s = instantdex_statecreate(s,n,"ALICE_gotoffer",BTC_waitprivCfunc,0,"BTC_cleanup",0,1);
    instantdex_addevent(s,*n,"BOB_gotoffer","BTCprivC","BTCprivs","BOB_sentprivs"); // send privs
    instantdex_addevent(s,*n,"ALICE_gotoffer","BTCprivC","BTCprivs","ALICE_sentprivs");
   
    // to reach sentprivs, all paths must have sent/recv deck and Chose and verified cut and choose
    s = instantdex_statecreate(s,n,"BOB_sentprivs",BTC_waitprivsfunc,0,"BTC_cleanup",0,0);
    instantdex_addevent(s,*n,"BOB_sentprivs","BTCprivs","poll","BOB_waitfee");
   
    s = instantdex_statecreate(s,n,"ALICE_sentprivs",BTC_waitprivsfunc,0,"BTC_cleanup",0,0);
    instantdex_addevent(s,*n,"ALICE_sentprivs","BTCprivs","poll","Alice_waitfee");

    // Bob waits for fee and sends deposit when it appears
    s = instantdex_statecreate(s,n,"BOB_waitfee",BOB_waitfeefunc,0,"BTC_cleanup",0,0);
    instantdex_addevent(s,*n,"BOB_waitfee","feefound","BTCdeptx","BOB_sentdeposit");
    instantdex_addevent(s,*n,"BOB_waitfee","poll","poll","BOB_waitfee");

    // Alice waits for fee and then waits for deposit to confirm and sends altpayment
    s = instantdex_statecreate(s,n,"Alice_waitfee",ALICE_waitfeefunc,0,"BTC_cleanup",0,0);
    instantdex_addevent(s,*n,"Alice_waitfee","feefound","poll","ALICE_waitdeposit");
    instantdex_addevent(s,*n,"Alice_waitfee","poll","poll","Alice_waitfee");
   
    s = instantdex_statecreate(s,n,"ALICE_waitdeposit",ALICE_waitdepositfunc,0,"BTC_cleanup",0,0);
    instantdex_addevent(s,*n,"ALICE_waitdeposit","depfound","BTCalttx","ALICE_sentalt");
    instantdex_addevent(s,*n,"ALICE_waitdeposit","poll","poll","ALICE_waitdeposit");

    // now Bob's turn to make sure altpayment is confirmed and send real payment
    s = instantdex_statecreate(s,n,"BOB_sentdeposit",BOB_waitBTCalttxfunc,0,"BOB_reclaim",0,0);
    instantdex_addevent(s,*n,"BOB_sentdeposit","BTCalttx","poll","BOB_altconfirm");
 
    s = instantdex_statecreate(s,n,"BOB_altconfirm",BOB_waitaltconfirmfunc,0,"BOB_reclaim",0,0);
    instantdex_addevent(s,*n,"BOB_altconfirm","altfound","BTCpaytx","BOB_sentpayment");
    instantdex_addevent(s,*n,"BOB_altconfirm","poll","poll","BOB_altconfirm");
   
    // now Alice's turn to make sure payment is confrmed and send in claim or see bob's reclaim and reclaim
    s = instantdex_statecreate(s,n,"ALICE_sentalt",ALICE_waitBTCpaytxfunc,0,"ALICE_reclaim",0,0);
    instantdex_addevent(s,*n,"ALICE_sentalt","BTCpaytx","poll","ALICE_waitconfirms");
   
    s = instantdex_statecreate(s,n,"ALICE_waitconfirms",ALICE_waitpayconf_or_bobreclaimfunc,0,"ALICE_reclaim",0,0);
    instantdex_addevent(s,*n,"ALICE_waitconfirms","bobfound","poll","ALICE_reclaim");
    instantdex_addevent(s,*n,"ALICE_waitconfirms","payfound","BTCprivM","ALICE_claimedbtc");
    instantdex_addevent(s,*n,"ALICE_waitconfirms","poll","poll","ALICE_waitconfirms");

    // Bob waits for privM either from Alice or alt blockchain
    s = instantdex_statecreate(s,n,"BOB_sentpayment",BOB_waitprivMfunc,0,"BOB_reclaim",0,0);
    instantdex_addevent(s,*n,"BOB_sentpayment","btcfound","BTCdone","BOB_claimedalt");
    instantdex_addevent(s,*n,"BOB_sentpayment","BTCprivM","BTCdone","BOB_claimedalt");
    instantdex_addevent(s,*n,"BOB_sentpayment","poll","poll","BOB_sentpayment");
    instantdex_FSMtest(s,*n);

I also wrote a bruteforce tester

James
legendary
Activity: 1176
Merit: 1132
February 15, 2016, 11:40:48 PM
#9
I have to add another metaevent to deal with the waiting states, as there is no incoming message to trigger it.

this allows to create states like:

Code:
    s = instantdex_statecreate(s,n,"BOB_waitfee",BOB_waitfeefunc,0,"BTC_cleanup",0);
    instantdex_addevent(s,*n,"BOB_waitfee","feefound","BTCdeptx","BOB_sentdeposit");
    instantdex_addevent(s,*n,"BOB_waitfee","poll","poll","BOB_waitfee");

BOB_waitfee will issue poll events to itself in a loop, until "feefound" event is generated (or timeout)

James
legendary
Activity: 1176
Merit: 1132
February 15, 2016, 04:44:12 PM
#8
optimized FSM a bit:

Code:
    s = instantdex_statecreate(s,n,"BTC_cleanup",BTC_cleanupfunc,0,0,0); // from states without any commits
    s = instantdex_statecreate(s,n,"BOB_reclaim",BOB_reclaimfunc,0,0,0); // Bob's gets his deposit back
    s = instantdex_statecreate(s,n,"ALICE_reclaim",ALICE_reclaimfunc,0,0,0); // Alice retrieves alt payment
 
    s = instantdex_statecreate(s,n,"ALICE_claimedbtc",ALICE_claimbtcfunc,0,0,0); // mainstream cases
    s = instantdex_statecreate(s,n,"BOB_claimedalt",BOB_claimaltfunc,0,0,0);

    // need to create states before they can be referred to, that way a one pass FSM compile is possible
    s = instantdex_statecreate(s,n,"BOB_sentprivs",BTC_waitprivsfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_sentprivs",ALICE_waitfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_wait3",ALICE_waitfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"BOB_sentdeposit",BOB_waitBTCalttxfunc,0,"BTC_claimdeposit",0);

    // events instantdex_addevent(s,*n,,,,)
    if ( 0 ) // following are implicit states and events handled externally to setup datastructures
    {
        //s = instantdex_statecreate(s,n,"BOB_idle",BTC_idlefunc,0,0,0);
        //s = instantdex_statecreate(s,n,"ALICE_idle",BTC_idlefunc,0,0,0);
        instantdex_addevent(s,*n,"BOB_idle","usrorder","BTCoffer","BOB_sentoffer"); // send deck
        instantdex_addevent(s,*n,"ALICE_idle","usrorder","BTCoffer","ALICE_sentoffer");
        instantdex_addevent(s,*n,"BOB_idle","BTCoffer","BTCdeckC","BOB_gotoffer"); // send deck + Chose
        instantdex_addevent(s,*n,"ALICE_idle","BTCoffer","BTCdeckC","ALICE_gotoffer");
    }
    // after offer is sent, wait for other side to choose and sent their deck, then send privs
    s = instantdex_statecreate(s,n,"BOB_sentoffer",BTC_waitdeckCfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_sentoffer",BTC_waitdeckCfunc,0,"BTC_cleanup",0);
    instantdex_addevent(s,*n,"BOB_sentoffer","BTCdeckC","BTCprivC","BOB_sentprivs"); // send privs + Chose
    instantdex_addevent(s,*n,"ALICE_sentoffer","BTCdeckC","BTCprivC","ALICE_sentprivs");
   
    // gotoffer states have received deck and sent BTCchose already (along with deck)
    s = instantdex_statecreate(s,n,"BOB_gotoffer",BTC_waitprivCfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_gotoffer",BTC_waitprivCfunc,0,"BTC_cleanup",0);
    instantdex_addevent(s,*n,"BOB_gotoffer","BTCprivC","BTCprivs","BOB_sentprivs"); // send privs
    instantdex_addevent(s,*n,"ALICE_gotoffer","BTCprivC","BTCprivs","ALICE_sentprivs");
   
    // to reach sentprivs, all paths must have sent/recv deck and Chose and verified cut and choose
    s = instantdex_statecreate(s,n,"BOB_sentprivs",BTC_waitprivsfunc,0,"BTC_cleanup",0);
    instantdex_addevent(s,*n,"BOB_sentprivs","BTCprivs",0,"BOB_waitfee");
    s = instantdex_statecreate(s,n,"ALICE_sentprivs",BTC_waitprivsfunc,0,"BTC_cleanup",0);
    instantdex_addevent(s,*n,"ALICE_sentprivs","BTCprivs",0,"Alice_waitfee");

    s = instantdex_statecreate(s,n,"BOB_waitfee",BOB_waitfeefunc,0,"BTC_cleanup",0);
    instantdex_addevent(s,*n,"BOB_waitfee","feefound","BTCdeptx","BOB_sentdeposit");
   
    s = instantdex_statecreate(s,n,"Alice_waitfee",ALICE_waitfeefunc,0,"BTC_cleanup",0);
    instantdex_addevent(s,*n,"BOB_waitfee","feefound",0,"ALICE_waitfee_deposit");
   
    // following states cover all permutations of the three required events to make altpayment
    s = instantdex_statecreate(s,n,"ALICE_waitfee_deposit",ALICE_waitfunc,0,"BTC_cleanup",0);
    instantdex_addevent(s,*n,"ALICE_waitfee_deposit","depfound",0,"ALICE_waitfee");
    instantdex_addevent(s,*n,"ALICE_waitfee_deposit","feefound",0,"ALICE_waitdeposit");
   
    // wait for last event and send out altpayment
    instantdex_addevent(s,*n,"ALICE_waitfee","feefound","BTCalttx","ALICE_sentalt");
    instantdex_addevent(s,*n,"ALICE_waitdeposit","depfound","BTCalttx","ALICE_sentalt");

    // now Bob's turn to make sure altpayment is confirmed and send real payment
    s = instantdex_statecreate(s,n,"BOB_sentdeposit",BOB_waitBTCalttxfunc,0,"BOB_reclaim",0);
    instantdex_addevent(s,*n,"BOB_sentdeposit","BTCalttx",0,"BOB_altconfirm");
 
    s = instantdex_statecreate(s,n,"BOB_altconfirm",BOB_waitaltconfirmfunc,0,"BTC_claimdeposit",0);
    instantdex_addevent(s,*n,"BOB_altconfirm","altfound","BTCpaytx","BOB_sentpayment");
   
    // now Alice's turn to make sure payment is confrmed and send in claim or see bob's reclaim and reclaim
    s = instantdex_statecreate(s,n,"ALICE_sentalt",ALICE_waitBTCpaytxfunc,0,"BTC_claimdeposit",0);
    instantdex_addevent(s,*n,"ALICE_sentalt","BTCpaytx",0,"ALICE_waitconfirms");
   
    s = instantdex_statecreate(s,n,"ALICE_waitconfirms",ALICE_waitpayconf_or_bobreclaimfunc,0,"BTC_claimdeposit",0);
    instantdex_addevent(s,*n,"ALICE_waitconfirms","bobfound",0,"ALICE_reclaim");
    instantdex_addevent(s,*n,"ALICE_waitconfirms","payfound","BTCprivM","ALICE_claimedbtc");

    // Bob waits for privM either from Alice or alt blockchain
    s = instantdex_statecreate(s,n,"BOB_sentpayment",BOB_waitprivMfunc,0,"BTC_claimdeposit",0);
    instantdex_addevent(s,*n,"BOB_sentpayment","btcfound","BTCdone","BOB_claimedalt");
    instantdex_addevent(s,*n,"BOB_sentpayment","BTCprivM","BTCdone","BOB_claimedalt");
legendary
Activity: 1176
Merit: 1132
February 15, 2016, 11:06:10 AM
#7
Here are the scripts I am using:

both fees are standard payments: OP_DUP OP_HASH160 FEE_RMD160 OP_EQUALVERIFY OP_CHECKSIG

Fees should somehow incorporate the tradeId hash.  That way a trader can't use the same fee for multiple trades.

This could be incorporated into the public keys by multiplying key pairs by a random number selected by the other party.

Bob selects a key pair (fee_pri_bob, fee_pub_bob) and a random number fee_rand_bob.

Note: fee_pub_bob = fee_pri_bob * G

He sends fee_pub_bob and fee_rand_bob to Alice.

Alice computes the same and sends her EC point and random number back.

Bob uses the following key pair

Adjusted Private = fee_pri_bob * fee_rand_alice
Adjusted Public =  fee_pri_bob * fee_rand_alice * G =  fee_rand_alice * (fee_pri_bob * G) = fee_rand_alice * fee_pub_bob

This means that Alice can verify that the public key is unique for this trade (since she can calculate fee_rand_alice * fee_pub_bob), but still doesn't know the matching private key. 
yes, I will add a tag to the feetx by:

OP_DROP OP_DUP OP_HASH160 FEE_RMD160 OP_EQUALVERIFY OP_CHECKSIG

The orderid is unique to a specific orderbook entry. This way, once fee is paid for an atomic sequence, if it fails for whatever reason, you can reuse the feetx. If the feetx is locked to a specific Alice/Bob, that would increase the effect of a nuisance attack (just starting trades without intending to complete them) as the fee wont be able to be reused

James
legendary
Activity: 1232
Merit: 1084
February 15, 2016, 10:46:12 AM
#6
Here are the scripts I am using:

both fees are standard payments: OP_DUP OP_HASH160 FEE_RMD160 OP_EQUALVERIFY OP_CHECKSIG

Fees should somehow incorporate the tradeId hash.  That way a trader can't use the same fee for multiple trades.

This could be incorporated into the public keys by multiplying key pairs by a random number selected by the other party.

Bob selects a key pair (fee_pri_bob, fee_pub_bob) and a random number fee_rand_bob.

Note: fee_pub_bob = fee_pri_bob * G

He sends fee_pub_bob and fee_rand_bob to Alice.

Alice computes the same and sends her EC point and random number back.

Bob uses the following key pair

Adjusted Private = fee_pri_bob * fee_rand_alice
Adjusted Public =  fee_pri_bob * fee_rand_alice * G =  fee_rand_alice * (fee_pri_bob * G) = fee_rand_alice * fee_pub_bob

This means that Alice can verify that the public key is unique for this trade (since she can calculate fee_rand_alice * fee_pub_bob), but still doesn't know the matching private key. 
legendary
Activity: 1176
Merit: 1132
February 15, 2016, 08:40:04 AM
#5
Here are the scripts I am using:

both fees are standard payments: OP_DUP OP_HASH160 FEE_RMD160 OP_EQUALVERIFY OP_CHECKSIG

Alice altpayment: OP_2 OP_2 OP_CHECKMULTISIG

Bob deposit:
OP_IF
    OP_CLTV OP_DROP OP_CHECKSIG
OP_ELSE
    OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG
OP_ENDIF
 
Bob paytx:
OP_IF
    OP_CLTV OP_DROP OP_CHECKSIG
OP_ELSE
    OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG
OP_ENDIF

Naming convention are pubAi are alice's pubkeys (seems only pubA0 and not pubA1)
pubBi are Bob's pubkeys

privN is Bob's privkey from the cut and choose deck as selected by Alice
privM is Alice's counterpart
pubN and pubM are the corresponding pubkeys for these chosen privkeys

Alice timeout event is triggered if INSTANTDEX_LOCKTIME elapses from the start of a FSM instance. Bob timeout event is triggered after INSTANTDEX_LOCKTIME*2

James
legendary
Activity: 1176
Merit: 1132
February 15, 2016, 07:27:27 AM
#4
Also, before an exchange is ready to be put into the state machine, a lot of onetime prep needs to be done and I wanted the state machine to be as pure as possible and not be cluttered with initial setup.

I notice that you have a single processing function (BOB_processfunc for Bob).  You could maybe reduce clutter by having a different handler for each state.

That is all implementation details but I realize that is half the battle.  The basic description doesn't require details on how to check signatures etc., but it is critical that each step is properly checked.

For example, the CPRKV BIP should very clearly define the formatting of the two keys.  Someone might be able to break the protocol by using badly encoded keys or something.
Yes, the FSM was in first draft state and there is a tradeoff between very granular processfuncs vs. duplication of code, but I think the following is much improved and other than the exact transitions for all the possible errors after money is committed, I think it is solid. But I am not confident that I have all the error states for both sides being handled properly.

This is where the FSM is much better than English to specify things and is the "implementation details" that is fully in the specification area, especially when one missed error event can mean loss of funds!

It isnt so clear, but in the create state function you can specify new state to go to in the event of a timeout (max timeout for bob and half max for Alice?) and a different state if some other error happens, ie some unexpected event (not sure if that should just be ignored) or disconnection. We could specify all the possible types of errors that can happen and have a common error handling.

Anyway, here is revised FSM, with all timeout states invoked if we pass half maxtime for Alice or maxtime for Bob. Speaking of time, with the possible +/- 2 hours on the BTC timestamp if the timeout events trigger based on local clock on each node if we need to pad the cltv parameter by 2 hours to prevent race (or worse) conditions. And if we are adding 2 hours, how this affects the claim windows if maxtime is set to be 2 hours.

Code:
     // Four initial states are BOB_sentoffer, ALICE_gotoffer, ALICE_sentoffer, BOB_gotoffer
    // the initiator includes signed feetx and deck of 777 keypairs
    //
    // "BTCabcde are message events from other party (message events capped at length 8)
    // "lowercas" are special events, types: , osit, payment, is altcoin claim
    // "found" means the other party's is confirmed at user specified confidence level
    // BTC_cleanup state just unwinds pending swap as nothing has been committed yet
   
    // states instantdex_statecreate(s,n,,handlerfunc,errorhandler,,
    // a given state has a couple of handlers and custom events, with timeouts and errors invoking a bypass
    s = instantdex_statecreate(s,n,"BTC_cleanup",BTC_cleanupfunc,0,0,0); // from states without any commits
    s = instantdex_statecreate(s,n,"BOB_reclaim",BOB_reclaimfunc,0,0,0); // Bob's gets his deposit back
    s = instantdex_statecreate(s,n,"ALICE_reclaim",ALICE_reclaimfunc,0,0,0); // Alice retrieves alt payment
 
    s = instantdex_statecreate(s,n,"ALICE_claimedbtc",ALICE_claimbtcfunc,0,0,0); // mainstream cases
    s = instantdex_statecreate(s,n,"BOB_claimedalt",BOB_claimaltfunc,0,0,0);

    // need to create states before they can be referred to, that way a one pass FSM compile is possible
    s = instantdex_statecreate(s,n,"BOB_sentprivs",BOB_waitfeefunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_sentprivs",ALICE_waitfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_wait3",ALICE_waitfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"BOB_sentdeposit",BOB_waitBTCalttxfunc,0,"BTC_claimdeposit",0);

    // events instantdex_addevent(s,*n,,,,)
    if ( 0 ) // following are implicit states and events handled externally to setup datastructures
    {
        //s = instantdex_statecreate(s,n,"BOB_idle",BTC_idlefunc,0,0,0);
        //s = instantdex_statecreate(s,n,"ALICE_idle",BTC_idlefunc,0,0,0);
        instantdex_addevent(s,*n,"BOB_idle","usrorder","BTCoffer","BOB_sentoffer"); // send deck
        instantdex_addevent(s,*n,"ALICE_idle","usrorder","BTCoffer","ALICE_sentoffer");
        instantdex_addevent(s,*n,"BOB_idle","BTCoffer","BTCdeckC","BOB_gotoffer"); // send deck + Chose
        instantdex_addevent(s,*n,"ALICE_idle","BTCoffer","BTCdeckC","ALICE_gotoffer");
    }
    // after offer is sent, wait for other side to choose and sent their deck, then send privs
    s = instantdex_statecreate(s,n,"BOB_sentoffer",BTC_waitdeckCfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_sentoffer",BTC_waitdeckCfunc,0,"BTC_cleanup",0);
    instantdex_addevent(s,*n,"BOB_sentoffer","BTCdeckC","BTCprivC","BOB_sentprivs"); // send privs + Chose
    instantdex_addevent(s,*n,"ALICE_sentoffer","BTCdeckC","BTCprivC","ALICE_sentprivs");
   
    // gotoffer states have received deck and sent BTCchose already (along with deck)
    s = instantdex_statecreate(s,n,"BOB_gotoffer",BTC_waitprivCfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_gotoffer",BTC_waitprivCfunc,0,"BTC_cleanup",0);
    instantdex_addevent(s,*n,"BOB_gotoffer","BTCprivC","BTCprivs","BOB_sentprivs"); // send privs
    instantdex_addevent(s,*n,"ALICE_gotoffer","BTCprivC","BTCprivs","ALICE_sentprivs");
   
    // to reach sentprivs, all paths must have sent/recv deck and Chose and verified cut and choose
    s = instantdex_statecreate(s,n,"BOB_sentprivs",BOB_waitfeefunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_sentprivs",ALICE_waitfunc,0,"BTC_cleanup",0);
    instantdex_addevent(s,*n,"BOB_sentprivs","feefound","BTCdeptx","BOB_sentdeposit");
    instantdex_addevent(s,*n,"ALICE_sentprivs","BTCdeptx",0,"ALICE_wait3");

    // following states cover all permutations of the three required events to make altpayment
    s = instantdex_statecreate(s,n,"ALICE_wait3",ALICE_waitfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_waitfee_privs",ALICE_waitfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_waitdeposit_privs",ALICE_waitfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_waitfee_deposit",ALICE_waitfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_waitprivs",ALICE_waitfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_waitfee",ALICE_waitfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_waitdeposit",ALICE_waitfunc,0,"BTC_cleanup",0);
    instantdex_addevent(s,*n,"ALICE_wait3","feefound",0,"ALICE_waitdeposit_privs");
    instantdex_addevent(s,*n,"ALICE_wait3","depfound",0,"ALICE_waitfee_privs");
    instantdex_addevent(s,*n,"ALICE_wait3","BTCprivs",0,"ALICE_waitfee_deposit");
   
    instantdex_addevent(s,*n,"ALICE_waitfee_privs","feefound",0,"ALICE_waitprivs");
    instantdex_addevent(s,*n,"ALICE_waitfee_privs","BTCprivs",0,"ALICE_waitfee");
   
    instantdex_addevent(s,*n,"ALICE_waitdeposit_privs","depfound",0,"ALICE_waitprivs");
    instantdex_addevent(s,*n,"ALICE_waitdeposit_privs","BTCprivs",0,"ALICE_waitdeposit");
   
    instantdex_addevent(s,*n,"ALICE_waitfee_deposit","depfound",0,"ALICE_waitfee");
    instantdex_addevent(s,*n,"ALICE_waitfee_deposit","feefound",0,"ALICE_waitdeposit");
   
    // wait for last event and send out altpayment
    instantdex_addevent(s,*n,"ALICE_waitprivs","BTCprivs","BTCalttx","ALICE_sentalt");
    instantdex_addevent(s,*n,"ALICE_waitfee","feefound","BTCalttx","ALICE_sentalt");
    instantdex_addevent(s,*n,"ALICE_waitdeposit","depfound","BTCalttx","ALICE_sentalt");

    // now Bob's turn to make sure altpayment is confirmed and send real payment
    s = instantdex_statecreate(s,n,"BOB_sentdeposit",BOB_waitBTCalttxfunc,0,"BOB_reclaim",0);
    instantdex_addevent(s,*n,"BOB_sentdeposit","BTCalttx",0,"BOB_altconfirm");
 
    s = instantdex_statecreate(s,n,"BOB_altconfirm",BOB_waitaltconfirmfunc,0,"BTC_claimdeposit",0);
    instantdex_addevent(s,*n,"BOB_altconfirm","altfound","BTCpaytx","BOB_sentpayment");
   
    // now Alice's turn to make sure payment is confrmed and send in claim or see bob's reclaim and reclaim
    s = instantdex_statecreate(s,n,"ALICE_sentalt",ALICE_waitBTCpaytxfunc,0,"BTC_claimdeposit",0);
    instantdex_addevent(s,*n,"ALICE_sentalt","BTCpaytx",0,"ALICE_waitconfirms");
   
    s = instantdex_statecreate(s,n,"ALICE_waitconfirms",ALICE_waitpayconf_or_bobreclaimfunc,0,"BTC_claimdeposit",0);
    instantdex_addevent(s,*n,"ALICE_waitconfirms","bobfound",0,"ALICE_reclaim");
    instantdex_addevent(s,*n,"ALICE_waitconfirms","payfound","BTCprivM","ALICE_claimedbtc");

    // Bob waits for privM either from Alice or alt blockchain
    s = instantdex_statecreate(s,n,"BOB_sentpayment",BOB_waitprivMfunc,0,"BTC_claimdeposit",0);
    instantdex_addevent(s,*n,"BOB_sentpayment","aclfound","BTCdone","BOB_claimedalt");
    instantdex_addevent(s,*n,"BOB_sentpayment","BTCprivM","BTCdone","BOB_claimedalt");
 

Most process functions should be self explanatory and I made it a linear flow as the protocol proceeds toward completion.

I think the following four claim states are what needs to always be atomic and with FSM we would be able to prove that either BTC_cleanup is called by both sides or BOB_claimdepositfunc and ALICE_claimaltfunc unwinds the swap or ALICE_claimbtcfunc and BOB_claimaltfunc completes the atomic swap.

James
 
legendary
Activity: 1540
Merit: 1000
February 15, 2016, 05:58:53 AM
#3
continuing from https://bitcointalksearch.org/topic/m.13881127 as it seems the OP locked it for some reason...
Thanks!!  Smiley
watched again!!  Wink
legendary
Activity: 1232
Merit: 1084
February 14, 2016, 07:51:02 PM
#2
Also, before an exchange is ready to be put into the state machine, a lot of onetime prep needs to be done and I wanted the state machine to be as pure as possible and not be cluttered with initial setup.

I notice that you have a single processing function (BOB_processfunc for Bob).  You could maybe reduce clutter by having a different handler for each state.

That is all implementation details but I realize that is half the battle.  The basic description doesn't require details on how to check signatures etc., but it is critical that each step is properly checked.

For example, the CPRKV BIP should very clearly define the formatting of the two keys.  Someone might be able to break the protocol by using badly encoded keys or something.
legendary
Activity: 1176
Merit: 1132
February 14, 2016, 06:53:32 PM
#1
continuing from https://bitcointalksearch.org/topic/m.13881127 as it seems the OP locked it for some reason...

Code:
   // Four initial states are BOB_sentoffer, ALICE_gotoffer, ALICE_sentoffer, BOB_gotoffer
    // the initiator includes signed feetx and deck of 777 keypairs
    // the responder chooses one of 777 and returns it with "BTCchose" message
    //
    // "BTC are message events from other party (message events capped at length 8)
    // "lowercas" are special events, types: , osit, payment, is altcoin claim
    // "found" means the other party's is confirmed at user specified confidence level
    // BTC_cleanup state just unwinds pending swap as nothing has been committed yet
   
    // states instantdex_statecreate(s,n,,handlerfunc,errorhandler,,
    // a given state has a couple of handlers and custom events, with timeouts and errors invoking a bypass
    s = instantdex_statecreate(s,n,"BTC_cleanup",BOB_processfunc,0,0,0);
    s = instantdex_statecreate(s,n,"BOB_claimdeposit",BOB_processfunc,0,0,0);
    s = instantdex_statecreate(s,n,"ALICE_reclaim",BOB_processfunc,0,0,0);
 
    s = instantdex_statecreate(s,n,"BOB_sentoffer",BOB_processfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"BOB_sentprivs",BOB_processfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"BOB_gotoffer",BOB_processfunc,0,"BTC_cleanup",0);
   
    s = instantdex_statecreate(s,n,"ALICE_sentoffer",ALICE_processfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_gotoffer",ALICE_processfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_sentprivs",ALICE_processfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_wait3",ALICE_processfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_waitfee_privs",ALICE_processfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_waitdeposit_privs",ALICE_processfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_waitfee_deposit",ALICE_processfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_waitprivs",ALICE_processfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_waitfee",ALICE_processfunc,0,"BTC_cleanup",0);
    s = instantdex_statecreate(s,n,"ALICE_waitdeposit",ALICE_processfunc,0,"BTC_cleanup",0);
   
    s = instantdex_statecreate(s,n,"BOB_sentdeposit",BOB_processfunc,0,"BTC_claimdeposit",0);
    s = instantdex_statecreate(s,n,"BOB_altconfirm",BOB_processfunc,0,"BTC_claimdeposit",0);
    s = instantdex_statecreate(s,n,"ALICE_sentalt",ALICE_processfunc,0,"BTC_claimdeposit",0);
    s = instantdex_statecreate(s,n,"ALICE_waitconfirms",ALICE_processfunc,0,"BTC_claimdeposit",0);
    s = instantdex_statecreate(s,n,"BOB_sentpayment",BOB_processfunc,0,"BTC_claimdeposit",0);
 
    s = instantdex_statecreate(s,n,"ALICE_claimedbtc",BOB_processfunc,0,0,0);
    s = instantdex_statecreate(s,n,"BOB_claimedalt",BOB_processfunc,0,0,0);

    // events instantdex_addevent(s,*n,,,,)
    instantdex_addevent(s,*n,"BOB_sentoffer","BTCchose","BTCprivs","BOB_sentprivs");
    instantdex_addevent(s,*n,"BOB_sentprivs","feefound","BTCdeptx","BOB_sentdeposit");
    instantdex_addevent(s,*n,"ALICE_sentoffer","BTCchose","BTCprivs","ALICE_sentprivs");
   
    // gotoffer states have sent BTCchose already
    instantdex_addevent(s,*n,"BOB_gotoffer","BTCchose","BTCprivs","BOB_sentprivs");
    instantdex_addevent(s,*n,"ALICE_gotoffer","BTCchose","BTCprivs","ALICE_sentprivs");
   
    // alice needs to wait for various items
    instantdex_addevent(s,*n,"ALICE_sentprivs","BTCdeptx",0,"ALICE_wait3");

    // following states cover all permutations of the three required events to make altpayment
    instantdex_addevent(s,*n,"ALICE_wait3","feefound",0,"ALICE_waitdeposit_privs");
    instantdex_addevent(s,*n,"ALICE_wait3","depfound",0,"ALICE_waitfee_privs");
    instantdex_addevent(s,*n,"ALICE_wait3","BTCprivs",0,"ALICE_waitfee_deposit");
   
    instantdex_addevent(s,*n,"ALICE_waitfee_privs","feefound",0,"ALICE_waitprivs");
    instantdex_addevent(s,*n,"ALICE_waitfee_privs","BTCprivs",0,"ALICE_waitfee");
   
    instantdex_addevent(s,*n,"ALICE_waitdeposit_privs","depfound",0,"ALICE_waitprivs");
    instantdex_addevent(s,*n,"ALICE_waitdeposit_privs","BTCprivs",0,"ALICE_waitdeposit");
   
    instantdex_addevent(s,*n,"ALICE_waitfee_deposit","depfound",0,"ALICE_waitfee");
    instantdex_addevent(s,*n,"ALICE_waitfee_deposit","feefound",0,"ALICE_waitdeposit");
   
    // wait for last event and send out altpayment
    instantdex_addevent(s,*n,"ALICE_waitprivs","BTCprivs","BTCalttx","ALICE_sentalt");
    instantdex_addevent(s,*n,"ALICE_waitfee","feefound","BTCalttx","ALICE_sentalt");
    instantdex_addevent(s,*n,"ALICE_waitdeposit","depfound","BTCalttx","ALICE_sentalt");

    // now Bob's turn to make sure altpayment is confirmed and send real payment
    instantdex_addevent(s,*n,"BOB_sentdeposit","BTCalttx",0,"BOB_altconfirm");
    instantdex_addevent(s,*n,"BOB_altconfirm","altfound","BTCpaytx","BOB_sentpayment");
   
    instantdex_addevent(s,*n,"ALICE_sentalt","BTCpaytx",0,"ALICE_waitconfirms");
    instantdex_addevent(s,*n,"ALICE_waitconfirms","bobfound",0,"ALICE_reclaim");
    instantdex_addevent(s,*n,"ALICE_waitconfirms","payfound","BTCprivM","ALICE_claimedbtc");
 
    // if BTCprivM doesnt come in, altcoin needs to be monitored for alice's claim
    instantdex_addevent(s,*n,"BOB_sentpayment","aclfound","BTCdone","BOB_claimedalt");
    instantdex_addevent(s,*n,"BOB_sentpayment","BTCprivM","BTCdone","BOB_claimedalt");
 

Quote
I haven't gone through it step by step but that is a good way to do it.

At any time each party is in a given state right?  Why are there 4 start states?  Shouldn't it just be that Bob is in one state and Alice is in another?

For example, Bob starts in BOB_start and Alice starts in Alice_waiting_for_trade_request, or something similar.

If a node receives an offer from another party, then it creates a thread to handle it, like a web-server right?

I guess that means that Alice effectively starts at Alice_received_trade_request, or equivalent.  Since the waiting_for_trade_request is implicit by listening on the socket.

Bob_start causes Bob to send his offer and then transition to Bob_offer_sent.

Bob_offer_sent could timeout within 30-60 seconds and cause Bob to transition to Bob_cancel_offer.  Alternatively, it Alice accepts the offer, they could transition to the fee and 777 pairs exchange.  There is no point in wasting processing if the other party isn't accepting the trade.

I guess it depends on how fine grained the state resolution should be.

Also, there could be a step where both sides decide who is Alice and who is Bob, since the person who offers the trade may not necessarily be Bob.
To avoid insanity I always designate the bitcoin side as Bob and the altcoin side as alice. That way all the directions and scripts are always the same.

Implementation wise, yes it is possible to have just one starting state for both sides, however we have the situation that either party can be the first one to place a quote in the orderbook, ie a bid or ask and this creates 4 possible starting states with 2 parties involved.

alice starts with bid, alice starts with ask, bob starts with bid, bob starts with ask.

notice that alice can be in two of these states at the same time, actually N of them as using the state machine approach each trade that is matched is its own state machine, relatively independent of others (some details like total available balance vs chance that more has been put in the orderbook than funds available, existing trades that are pending)

So that is why 4 possible starting states for when there are two sides to a trade. Internally I have two initial states that bifurcates depending on whether it is alice or bob. Also, before an exchange is ready to be put into the state machine, a lot of onetime prep needs to be done and I wanted the state machine to be as pure as possible and not be cluttered with initial setup.

James
Pages:
Jump to: