private bool VerifyScript(IndexedTxIn input, Script scriptPubKey, Money value, ScriptVerify scriptVerify, out ScriptError error) { #if !NOCONSENSUSLIB if (!UseConsensusLib) #endif { if (input.Transaction is IHasForkId) { scriptVerify |= Scripting.ScriptVerify.ForkId; } return(input.VerifyScript(scriptPubKey, value, scriptVerify, out error)); } #if !NOCONSENSUSLIB if (input.Transaction is IHasForkId) { scriptVerify |= (ScriptVerify)(1U << 16); } var ok = Script.VerifyScriptConsensus(scriptPubKey, input.Transaction, input.Index, scriptVerify); if (!ok) { if (input.VerifyScript(scriptPubKey, scriptVerify, out error)) { error = ScriptError.UnknownError; } return(false); } error = ScriptError.OK; return(true); #endif }
private bool VerifyScript(IndexedTxIn input, Script scriptPubKey, Money value, ScriptVerify scriptVerify, out ScriptError error) { #if !NOCONSENSUSLIB if (!UseConsensusLib) #endif return(input.VerifyScript(scriptPubKey, value, scriptVerify, out error)); #if !NOCONSENSUSLIB else { var ok = Script.VerifyScriptConsensus(scriptPubKey, input.Transaction, input.Index, scriptVerify); if (!ok) { if (input.VerifyScript(scriptPubKey, scriptVerify, out error)) { error = ScriptError.UnknownError; } return(false); } else { error = ScriptError.OK; } return(true); } #endif }
public ScriptPolicyError(IndexedTxIn input, ScriptError error, ScriptVerify scriptVerify, Script scriptPubKey) : base("Script error on input " + input.Index + " (" + error + ")", input) { _ScriptError = error; _ScriptVerify = scriptVerify; _ScriptPubKey = scriptPubKey; }
private void Spent(TrackedScript metadata, IndexedTxIn txin, Coin coin, ChainedBlock block, MerkleBlock proof) { var operation = new Operation(txin.Transaction, block, proof); operation.SpentCoins.Add(Tuple.Create(coin, metadata.GetId())); SetUnconfirmedSeenIfPossible(txin.Transaction, block, operation); _Operations.AddOrUpdate(operation.GetId(), operation, (k, old) => old.Merge(operation)); }
private Operation Spent(TrackedScript metadata, IndexedTxIn txin, Coin coin, ChainedBlock block, MerkleBlock proof) { var operation = new Operation(txin.Transaction, block, proof, _TrackedScripts); operation.SpentCoins.Add(Tuple.Create(coin, metadata.GetId())); SetUnconfirmedSeenIfPossible(txin.Transaction, block, operation); bool merged = false; var returned = _Operations.AddOrUpdate(operation.GetId(), operation, (k, old) => old.Merge(operation, out merged)); return((operation == returned || merged) ? operation : null); }
public byte[][] UntrustedHashTransactionInputStart(bool newTransaction, IndexedTxIn txIn, TrustedInput[] trustedInputs) { List <byte[]> apdus = new List <byte[]>(); trustedInputs = trustedInputs ?? new TrustedInput[0]; // Start building a fake transaction with the passed inputs MemoryStream data = new MemoryStream(); BufferUtils.WriteBuffer(data, txIn.Transaction.Version); VarintUtils.write(data, txIn.Transaction.Inputs.Count); apdus.Add(CreateAPDU(LedgerWalletConstants.LedgerWallet_CLA, LedgerWalletConstants.LedgerWallet_INS_HASH_INPUT_START, (byte)0x00, (newTransaction ? (byte)0x00 : (byte)0x80), data.ToArray())); // Loop for each input long currentIndex = 0; foreach (var input in txIn.Transaction.Inputs) { var trustedInput = trustedInputs.FirstOrDefault(i => i.OutPoint == input.PrevOut); byte[] script = (currentIndex == txIn.Index ? txIn.TxIn.ScriptSig.ToBytes() : new byte[0]); data = new MemoryStream(); if (trustedInput != null) { data.WriteByte(0x01); var b = trustedInput.ToBytes(); // untrusted inputs have constant length data.WriteByte((byte)b.Length); BufferUtils.WriteBuffer(data, b); } else { data.WriteByte(0x00); BufferUtils.WriteBuffer(data, input.PrevOut); } VarintUtils.write(data, script.Length); apdus.Add(CreateAPDU(LedgerWalletConstants.LedgerWallet_CLA, LedgerWalletConstants.LedgerWallet_INS_HASH_INPUT_START, (byte)0x80, (byte)0x00, data.ToArray())); data = new MemoryStream(); BufferUtils.WriteBuffer(data, script); BufferUtils.WriteBuffer(data, input.Sequence); apdus.AddRange(CreateAPDUSplit(LedgerWalletConstants.LedgerWallet_CLA, LedgerWalletConstants.LedgerWallet_INS_HASH_INPUT_START, (byte)0x80, (byte)0x00, data.ToArray())); currentIndex++; } return(apdus.ToArray()); }
private bool VerifyScript(IndexedTxIn input, TxOut spentOutput, ScriptVerify scriptVerify, out ScriptError error) { #if !NOCONSENSUSLIB if (!UseConsensusLib) #endif { if (input.Transaction is IHasForkId) { scriptVerify |= NBitcoin.ScriptVerify.ForkId; } return(input.VerifyScript(spentOutput, scriptVerify, out error)); } #if !NOCONSENSUSLIB else { if (input.Transaction is IHasForkId) { scriptVerify |= (NBitcoin.ScriptVerify)(1U << 16); } var ok = Script.VerifyScriptConsensus(spentOutput.ScriptPubKey, input.Transaction, input.Index, scriptVerify); if (!ok) { if (input.VerifyScript(spentOutput, scriptVerify, out error)) { error = ScriptError.UnknownError; } return(false); } else { error = ScriptError.OK; } return(true); } #endif }
private bool VerifyScript(IndexedTxIn input, Script scriptPubKey, Money value, ScriptVerify scriptVerify, out ScriptError error) { if (!this.UseConsensusLib) { return(input.VerifyScript(this.network, scriptPubKey, value, scriptVerify, out error)); } else { bool ok = Script.VerifyScriptConsensus(scriptPubKey, input.Transaction, input.Index, scriptVerify); if (!ok) { if (input.VerifyScript(this.network, scriptPubKey, scriptVerify, out error)) { error = ScriptError.UnknownError; } return(false); } else { error = ScriptError.OK; } return(true); } }
public InputPolicyError(string message, IndexedTxIn txIn) : base(message) { _OutPoint = txIn.PrevOut; _InputIndex = txIn.Index; }
public bool Check(PubKey pubKey, Script scriptPubKey, IndexedTxIn txIn, ScriptVerify verify = ScriptVerify.Standard) { return(Check(pubKey, scriptPubKey, txIn.Transaction, txIn.Index, verify)); }
private void Sign(TransactionSigningContext ctx, ICoin coin, IndexedTxIn txIn) { var input = txIn.TxIn; if(coin is StealthCoin) { var stealthCoin = (StealthCoin)coin; var scanKey = FindKey(ctx, stealthCoin.Address.ScanPubKey.ScriptPubKey); if(scanKey == null) throw new KeyNotFoundException("Scan key for decrypting StealthCoin not found"); var spendKeys = stealthCoin.Address.SpendPubKeys.Select(p => FindKey(ctx, p.ScriptPubKey)).Where(p => p != null).ToArray(); ctx.AdditionalKeys.AddRange(stealthCoin.Uncover(spendKeys, scanKey)); var normalCoin = new Coin(coin.Outpoint, coin.TxOut); if(stealthCoin.Redeem != null) normalCoin = normalCoin.ToScriptCoin(stealthCoin.Redeem); coin = normalCoin; } var scriptSig = CreateScriptSig(ctx, coin, txIn); if(scriptSig == null) return; ScriptCoin scriptCoin = coin as ScriptCoin; Script signatures = null; if(coin.GetHashVersion() == HashVersion.Witness) { signatures = txIn.WitScript; if(scriptCoin != null) { if(scriptCoin.IsP2SH) txIn.ScriptSig = Script.Empty; if(scriptCoin.RedeemType == RedeemType.WitnessV0) signatures = RemoveRedeem(signatures); } } else { signatures = txIn.ScriptSig; if(scriptCoin != null && scriptCoin.RedeemType == RedeemType.P2SH) signatures = RemoveRedeem(signatures); } signatures = CombineScriptSigs(coin, scriptSig, signatures); if(coin.GetHashVersion() == HashVersion.Witness) { txIn.WitScript = signatures; if(scriptCoin != null) { if(scriptCoin.IsP2SH) txIn.ScriptSig = new Script(Op.GetPushOp(scriptCoin.GetP2SHRedeem().ToBytes(true))); if(scriptCoin.RedeemType == RedeemType.WitnessV0) txIn.WitScript = txIn.WitScript + new WitScript(Op.GetPushOp(scriptCoin.Redeem.ToBytes(true))); } } else { txIn.ScriptSig = signatures; if(scriptCoin != null && scriptCoin.RedeemType == RedeemType.P2SH) { txIn.ScriptSig = input.ScriptSig + Op.GetPushOp(scriptCoin.GetP2SHRedeem().ToBytes(true)); } } }
private Script CreateScriptSig(TransactionSigningContext ctx, ICoin coin, IndexedTxIn txIn) { var scriptPubKey = coin.GetScriptCode(); var keyRepo = new TransactionBuilderKeyRepository(this, ctx); var signer = new TransactionBuilderSigner(coin, ctx.SigHash, txIn); foreach(var extension in Extensions) { if(extension.CanGenerateScriptSig(scriptPubKey)) { return extension.GenerateScriptSig(scriptPubKey, keyRepo, signer); } } throw new NotSupportedException("Unsupported scriptPubKey"); }
public TransactionBuilderSigner(ICoin coin, SigHash sigHash, IndexedTxIn txIn) { this.coin = coin; this.sigHash = sigHash; this.txIn = txIn; }
public void UntrustedHashTransactionInputStart(bool newTransaction, IndexedTxIn txIn, TrustedInput[] trustedInputs) { using(Transport.Lock()) { trustedInputs = trustedInputs ?? new TrustedInput[0]; // Start building a fake transaction with the passed inputs MemoryStream data = new MemoryStream(); BufferUtils.WriteBuffer(data, txIn.Transaction.Version); VarintUtils.write(data, txIn.Transaction.Inputs.Count); ExchangeApdu(LedgerWalletConstants.LedgerWallet_CLA, LedgerWalletConstants.LedgerWallet_INS_HASH_INPUT_START, (byte)0x00, (newTransaction ? (byte)0x00 : (byte)0x80), data.ToArray(), OK); // Loop for each input long currentIndex = 0; foreach(var input in txIn.Transaction.Inputs) { var trustedInput = trustedInputs.FirstOrDefault(i => i.OutPoint == input.PrevOut); byte[] script = (currentIndex == txIn.Index ? txIn.TxIn.ScriptSig.ToBytes() : new byte[0]); data = new MemoryStream(); if(trustedInput != null) { data.WriteByte(0x01); var b = trustedInput.ToBytes(); // untrusted inputs have constant length data.WriteByte((byte)b.Length); BufferUtils.WriteBuffer(data, b); } else { data.WriteByte(0x00); BufferUtils.WriteBuffer(data, input.PrevOut); } VarintUtils.write(data, script.Length); ExchangeApdu(LedgerWalletConstants.LedgerWallet_CLA, LedgerWalletConstants.LedgerWallet_INS_HASH_INPUT_START, (byte)0x80, (byte)0x00, data.ToArray(), OK); data = new MemoryStream(); BufferUtils.WriteBuffer(data, script); BufferUtils.WriteBuffer(data, input.Sequence); ExchangeApduSplit(LedgerWalletConstants.LedgerWallet_CLA, LedgerWalletConstants.LedgerWallet_INS_HASH_INPUT_START, (byte)0x80, (byte)0x00, data.ToArray(), OK); currentIndex++; } } }
private ScriptSigs GetScriptSigs(IndexedTxIn indexedTxIn) { return new ScriptSigs() { ScriptSig = indexedTxIn.ScriptSig, WitSig = indexedTxIn.WitScript }; }
private bool VerifyScript(IndexedTxIn input, Script scriptPubKey, Money value, ScriptVerify scriptVerify, out ScriptError error) { return(input.VerifyScript(scriptPubKey, value, scriptVerify, out error)); }
static void Main(string[] args) { // parameters var walletPath = "/home/lontivero/.walletwasabi/client/Wallets/REAL.json"; var txHex = File.ReadAllText("tx.hex"); var index = 56; var tx = Transaction.Parse(txHex); tx.Inputs[index].WitScript = null; IndexedTxIn currentIndexedInput = tx.Inputs.AsIndexedInputs().Skip(index).First(); // 4. Find the corresponding registered input. Coin registeredCoin; TxOut output = null; OutPoint prevOut = tx.Inputs[index].PrevOut; using (var client = new HttpClient{BaseAddress = new Uri("https://api.smartbit.com.au/v1/")}) { using (HttpResponseMessage response = client.GetAsync($"blockchain/tx/{prevOut.Hash}/hex").GetAwaiter().GetResult()) { string cont = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); var json = JObject.Parse(cont); string hex = json["hex"][0]["hex"].ToString(); Transaction ttx = Transaction.Parse(hex, Network.Main); output = ttx.Outputs[prevOut.N]; registeredCoin = new Coin(prevOut, output); } } var km = KeyManager.FromFile(walletPath); var keys = km.GetSecrets("", registeredCoin.ScriptPubKey); var pass = false; while(!pass) { var builder = Network.Main.CreateTransactionBuilder(); var signedCoinJoin = builder .ContinueToBuild(tx) .AddKeys( keys.ToArray()) .AddCoins( registeredCoin ) .BuildTransaction(true); var w = signedCoinJoin.Inputs.Where(x=> x.WitScript != WitScript.Empty).FirstOrDefault(); tx.Inputs[index].WitScript = signedCoinJoin.Inputs[index].WitScript; // 5. Verify if currentIndexedInput is correctly signed, if not, return the specific error. #if CONSENSUS if (!Script.VerifyScriptConsensus(output.ScriptPubKey, tx, (uint)index, output.Value, ScriptVerify.Standard)) { Console.WriteLine($"Error"); } #else if (!currentIndexedInput.VerifyScript(registeredCoin, out ScriptError error)) { Console.WriteLine($"Error: {error}"); } } pass = true; #endif }
private bool VerifyScript(IndexedTxIn input, Script scriptPubKey, Money value, ScriptVerify scriptVerify, out ScriptError error) { #if !NOCONSENSUSLIB if(!UseConsensusLib) #endif return input.VerifyScript(scriptPubKey, value, scriptVerify, out error); #if !NOCONSENSUSLIB else { var ok = Script.VerifyScriptConsensus(scriptPubKey, input.Transaction, input.Index, scriptVerify); if(!ok) { if(input.VerifyScript(scriptPubKey, scriptVerify, out error)) error = ScriptError.UnknownError; return false; } else { error = ScriptError.OK; } return true; } #endif }
public CoinNotFoundException(IndexedTxIn txIn) : base("No coin matching " + txIn.PrevOut + " was found") { _OutPoint = txIn.PrevOut; _InputIndex = txIn.Index; }
public DuplicateInputPolicyError(IndexedTxIn[] duplicated) : base("Duplicate input " + duplicated[0].PrevOut) { _OutPoint = duplicated[0].PrevOut; _InputIndices = duplicated.Select(d => d.Index).ToArray(); }
private async Task ModifyScriptSigAndVerifySignature(Task <TransactionSignature> sigTask, SignatureRequest previousReq, IndexedTxIn input) { var pubkey = previousReq.PubKey ?? (await GetWalletPubKeyAsync(previousReq.KeyPath).ConfigureAwait(false)).UncompressedPublicKey.Compress(); var sig = await sigTask.ConfigureAwait(false); }
public CoinNotFoundPolicyError(IndexedTxIn txIn) : base("No coin matching " + txIn.PrevOut + " was found", txIn) { _TxIn = txIn; }
public async Task <IActionResult> PostSignaturesAsync([FromQuery, Required] string uniqueId, [FromQuery, Required] long roundId, [FromBody, Required] IDictionary <int, string> signatures) { if (roundId < 0 || !signatures.Any() || signatures.Any(x => x.Key < 0 || string.IsNullOrWhiteSpace(x.Value)) || !ModelState.IsValid) { return(BadRequest()); } (CoordinatorRound round, Alice alice) = GetRunningRoundAndAliceOrFailureResponse(roundId, uniqueId, RoundPhase.Signing, out IActionResult returnFailureResponse); if (returnFailureResponse != null) { return(returnFailureResponse); } // Check if Alice provided signature to all her inputs. if (signatures.Count != alice.Inputs.Count()) { return(BadRequest("Alice did not provide enough witnesses.")); } RoundPhase phase = round.Phase; switch (phase) { case RoundPhase.Signing: { using (await SigningLock.LockAsync()) { foreach (var signaturePair in signatures) { int index = signaturePair.Key; WitScript witness = null; try { witness = new WitScript(signaturePair.Value); } catch (Exception ex) { return(BadRequest($"Malformed witness is provided. Details: {ex.Message}")); } int maxIndex = round.UnsignedCoinJoin.Inputs.Count - 1; if (maxIndex < index) { return(BadRequest($"Index out of range. Maximum value: {maxIndex}. Provided value: {index}")); } // Check duplicates. if (round.SignedCoinJoin.Inputs[index].HasWitScript()) { return(BadRequest("Input is already signed.")); } // Verify witness. // 1. Copy UnsignedCoinJoin. Transaction cjCopy = Transaction.Parse(round.UnsignedCoinJoin.ToHex(), Network); // 2. Sign the copy. cjCopy.Inputs[index].WitScript = witness; // 3. Convert the current input to IndexedTxIn. IndexedTxIn currentIndexedInput = cjCopy.Inputs.AsIndexedInputs().Skip(index).First(); // 4. Find the corresponding registered input. Coin registeredCoin = alice.Inputs.Single(x => x.Outpoint == cjCopy.Inputs[index].PrevOut); // 5. Verify if currentIndexedInput is correctly signed, if not, return the specific error. if (!currentIndexedInput.VerifyScript(registeredCoin, out ScriptError error)) { return(BadRequest($"Invalid witness is provided. {nameof(ScriptError)}: {error}.")); } // Finally add it to our CJ. round.SignedCoinJoin.Inputs[index].WitScript = witness; } alice.State = AliceState.SignedCoinJoin; await round.BroadcastCoinJoinIfFullySignedAsync(); } return(NoContent()); } default: { TryLogLateRequest(roundId, RoundPhase.Signing); return(Conflict($"CoinJoin can only be requested from Signing phase. Current phase: {phase}.")); } } }
private CoinNotFoundException CoinNotFound(IndexedTxIn txIn) { return new CoinNotFoundException(txIn); }
public BitcoinBasedTxPoint(IndexedTxIn input) { _input = input ?? throw new ArgumentNullException(nameof(input)); }
private Operation Spent(TrackedScript metadata, IndexedTxIn txin, Coin coin, ChainedBlock block, MerkleBlock proof) { var operation = new Operation(txin.Transaction, block, proof, _TrackedScripts); operation.SpentCoins.Add(Tuple.Create(coin, metadata.GetId())); SetUnconfirmedSeenIfPossible(txin.Transaction, block, operation); bool merged = false; var returned = _Operations.AddOrUpdate(operation.GetId(), operation, (k, old) => old.Merge(operation, out merged)); return (operation == returned || merged) ? operation : null; }
public byte[][] UntrustedHashTransactionInputStart( InputStartType startType, IndexedTxIn txIn, Dictionary <OutPoint, TrustedInput> trustedInputs, Dictionary <OutPoint, ICoin> coins, bool segwitMode, bool segwitParsedOnce) { List <byte[]> apdus = new List <byte[]>(); trustedInputs = trustedInputs ?? new Dictionary <OutPoint, TrustedInput>(); // Start building a fake transaction with the passed inputs MemoryStream data = new MemoryStream(); BufferUtils.WriteBuffer(data, txIn.Transaction.Version); if (segwitMode && segwitParsedOnce) { VarintUtils.write(data, 1); } else { VarintUtils.write(data, txIn.Transaction.Inputs.Count); } apdus.Add(CreateAPDU(LedgerWalletConstants.LedgerWallet_CLA, LedgerWalletConstants.LedgerWallet_INS_HASH_INPUT_START, (byte)0x00, (byte)startType, data.ToArray())); // Loop for each input long currentIndex = 0; foreach (var input in txIn.Transaction.Inputs) { if (segwitMode && segwitParsedOnce && currentIndex != txIn.Index) { currentIndex++; continue; } byte[] script = new byte[0]; if (currentIndex == txIn.Index || segwitMode && !segwitParsedOnce) { script = coins[input.PrevOut].GetScriptCode().ToBytes(); } data = new MemoryStream(); if (segwitMode) { data.WriteByte(0x02); BufferUtils.WriteBuffer(data, input.PrevOut); BufferUtils.WriteBuffer(data, Utils.ToBytes((ulong)coins[input.PrevOut].TxOut.Value.Satoshi, true)); } else { var trustedInput = trustedInputs[input.PrevOut]; if (trustedInput != null) { data.WriteByte(0x01); var b = trustedInput.ToBytes(); // untrusted inputs have constant length data.WriteByte((byte)b.Length); BufferUtils.WriteBuffer(data, b); } else { data.WriteByte(0x00); BufferUtils.WriteBuffer(data, input.PrevOut); } } VarintUtils.write(data, script.Length); apdus.Add(CreateAPDU(LedgerWalletConstants.LedgerWallet_CLA, LedgerWalletConstants.LedgerWallet_INS_HASH_INPUT_START, (byte)0x80, (byte)0x00, data.ToArray())); data = new MemoryStream(); BufferUtils.WriteBuffer(data, script); BufferUtils.WriteBuffer(data, input.Sequence); apdus.AddRange(CreateAPDUSplit(LedgerWalletConstants.LedgerWallet_CLA, LedgerWalletConstants.LedgerWallet_INS_HASH_INPUT_START, (byte)0x80, (byte)0x00, data.ToArray())); currentIndex++; } return(apdus.ToArray()); }
public bool Check(PubKey pubKey, Script scriptPubKey, IndexedTxIn txIn, ScriptVerify verify = ScriptVerify.Standard) { return Check(pubKey, scriptPubKey, txIn.Transaction, txIn.Index, verify); }
private bool VerifyScript(IndexedTxIn input, Script scriptPubKey, ScriptVerify scriptVerify, out ScriptError error) { if(!UseConsensusLib) return input.VerifyScript(scriptPubKey, scriptVerify, out error); else { var ok = Script.VerifyScriptConsensus(scriptPubKey, input.Transaction, input.Index, scriptVerify); if(!ok) { if(input.VerifyScript(scriptPubKey, scriptVerify, out error)) error = ScriptError.UnknownError; return false; } else { error = ScriptError.OK; } return true; } }
public ICoin FindSignableCoin(IndexedTxIn txIn) { var coin = FindCoin(txIn.PrevOut); if(coin is IColoredCoin) coin = ((IColoredCoin)coin).Bearer; if(coin == null || coin is ScriptCoin || coin is StealthCoin) return coin; var hash = ScriptCoin.GetRedeemHash(coin.TxOut.ScriptPubKey); if(hash != null) { var redeem = _ScriptPubKeyToRedeem.TryGet(coin.TxOut.ScriptPubKey); if(redeem != null && PayToWitScriptHashTemplate.Instance.CheckScriptPubKey(redeem)) redeem = _ScriptPubKeyToRedeem.TryGet(redeem); if(redeem == null) { if(hash is WitScriptId) redeem = PayToWitScriptHashTemplate.Instance.ExtractWitScriptParameters(txIn.WitScript, (WitScriptId)hash); if(hash is ScriptId) { var parameters = PayToScriptHashTemplate.Instance.ExtractScriptSigParameters(txIn.ScriptSig, (ScriptId)hash); if(parameters != null) redeem = parameters.RedeemScript; } } if(redeem != null) return new ScriptCoin(coin, redeem); } return coin; }