public TrustedBroadcastRequest CreateOfferRedeemTransaction(FeeRate feeRate, Script redeemDestination) { var coin = CreateUnsignedOfferTransaction().Outputs.AsCoins().First().ToScriptCoin(CreateOfferScript()); var unknownOutpoints = new OutPoint(uint256.Zero, 0); Transaction tx = new Transaction(); tx.LockTime = CreateOfferScriptParameters().Expiration; tx.Inputs.Add(new TxIn(unknownOutpoints)); tx.Inputs[0].Sequence = 0; tx.Outputs.Add(new TxOut(coin.Amount, redeemDestination)); tx.Inputs[0].ScriptSig = new Script(OpcodeType.OP_0) + Op.GetPushOp(coin.Redeem.ToBytes()); var vSize = tx.GetVirtualSize() + 80; // Size without signature + the signature size tx.Outputs[0].Value -= feeRate.GetFee(vSize); var redeemTransaction = new TrustedBroadcastRequest { Key = InternalState.RedeemKey, PreviousScriptPubKey = coin.Redeem.Hash.ScriptPubKey, Transaction = tx }; //Strip redeem script information so we check if TrustedBroadcastRequest can sign correctly redeemTransaction.Transaction = redeemTransaction.ReSign(new Coin(unknownOutpoints, coin.TxOut)); return(redeemTransaction); }
public void Broadcast(string label, TrustedBroadcastRequest broadcast) { if (broadcast == null) { throw new ArgumentNullException(nameof(broadcast)); } var address = broadcast.PreviousScriptPubKey.GetDestinationAddress(RPCClient.Network); if (address == null) { throw new NotSupportedException("ScriptPubKey to track not supported"); } if (TrackPreviousScriptPubKey) { RPCClient.ImportAddress(address, label + " (PreviousScriptPubKey)", false); } var height = RPCClient.GetBlockCount(); var record = new Record(); record.Label = label; //3 days expiration record.Expiration = height + (int)(TimeSpan.FromDays(3).Ticks / Network.Main.Consensus.PowTargetSpacing.Ticks); record.Request = broadcast; AddBroadcast(record); if (height < broadcast.BroadcastAt.Height) { return; } _Broadcaster.Broadcast(record.Label, broadcast.Transaction); }
public TrustedBroadcastRequest CreateOfferRedeemTransaction(FeeRate feeRate) { Transaction tx = new Transaction(); tx.LockTime = EscrowScriptPubKeyParameters.GetFromCoin(InternalState.EscrowedCoin).LockTime; tx.Inputs.Add(new TxIn()); tx.Inputs[0].Sequence = 0; tx.Outputs.Add(new TxOut(InternalState.OfferCoin.Amount, InternalState.RedeemDestination)); tx.Inputs[0].ScriptSig = new Script( Op.GetPushOp(TrustedBroadcastRequest.PlaceholderSignature), Op.GetPushOp(InternalState.OfferCoin.Redeem.ToBytes())); tx.Inputs[0].Witnessify(); var virtualSize = tx.HasWitness ? tx.GetVirtualSize(_Network.Consensus.Options.WitnessScaleFactor) : tx.GetSerializedSize(); tx.Outputs[0].Value -= feeRate.GetFee(virtualSize); var redeemTransaction = new TrustedBroadcastRequest { Key = InternalState.EscrowKey, PreviousScriptPubKey = InternalState.OfferCoin.ScriptPubKey, Transaction = tx }; return(redeemTransaction); }
public void TrustedBroadcast(int cycleStart, TransactionType transactionType, uint correlation, TrustedBroadcastRequest broadcast) { }
public void Broadcast(int cycleStart, TransactionType transactionType, CorrelationId correlation, TrustedBroadcastRequest broadcast) { if (broadcast == null) { throw new ArgumentNullException(nameof(broadcast)); } if (broadcast.Key != null && !broadcast.Transaction.Inputs.Any(i => i.PrevOut.IsNull)) { throw new InvalidOperationException("One of the input should be null"); } var address = broadcast.PreviousScriptPubKey?.GetDestinationAddress(RPCClient.Network); if (address != null && TrackPreviousScriptPubKey) { RPCClient.ImportAddress(address, "", false); } var height = _Cache.BlockCount; var record = new Record(); //3 days expiration after now or broadcast date var expirationBase = Math.Max(height, broadcast.BroadcastableHeight); record.Expiration = expirationBase + (int)(TimeSpan.FromDays(3).Ticks / RPCClient.Network.Consensus.TargetSpacing.Ticks); record.Request = broadcast; record.TransactionType = transactionType; record.Cycle = cycleStart; record.Correlation = correlation; Logs.Broadcasters.LogInformation($"Planning to broadcast {record.TransactionType} of cycle {record.Cycle} on block {record.Request.BroadcastableHeight}"); AddBroadcast(record); }
public void Broadcast(int cycleStart, NTumbleBit.Services.TransactionType transactionType, CorrelationId correlation, TrustedBroadcastRequest broadcast) { if (broadcast == null) { throw new ArgumentNullException(nameof(broadcast)); } if (broadcast.Key != null && !broadcast.Transaction.Inputs.Any(i => i.PrevOut.IsNull)) { throw new InvalidOperationException("One of the input should be null"); } var address = broadcast.PreviousScriptPubKey?.GetDestinationAddress(this.tumblingState.TumblerNetwork); if (address != null && TrackPreviousScriptPubKey) { this.tumblingState.watchOnlyWalletManager.WatchAddress(address.ScriptPubKey.GetDestinationAddress(this.tumblingState.TumblerNetwork).ToString()); } var height = _Cache.BlockCount; var record = new Record(); //3 days expiration after now or broadcast date var expirationBase = Math.Max(height, broadcast.BroadcastableHeight); record.Expiration = expirationBase + (int)(TimeSpan.FromDays(3).Ticks / this.tumblingState.TumblerNetwork.Consensus.PowTargetSpacing.Ticks); record.Request = broadcast; record.TransactionType = transactionType; record.Cycle = cycleStart; record.Correlation = correlation; AddBroadcast(record); }