So I'm in the process of implementing a BTC-based payment module where for every transaction to a non-wallet account a fraction of the amount will end up to a charity account in a external wallet not controlled by this module.

A typical round for that would be:

  • The module receives the payment from user
  • It forwards the 90% (this percentage is arbitary) of the amount to its final destination (e.g. a merchant)
  • It now has to forward the remaining 10% to the charity of the user's choice

In a lower level, the system:

  • Receives a transaction TxFromUser from the user with an amount of X BTC
  • Waits until it gets 6 confirmations
  • Creates a new raw transaction, TxToMerchant to forward the payment to the merchant
  • Creates another raw transaction TxToCharity to forward the donation to the charity

Going a bit deeper:

TxToMerchant:

  • Create new raw transaction
  • Add new input: TxFromUser
  • Add new output: Address: Merchant's address, Amount: 0.9 * TxFromUser.Amount
  • Add new output: Address: Module's own wallet address, Amount: 0.1 * TxFromUser.Amount
  • Calculate the fee for this transaction
  • Subtract the fee from the second output's amount
  • Create the transaction's hex and sign it with the right key
  • Send the transaction and get its id: TxToMerchant.Id

TxToCharity:

  • Wait for the above transaction (TxToMerchant) to get confirmed
  • Create a new raw transaction
  • Add new input: TxToMerchant (this will be the change we asked for above)
  • Add new output: Address: Charity's address, Amount: TxToMerchant.Amount = 0.1 * TxFromUser.Amount
  • Calculate the fee for this transaction
  • Subtract the fee from transaction's output amount
  • Create the transaction's hex and sign it with the right key
  • Send the transaction and get its id: TxToCharity.Id

I am aware of the fact that I could merge these two transactions (TxToMerchant and TxToCharity) into a single transaction, however for various reasons (business requirement) let's just say that this is not possible at the moment.

The issue I have with the above implementation is this: waiting for the TxToMerchant to confirm creates a lag, as I cannot forward the payment to the charity TxToCharity until TxToMerchant is confirmed (or can I, without having to worry about transaction malleability etc?).

On top of that, when the time comes to add the TxToCharity's input I have to keep track of how the change was returned in TxToMerchant and then get the right unspent transaction (where listunspent.txid = TxToMerchant.Id), is there a more efficient and less error-prone way to do this?

Let's suppose that the user wants to split the payment between 2 merchants (or a merchant and a freight service, which makes more sense), so in the above example there would be 1 more transaction like TxToMerchant, let's call it TxToFreightService. Let's say now that TxToMerchant goes trough well and gets confirmed but TxToFreightService fails and never gets confirmed because the input used for it was a double-spend regardless the 6 confirmations we got (for its input) before processing it. TxToCharity depends on TxToFreightService because the requested change in TxToFreightService will serve as the input to TxToCharity. How do I deal with this scenario programmatically without having to perform corrections by hand every single time this happens?

up vote 2 down vote accepted

I think your business process is confusing the issue. I'm going to assume that the "business" side of this also wants to take a cut of the transaction or it wants to delay paying the charity and that is why this has become more complicated.

There are a number of considerations not least the fact that you are using one input to pay the merchant, and the change to pay the freight, and the change of that to pay the charity.

What you are concerned about is the inability that you have built-in to pay the one party because of a preceding ttransaction, but that's your business process at fault not the Bitcoin protocol.

You should also consider the minimum payment amount and the eventual network fee, neither of which are %age based.

These are not mentioned and in fact by making two (or possibly four) transactions you are incurring up to 4x the bitcoin network transaction fees.

This is one of the main reasons why (from a business perspective) you should not split the transactions up ie it is more expensive and who is going to wear the costs? The charity? the merchant? the freight? You?

Can I suggest also that you have misunderstood the "confirmations" as something other than your transaction being included in a block. When a transaction is requested by a peer prior to it being included in a block - the peer validates the transaction independently, and if for any reason it is not good it is rejected. This is NOT the process of "confirmation".

All peers in effect will do the same validation to your transaction as it propagates through the network (which BTW is extremely fast).

Confirmation on the other hand is when the transaction has been included in a block, and the only time this becomes an issue is if there is a fork in the blockchain. But even then you still can rebroadcast a transaction if the "other fork" becomes the final one provided the basis on which it was made is good.

The point I want to make is that you are placing too much emphasis on confirmations for transactions that you yourself have created, and then wait until someone else confirms what you already know to be true, and this seems completely pointless.

Perhaps you can expand your question to explain the "business reasons"?

  • +1 For the extensive analysis. The delayed payments to the charities and the freight services is where the revenue stream is being generated by. I am fully aware that this is not a bitcoin protocol issue, however I am positive that more entrepreneurs who will want to make use of the built-in credit capabilities will face the same issues. The fees are included in our model (although not mentioned above) and dust payments will not qualify and will be forwarded intact to the merchant. – Doug Peters Mar 13 '14 at 14:09
  • 1
    Regarding the confirmations I also had the same opinion as you until I stumbled upon some veterans' posts that made it clear that we shouldn't assume that just because we created transactions based on change from a previous in-wallet transaction that this change is safe to spend. Please take a look here: reddit.com/r/Bitcoin/comments/1xm49o/… – Doug Peters Mar 13 '14 at 14:13
  • @DougPeters it's not that you have to wait to spend previous in-wallet transactions, it's that you are obliged to. Otherwise no subsequent transaction will validate. On a side note, you are probably on slippery ground if you think that Bitcoin can support any form of credit. You will immediately find yourself up against a competitor who offers immediate distribution, just because they can. It's an arguable point, but not one I would like to be trying to make work;) – T9b Mar 13 '14 at 20:11
  • With raw transactions you can send a payment that has as input unconfirmed change so I'm not really obliged to wait, the thing is that this is not really a good practice. Bitcoin already supports a form of credit with the use of escrow, I decided to take this into my application, but again let's stick to the main answer's questions for now. – Doug Peters Mar 13 '14 at 20:51

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.