Publicación
Comparte tu conocimiento.
¿Cómo puedo enviar Bitcoin de una dirección de Taproot a otra?
Creé una dirección bitcoin principal (bech32m) y envié 1 UTXO desde una dirección segwit que no era taproot (bech32) a esta dirección principal. ¿Cómo escribiría un script de c# para enviar este btc a otra dirección principal? No necesito nada demasiado complicado, solo un script simple para enviar este btc de una dirección principal a otra. Creo que Bitcoin sería el paquete más sensato de usar.
Encontré esto en una de las pruebas de NBitcoin:
public async Task CanBuildTaprootSingleSigTransactions()
{
using (var nodeBuilder = NodeBuilderEx.Create())
{
var rpc = nodeBuilder.CreateNode().CreateRPCClient();
nodeBuilder.StartAll();
rpc.Generate(102);
var change = new Key();
var rootKey = new ExtKey();
var accountKeyPath = new KeyPath("86'/0'/0'");
var accountRootKeyPath = new RootedKeyPath(rootKey.GetPublicKey().GetHDFingerPrint(), accountKeyPath);
var accountKey = rootKey.Derive(accountKeyPath);
var key = accountKey.Derive(new KeyPath("0/0")).PrivateKey;
var address = key.PubKey.GetAddress(ScriptPubKeyType.TaprootBIP86, nodeBuilder.Network);
var destination = new Key();
var amount = new Money(1, MoneyUnit.BTC);
uint256 id = null;
Transaction tx = null;
ICoin coin = null;
TransactionBuilder builder = null;
var rate = new FeeRate(Money.Satoshis(1), 1);
async Task RefreshCoin()
{
id = await rpc.SendToAddressAsync(address, Money.Coins(1));
tx = await rpc.GetRawTransactionAsync(id);
coin = tx.Outputs.AsCoins().Where(o => o.ScriptPubKey == address.ScriptPubKey).Single();
builder = Network.Main.CreateTransactionBuilder(0);
}
await RefreshCoin();
var signedTx = builder
.AddCoins(coin)
.AddKeys(key)
.Send(destination, amount)
.SubtractFees()
.SetChange(change)
.SendEstimatedFees(rate)
.BuildTransaction(true);
rpc.SendRawTransaction(signedTx);
await RefreshCoin();
// Let's try again, but this time with PSBT
var psbt = builder
.AddCoins(coin)
.Send(destination, amount)
.SubtractFees()
.SetChange(change)
.SendEstimatedFees(rate)
.BuildPSBT(false);
var tk = key.PubKey.GetTaprootFullPubKey();
psbt.Inputs[0].HDTaprootKeyPaths.Add(tk.OutputKey, new TaprootKeyPath(accountRootKeyPath.Derive(KeyPath.Parse("0/0"))));
psbt.SignAll(ScriptPubKeyType.TaprootBIP86, accountKey, accountRootKeyPath);
// Check if we can roundtrip
psbt = CanRoundtripPSBT(psbt);
psbt.Finalize();
rpc.SendRawTransaction(psbt.ExtractTransaction());
// Let's try again, but this time with BuildPSBT(true)
await RefreshCoin();
psbt = builder
.AddCoins(coin)
.AddKeys(key)
.Send(destination, amount)
.SubtractFees()
.SetChange(change)
.SendEstimatedFees(rate)
.BuildPSBT(true);
psbt.Finalize();
rpc.SendRawTransaction(psbt.ExtractTransaction());
// Let's try again, this time with a merkle root
var merkleRoot = RandomUtils.GetUInt256();
address = key.PubKey.GetTaprootFullPubKey(merkleRoot).GetAddress(nodeBuilder.Network);
await RefreshCoin();
psbt = builder
.AddCoins(coin)
.AddKeys(key.CreateTaprootKeyPair(merkleRoot))
.Send(destination, amount)
.SubtractFees()
.SetChange(change)
.SendEstimatedFees(rate)
.BuildPSBT(true);
Assert.NotNull(psbt.Inputs[0].TaprootMerkleRoot);
Assert.NotNull(psbt.Inputs[0].TaprootInternalKey);
Assert.NotNull(psbt.Inputs[0].TaprootKeySignature);
psbt = CanRoundtripPSBT(psbt);
psbt.Finalize();
rpc.SendRawTransaction(psbt.ExtractTransaction());
// Can we sign the PSBT separately?
await RefreshCoin();
psbt = builder
.AddCoins(coin)
.Send(destination, amount)
.SubtractFees()
.SetChange(change)
.SendEstimatedFees(rate)
.BuildPSBT(false);
var taprootKeyPair = key.CreateTaprootKeyPair(merkleRoot);
psbt.Inputs[0].Sign(taprootKeyPair);
Assert.NotNull(psbt.Inputs[0].TaprootMerkleRoot);
Assert.NotNull(psbt.Inputs[0].TaprootInternalKey);
Assert.NotNull(psbt.Inputs[0].TaprootKeySignature);
// This line is useless, we just use it to test the PSBT roundtrip
psbt.Inputs[0].HDTaprootKeyPaths.Add(taprootKeyPair.PubKey,
new TaprootKeyPath(RootedKeyPath.Parse("12345678/86'/0'/0'/0/0"),
new uint256[] { RandomUtils.GetUInt256() }));
psbt = CanRoundtripPSBT(psbt);
psbt.Finalize();
rpc.SendRawTransaction(psbt.ExtractTransaction());
// Can we sign the transaction separately?
await RefreshCoin();
var coin1 = coin;
await RefreshCoin();
var coin2 = coin;
builder = Network.Main.CreateTransactionBuilder(0);
signedTx = builder
.AddCoins(coin1, coin2)
.Send(destination, amount)
.SubtractFees()
.SetChange(change)
.SendEstimatedFees(rate)
.BuildTransaction(false);
var unsignedTx = signedTx.Clone();
builder = Network.Main.CreateTransactionBuilder(0);
builder.AddKeys(key.CreateTaprootKeyPair(merkleRoot));
builder.AddCoins(coin1);
var ex = Assert.Throws<InvalidOperationException>(() => builder.SignTransactionInPlace(signedTx));
Assert.Contains("taproot", ex.Message);
builder.AddCoin(coin2);
builder.SignTransactionInPlace(signedTx);
Assert.True(!WitScript.IsNullOrEmpty(signedTx.Inputs.FindIndexedInput(coin2.Outpoint).WitScript));
// Another solution is to set the precomputed transaction data.
signedTx = unsignedTx;
builder = Network.Main.CreateTransactionBuilder(0);
builder.AddKeys(key.CreateTaprootKeyPair(merkleRoot));
builder.AddCoins(coin2);
builder.SetSigningOptions(new SigningOptions() { PrecomputedTransactionData = signedTx.PrecomputeTransactionData(new ICoin[] { coin1, coin2 }) });
builder.SignTransactionInPlace(signedTx);
Assert.True(!WitScript.IsNullOrEmpty(signedTx.Inputs.FindIndexedInput(coin2.Outpoint).WitScript));
// Let's check if we estimate precisely the size of a taproot transaction.
await RefreshCoin();
signedTx = builder
.AddCoins(coin)
.AddKeys(key.CreateTaprootKeyPair(merkleRoot))
.Send(destination, amount)
.SubtractFees()
.SetChange(change)
.SendEstimatedFees(rate)
.BuildTransaction(false);
var actualvsize = builder.EstimateSize(signedTx, true);
builder.SignTransactionInPlace(signedTx);
var expectedvsize = signedTx.GetVirtualSize();
// The estimator can't assume the sighash to be default
// for all inputs, so we likely overestimate 1 bytes per input
Assert.Equal(expectedvsize, actualvsize - 1);
}
}
Pero no puedo entender cómo escribir una aplicación de consola C# simple en el formato:
class Program
{
static async Task Main()
...
}
Tengo la clave privada, así como la frase mnemotécnica completa para la clave privada, de la dirección bitcoin principal (bech32m) que financié con 1 UTXO. ¿Cómo escribiría una sencilla aplicación de consola de C# que transfiera este código utxo a otra dirección principal?
Y por favor, licencie su solución en el MIT.
- blockchain
- cryptocurrency
Sabes la respuesta?
Inicie sesión y compártalo.
Web3 (also known as Web 3.0) is an idea for a new iteration of the World Wide Web which incorporates concepts such as decentralization, blockchain technologies, and token-based economics.
Gana tu parte de 1000 Sui
Gana puntos de reputación y obtén recompensas por ayudar a crecer a la comunidad de Sui.

- 0xduckmove... SUI+88
1
- harry phan... SUI+61
2
- MiniBob... SUI+57
3
- ... SUIHaGiang+56
- ... SUIRogue+47
- ... SUIRogueRig+44
- ... SUIPeera Admin+25
- ... SUIVens.sui+20
- ... SUIMarlKey+20
- ... SUIdudley_smith+16