Two-Phased TransactionsTwo-Phased Transactions is multisig transactions implementation in Nxt but much more powerful.
Simplest example, Alice starts a Two-Phased transaction. In the first stage a transaction is included in a blockchain but it isn’t processed immediately and has the status of ‘pending’. For it to be processed, Bob has to complete the second phase of the transaction by approving it. This has to be done before the deadline set by Alice has elapsed.
Use cases* Bob approving a transaction of Alice
* Shareholders voting whether to send another 1M Nxt to a marketing service or not
* Nxt whales voting on whether to pay bounty or not
* Multisig wallet protected from a hacker(think about BTER case etc)
Features* any kind of transaction could be 2-phased
* M-of-N consensus or by-balance consensus or shareholders voting to release transaction
* possible vote threshold setting(e.g. only accounts with 1M+ Nxt or 100+ assets balance could vote)
* whitelist of voters
* blacklist of voters
* transaction could be released only prior to maxHeight
Options* MaxHeight - transaction has to be released before the mandatory height provided or it will be cancelled
* whitelist - list of accounts able to vote on transaction releasing. Max 10 accounts. If no given, any account has a right to vote! Mandatory for by-account voting
* blacklist - list of accounts voting is prohibited for. Only for by-balance & by-asset voting. Couldn't be combined with whitelist(so pending transaction submitter has to choose whether to use whitelist or blacklist).
* Voting option: by account, by balance, by asset.
* Consensus quorum - transaction released when gathered
* Vote threshold - min balance to vote. Only for by-balance & by-asset voting.
Example: accounts A(balance = 1000 nxt),B(700 nxt),C(400 nxt),D(200 nxt) are able to vote. Vote threshold is 300 nxt, so D can't vote. Consensus quorum is 1500 nxt, so transaction will be released only if A & B vote on this. The example doesn't take money transfers & heights into account.
Voting, Multivoting, CountingIt's possible to vote for multiple (max 10) pending transactions withing one voting transaction. It gives
possibility for trustless escrows etc.
In case of by-account(M-out-of-N) voting a pending transaction will be released on block Mth vote being including into a blockchain.
In case of by-balance or by-asset voting following algorithm is applied:
* votes weights are stored into database
* on getting a vote if vote weight + cached weights >= quorum weights rechecking with database update is taking place. if sum(updated weights) >=
quorum transaction is going to be released
* on maxHeight block there's is a final recheck
* this algo means in some cases of balances moving pending transaction could be released on maxHeight only
Trustless escrowsWith 2-phased transactions some kinds of trustless escrows are possible. E.g.
Tx 1. Alice publishes into blockchain a pending transaction to Bob which will be released only when both Alice and Bob vote for it
Tx 2. Bob publishes into blockchain a pending transaction to Alice which will be released only when both Alice and Bob vote for it
Tx 3. Alice generates transaction bytes for a multivote transaction with votes for both transactions 1 & 2 & sends unsigned transaction bytes, the full transaction hash, and the signature hash to Bob
Tx 4. Bob sends to the unconfirmed transactions pool a transaction with votes for both transactions 1 & 2 & reference to hash of transaction #3
See
https://nxtforum.org/general/trustless-escrows-are-coming!/ for details
ImplementationTo implement 2-phased transactions, 1 new Appendix type & 2 new Transaction types are needed.
* TwoPhased appendix to each type of transaction will mark 2-phased transactions from ordinary ones. Appendix parameters will specify max height to gather consensus to release transaction & poll options(by-account / by-balance / by asset voting), consensus quorum,
list of accounts able to vote, max 10)
* PENDING_PAYMENT_VOTE_CASTING transaction type to for transaction(s) to release (if an account doesn't want this, it should skip voting at all). Max 10 votes possible, so voter can vote up to 10 pending transactions at once. Transaction will be released when quorum(specified by threshold) will be gathered. It will be cancelled if no consensus being gathered @ height maxHeight provided in pending transaction params.
Java APILet's consider sort of classic example: Alice pays 50 Nxts to Chris, but only after Bob's approval and within 30 blocks after pending transaction issuance. Please note TransactionBuilder got `twoPhased` method which accepts `TwoPhased` appendix object. We use `TwoPhased` constructor accepting maxHeight, voting model, quorum, vote threshold, whitelist, blacklist as params. Scala language is used, but code is very like Java in the example.
val Fee = Constants.ONE_NXT
val h = Nxt.getBlockchain.getHeight
val tb = Nxt.getTransactionProcessor.newTransactionBuilder(alicePubKey, 50*Fee, Fee, defaultDeadline, Attachment.ORDINARY_PAYMENT)
tb.twoPhased(new TwoPhased(h+30, Constants.VOTING_MODEL_ACCOUNT, 1, 0, Array[Long](voterId), null))
tb.recipientId(chrisId)
val tx = tb.build()
tx.sign(alicePhrase)
Nxt.getTransactionProcessor.broadcast(tx)
Now Bob's turn to vote on transaction:
val vatt = new Attachment.PendingPaymentVoteCasting(tx.getId)
val vtb = Nxt.getTransactionProcessor.newTransactionBuilder(bobPubKey, 0, Fee, defaultDeadline, vatt)
val vtx = vtb.build()
vtx.sign(bobPhrase)
Nxt.getTransactionProcessor.broadcast(vtx)
And on block height when transaction is going into the blockchain balance of Chris is increasing by 50 Nxt
(if this height within 30 blocks after Alice's transaction block).
HTTP APIFrom now every kind of API call creating a transaction has additional parameters:
* pendingVotingModel - mandatory - could be 0,1 or 2 according to following constants:
public static final byte VOTING_MODEL_BALANCE = 0;
public static final byte VOTING_MODEL_ACCOUNT = 1;
public static final byte VOTING_MODEL_ASSET = 2;
* pendingMaxHeight - mandatory - height to refuse transaction if there's no quorum @ this height. Not less than
10 blocks from current height.
* pendingQuorum - mandatory - number of accounts/total Nxt/assets balance to get transaction released
* pendingMinBalance - optional - vote threshold. 0 if skipped
* pendingAssetId - mandatory if pendingVotingModel == 2 (e.g. by-asset voting)
* pendingWhitelisted - mandatory if by-account voting, provide multiple values if needed (e.g. `pendingWhitelisted=${account1Id}&pendingWhitelisted=${account2Id}`)
* pendingBlacklisted - optional, couldn't be combined with whitelist, provide multiple values if needed
Example:
Poll will be created only after approval of the account 7926777737834261541:
curl -d 'name=cryptos&description=rate+cryptos+you+like&finishHeight=112000&votingModel=1&minNumberOfOptions=1&maxNumberOfOptions=2&minRangeValue=-5&maxRangeValue=5&secretPhrase=secret+phrase&deadline=1000&feeNQT=1000000000&option1=nxt&option2=btc&isPending=true&pendingVotingModel=1&pendingMaxHeight=111800&pendingQuorum=1&pendingWhitelisted=7926777737834261541' http://localhost:6876/nxt?requestType=createPoll
Also there are some new API calls to get pending transactions, for now just:
* GetAccountPendingTransactionIds - to get pending transactions issued by some account. Possible parameters are "account", "finished", "firstIndex", "lastIndex", where "finished" could be empty or skipped.
* GetAccountPendingTransactionToSignIds - to get pending transactions where account is whitelisted. Parameters are the same as above.
* GetAssetPendingTransactionIds - to get pending transactions where some asset mentioned. Parameters are as above but "asset" instead of "account".
FeesIn case of by-balance & by-account voting pending transaction should be a subject for a higher fee probably,
as a lot of computations could be needed on vote processing. For now fee is standard (i.e. 1 Nxt) though.