La función combinerawtransaction no funciona

Tengo varias transacciones parcialmente firmadas que quiero combinar en una transacción. Todas esas transacciones se firmaron con la misma clave, por lo que debería ser posible combinar todas las firmas parciales en una transacción combinada que se pueda firmar y transmitir a la vez con una clave. De acuerdo con la función rpc de bitcoin, combinerawtransactiones la adecuada para usar en mi caso, pero esa función no funciona porque, en lugar de combinar todas las transacciones parciales firmadas en una, solo devuelve la primera transacción parcial firmada (no importa el orden de la matriz, es devolverá siempre el primer elemento)

Aquí tiene la forma en que estoy tratando de combinar dos direcciones firmadas parciales:

bitcoin-cli combinerawtransaction '["020000000001014a05cf2073d4ee6aa61256159e421d9f12291c44fc9607d99a4045ab192a580a01000000232200209acb3925f27bec7d8ac16b49705f6d47d5b87d48dc8571d3f49b10dcc7d89051ffffffff037cb002000000000016001488427232a9085b4ab6c334c6115725765864a6ad521d000000000000160014c2fe1292769b585b91fb8b045c651d79398589cc540700000000000016001454c64819279b8cc3e78e5f2be7b9121f1caa2386040047304402207abf6df0650b8723677d493b182e742a8dddd89ad1ee8eaa1c65a9b559841ecb022052fe5bcad01702e0e73c3b34cbfef957ba8e4744d614104f5d8fbc3d57cad4ce010069522103f6de61c401c947aad006ba9dbfdaad795e77be06972a3fb7308e70049d4026db2103e33af80b92e4efd64852166d6126e10aafdcc741579c67c6aa9eb89080cebeb221029791c6e3f0dc5bfa63db3f5aa0066badd6c5608d2a75394124d14df78795178153ae00000000", "02000000000101419e71a8980f8b86890a249e69bc9461f677dbefe4c856eb38baa361f0121d070000000023220020a8c4e11c15bcc878d57238016fe896c586508c913e0b300d80fa9409b031efb7ffffffff037cb002000000000016001488427232a9085b4ab6c334c6115725765864a6ad521d000000000000160014c2fe1292769b585b91fb8b045c651d79398589cc540700000000000016001454c64819279b8cc3e78e5f2be7b9121f1caa23860400473044022061b31eb92fb0555d368c2349ef9584df89bfc573a37acfd0bbf2de18d6cb51420220785706c33d3b7b735e434decddf1520ce687b168d17b40527da2712a3634f42f010069522103f6de61c401c947aad006ba9dbfdaad795e77be06972a3fb7308e70049d4026db2103e33af80b92e4efd64852166d6126e10aafdcc741579c67c6aa9eb89080cebeb221027152e86c82d162b47684a52cd9e74ed57b9fc2295531d8da6a560a7a602357fc53ae00000000"]'

El comando anterior se ejecuta sin ningún error y devuelve la siguiente transacción:

02000000000101419e71a8980f8b86890a249e69bc9461f677dbefe4c856eb38baa361f0121d070000000023220020a8c4e11c15bcc878d57238016fe896c586508c913e0b300d80fa9409b031efb7ffffffff037cb002000000000016001488427232a9085b4ab6c334c6115725765864a6ad521d000000000000160014c2fe1292769b585b91fb8b045c651d79398589cc540700000000000016001454c64819279b8cc3e78e5f2be7b9121f1caa23860400473044022061b31eb92fb0555d368c2349ef9584df89bfc573a37acfd0bbf2de18d6cb51420220785706c33d3b7b735e434decddf1520ce687b168d17b40527da2712a3634f42f010069522103f6de61c401c947aad006ba9dbfdaad795e77be06972a3fb7308e70049d4026db2103e33af80b92e4efd64852166d6126e10aafdcc741579c67c6aa9eb89080cebeb221027152e86c82d162b47684a52cd9e74ed57b9fc2295531d8da6a560a7a602357fc53ae00000000

Y esa transacción sin procesar es exactamente la primera transacción sin procesar pasada en la matriz para combinar la función de transacción sin procesar y devuelta sin modificar

Estoy un poco perdido porque no sé qué está pasando con no tener ambas transacciones combinadas. Además, estoy usando bitcoin testnet, puedo firmar y transmitir esas transacciones individualmente pero no puedo combinarlas en una sola, cualquier ayuda será apreciada

Pasos para reproducir cómo creé esas transacciones sin procesar:

  1. En primer lugar, creo una dirección multisig 2-3:
$participants = [];
$participants[] = "03e33af80b92e4efd64852166d6126e10aafdcc741579c67c6aa9eb89080cebeb2";//pubkey1
$participants[] = "03f6de61c401c947aad006ba9dbfdaad795e77be06972a3fb7308e70049d4026db";//pubkey2
$participants[] = "029791c6e3f0dc5bfa63db3f5aa0066badd6c5608d2a75394124d14df787951781";//pubkey3

$res = $this->bitcoin->addmultisigaddress($participants, $pubkey_str);
$multisig_address = $res["address"];
$redeemScript = $res["redeemScript"];
$this->bitcoin->importaddress($multisig_address, "", false); // I import the multisig address so I can check incoming transactions

El código anterior es para crear la dirección multisig asociada a la primera transacción sin procesar, para crear la dirección multisig asociada a la segunda transacción, repita los mismos pasos pero cambiando la tercera clave pública para esto.027152e86c82d162b47684a52cd9e74ed57b9fc2295531d8da6a560a7a602357fc

  1. Una vez que creé ambas direcciones multisig, procedo a enviar algunos fondos a ambas direcciones multisig. Puede verificar ambos txids: 0a582a19ab45409ad90796fc441c29129f1d429e155612a66aeed47320cf054ay 071d12f061a3ba38eb56c8e4efdb77f66194bc699e240a89868b0f98a8719e41(respectivamente). Para financiar ambas direcciones, acabo de abrir una cuenta de testnet usando electrum y gasté algo de btc testnet.

  2. Ahora, el siguiente paso es crear transacciones firmadas parciales (usando terceras claves públicas). Para eso, necesito verificar las salidas no gastadas y crear una transacción sin procesar basada en esos datos.

$res = $this->bitcoin->listunspent(2, 9999999, json_decode('["'.$multisig_address.'"]'));
$fee = 0.00002;
$total_amount = 0.00;
$total_amount = 0.00;
$txids = [];
$vouts = [];
$amounts = [];
$scriptPubs = [];
for($i=0; $i<count($transactions); $i++){
    $txids[] = $transactions[$i]["txid"];
    $total_amount+=$transactions[$i]["amount"];
    $vouts[] = $transactions[$i]["vout"];
    $amounts[] = $transactions[$i]["amount"];
    $scriptPubs[] = $transactions[$i]["scriptPubKey"];
}

$amount1 = 0.00176252;
$amount2 = 0.00007506;
$amount3 = 0.00001876;

$address1 = "tb1q3pp8yv4fppd54dkrxnrpz4e9wevxff4d2v3r6e";
$address2 = "tb1qctlp9ynkndv9hy0m3vz9cega0yuctzwv6z273w";
$address3 = "tb1q2nrysxf8nwxv8euwtu470wgjruw25guxkal3wd";

$inputs = '[';
for($j=0; $j<count($vouts); $j++){
    $inputs.='{
                        "txid": "'.$txids[$j].'",
                        "vout": '.$vouts[$j].'
                      }';
    if($j+1!=count($vouts)){
        $inputs.=',';
    }
}
$inputs.=']';

$outputs = '{"'.$address1.'": '.$amount1.', "'.$address2.'": '.$amount2.', "'.$address3.'": '.$amount3.'}';

$rawtransaction = $this->bitcoin->createrawtransaction(json_decode($inputs), json_decode($outputs));

$prevtxs = '[';
for($j=0; $j<count($txids); $j++){
    $prevtxs .= '{
                    "txid": "'.$txids[$j].'",
                    "vout": '.$vouts[$j].',
                    "scriptPubKey": "'.$scriptPubs[$j].'", 
                    "redeemScript": "'.$redeemScript.'",
                    "amount": '.$amounts[$j].'
                  }';
    if($j+1!=count($txids)){
        $prevtxs.=',';
    }
}
$prevtxs.=']';

$private_key = $this->dumpKey($pubkey3_privkey); // replace this value with cTe9h3HqgqC7wzUsVVw7hgoPkBNLUuChZNB7aKFsSYeTi5MYcABX or cQon9MgHPoAj3wBU8ne2BVaThTuRkXvb9FUFyQdjePUrYWTjdCaE
        $partially_signed = $this->signrawtransactionwithkey($rawtransaction, json_decode('["'.$private_key.'"]'), json_decode($prevtxs))["hex"]; // and in this step I get the transaction hex string

En caso de que tenga un nodo bitcoin con testnet blockchain, puede verificar que pubkey1 ( cPkPnf3qhf1AALzroHixPTYBq2cLQ9HLs9fvkTsS82ccBGZDHFaV) o pubkey2 ( cQmzvzai8ft574ErkUH7nPVcP2SbR7xaPurKigWGPYVbhfMop9ia) pueden firmar transacciones sin formato firmadas parcialmente

¿Cómo creaste esas transacciones? Ayudará a intentar reproducir el problema.
@Prayank Permítanme unos minutos y subiré todos los pasos detallados
@Prayank Listo! Lo estaba probando usando un pequeño script php, pero aún así creo que el código es lo suficientemente claro, también traté de mantenerlo lo más simple posible sin eliminar ninguna información. Si ves que me falta algo para combinar esas transacciones, házmelo saber :) ¡Gracias!

Respuestas (1)

El problema aquí es que las dos transacciones son diferentes y combinerawtransactionno operan en transacciones diferentes (aparentemente, simplemente no hace nada en silencio). Parece que espera combinerawtransactiontomar dos transacciones separadas y crear una nueva que tenga las entradas y salidas de ambas transacciones. (o tal vez tomar dos transacciones con los mismos resultados pero diferentes entradas y producir una transacción con las entradas combinadas y las mismas salidas). Sin embargo, eso no es lo que hace. En su lugar, en realidad toma la misma transacción (es decir, las mismas entradas y salidas) y fusiona las firmas de las mismas entradas.

No es posible hacer lo que desea porque las firmas se comprometen con las entradas y salidas particulares de esa transacción. Una vez que intenta unir una transacción con otra, esas firmas se vuelven inválidas y será necesario volver a firmar toda la transacción.

¡Gracias por su respuesta! Lo siento si estoy haciendo preguntas estúpidas y obvias, pero estoy aprendiendo a crear y manejar transacciones sin procesar. Ahora, gracias por su explicación, entiendo que la función fusiona firmas y las vuelve inválidas. Mi intención es hacer un proceso multisig más fácil entre diferentes partes, si necesita firmar varias transacciones multisig, me gustaría que pueda firmar varias transacciones a la vez (para que no necesite firmar una transacción y transmitirla, repitiendo el proceso para todas sus transacciones). ¿Es eso posible? ¿Quizás usando createpsbty combinepsbt?
¿O debería repetir todo el proceso anterior pero incluyendo todas las entradas y salidas en la misma transacción?
Debe incluir todas las entradas y salidas en la misma transacción cuando la crea.
¡Bueno, gracias! ¡Funcionó combinando todas las entradas y salidas en una sola transacción!