1
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
TxFromUserfrom the user with an amount ofXBTC - Waits until it gets 6 confirmations
- Creates a new raw transaction,
TxToMerchantto forward the payment to the merchant - Creates another raw transaction
TxToCharityto 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?
+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 – 2014-03-13T14:09:11.303
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: http://www.reddit.com/r/Bitcoin/comments/1xm49o/due_to_active_malleable_transaction_relayers_it/
– Doug Peters – 2014-03-13T14:13:25.627@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 – 2014-03-13T20:11:14.127
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 – 2014-03-13T20:51:03.733