Skip to content

Commit

Permalink
AND-5492 Retrieve only the necessary inputs for the UTXO transaction.
Browse files Browse the repository at this point in the history
  • Loading branch information
Yoggam1 committed Dec 7, 2023
1 parent 464b681 commit 547f6cd
Showing 1 changed file with 24 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import java.math.BigInteger

open class BitcoinTransactionBuilder(
private val walletPublicKey: ByteArray, blockchain: Blockchain,
walletAddresses: Set<com.tangem.blockchain.common.address.Address> = emptySet()
walletAddresses: Set<com.tangem.blockchain.common.address.Address> = emptySet(),
) {
private val walletScripts =
walletAddresses.filterIsInstance<BitcoinScriptAddress>().map { it.script }
Expand All @@ -51,9 +51,10 @@ open class BitcoinTransactionBuilder(
return Result.Failure(BlockchainSdkError.CustomError("Unspent outputs are missing"))
}

val change: BigDecimal = calculateChange(transactionData, unspentOutputs!!)
val outputsToSend = getOutputsToSend(unspentOutputs!!, transactionData)
val change: BigDecimal = calculateChange(transactionData, outputsToSend)
transaction =
transactionData.toBitcoinJTransaction(networkParameters, unspentOutputs!!, change)
transactionData.toBitcoinJTransaction(networkParameters, outputsToSend, change)

val hashesToSign = MutableList(transaction.inputs.size) { byteArrayOf() }
for (input in transaction.inputs) {
Expand Down Expand Up @@ -81,7 +82,7 @@ open class BitcoinTransactionBuilder(
transaction.hashForWitnessSignature(
index,
scriptToSign,
Coin.parseCoin(unspentOutputs!![index].amount.toPlainString()),
Coin.parseCoin(outputsToSend[index].amount.toPlainString()),
Transaction.SigHash.ALL,
false
).bytes
Expand Down Expand Up @@ -156,7 +157,7 @@ open class BitcoinTransactionBuilder(

fun calculateChange(
transactionData: TransactionData,
unspentOutputs: List<BitcoinUnspentOutput>
unspentOutputs: List<BitcoinUnspentOutput>,
): BigDecimal {
val fullAmount = unspentOutputs.map { it.amount }.reduce { acc, number -> acc + number }
return fullAmount - (transactionData.amount.value!! + (transactionData.fee?.amount?.value
Expand All @@ -170,6 +171,23 @@ open class BitcoinTransactionBuilder(
return TransactionSignature(r, canonicalS)
}

private fun getOutputsToSend(
unspentOutputs: List<BitcoinUnspentOutput>,
transactionData: TransactionData,
): List<BitcoinUnspentOutput> {
val outputs = mutableListOf<BitcoinUnspentOutput>()
val amount = transactionData.amount.value!! + transactionData.fee?.amount?.value!!
var sum = BigDecimal.ZERO
var i = 0
while (sum <= amount && i < unspentOutputs.size) {
val output = unspentOutputs[i]
sum = sum.plus(output.amount)
outputs.add(output)
i++
}
return outputs
}

private fun findSpendingScript(scriptPubKey: Script): Script {
val scriptHash = ScriptPattern.extractHashFromP2SH(scriptPubKey)
return when (scriptHash.size) {
Expand All @@ -187,7 +205,7 @@ open class BitcoinTransactionBuilder(
internal fun TransactionData.toBitcoinJTransaction(
networkParameters: NetworkParameters?,
unspentOutputs: List<BitcoinUnspentOutput>,
change: BigDecimal
change: BigDecimal,
): Transaction {
val transaction = Transaction(networkParameters)
for (utxo in unspentOutputs) {
Expand Down

0 comments on commit 547f6cd

Please sign in to comment.