/// <summary> /// Register the specified ScriptPubKey /// </summary> /// <param name="scriptPubKey">The ScriptPubKey</param> /// <param name="isRedeemScript">If true, the P2SH of the destination's script will be tracked (Default: false)</param> /// <param name="isInternal">If true, the scriptPubKey will not belong to tracked data, typically, change addresses (Default: false)</param> /// <param name="filter">The filter in which this key will appear (http://eprint.iacr.org/2014/763.pdf)</param> /// <param name="wallet">The wallet name to which it belongs</param> public bool Add(Script scriptPubKey, bool isRedeemScript = false, bool isInternal = false, string filter = "a", string wallet = "default") { if (filter == null) { throw new ArgumentNullException("filter"); } if (wallet == null) { throw new ArgumentNullException("wallet"); } Script redeem = isRedeemScript ? scriptPubKey : null; scriptPubKey = isRedeemScript ? scriptPubKey.Hash.ScriptPubKey : scriptPubKey; var data = scriptPubKey.ToOps().First(o => o.PushData != null).PushData; var trackedScript = new TrackedScript() { ScriptPubKey = scriptPubKey, RedeemScript = redeem, AddedDate = DateTimeOffset.UtcNow, IsInternal = isInternal, Filter = filter, Wallet = wallet }; bool added = false; lock (cs) { added = _TrackedScripts.TryAdd(trackedScript.GetId(), trackedScript); } return(added); }
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 void Received(TrackedScript match, IndexedTxOut txout, ChainedBlock block, MerkleBlock proof) { var operation = new Operation(txout.Transaction, block, proof); SetUnconfirmedSeenIfPossible(txout.Transaction, block, operation); var coin = new Coin(txout); operation.ReceivedCoins.Add(Tuple.Create(coin, match.GetId())); _Operations.AddOrUpdate(operation.GetId(), operation, (k, old) => old.Merge(operation)); var trackedOutpoint = new TrackedOutpoint() { Coin = coin, TrackedScriptId = match.GetId(), Filter = match.Filter }; _TrackedOutpoints.TryAdd(trackedOutpoint.GetId(), trackedOutpoint); }
private Operation Received(TrackedScript match, IndexedTxOut txout, ChainedBlock block, MerkleBlock proof) { var operation = new Operation(txout.Transaction, block, proof, _TrackedScripts); SetUnconfirmedSeenIfPossible(txout.Transaction, block, operation); var coin = new Coin(txout); operation.ReceivedCoins.Add(Tuple.Create(coin, match.GetId())); bool merged = false; var returned = _Operations.AddOrUpdate(operation.GetId(), operation, (k, old) => old.Merge(operation, out merged)); var trackedOutpoint = new TrackedOutpoint() { Coin = coin, TrackedScriptId = match.GetId(), Filter = match.Filter }; _TrackedOutpoints.TryAdd(trackedOutpoint.GetId(), trackedOutpoint); return((operation == returned || merged) ? operation : null); }
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 bool NotifyTransaction(Transaction transaction, ChainedBlock chainedBlock, MerkleBlock proof) { if (chainedBlock != null) { if (proof == null) { throw new ArgumentNullException("proof"); } if (proof.Header.GetHash() != chainedBlock.Header.GetHash()) { throw new InvalidOperationException("The chained block and the merkle block are different blocks"); } if (!proof.PartialMerkleTree.Check(chainedBlock.Header.HashMerkleRoot)) { throw new InvalidOperationException("The MerkleBlock does not have the expected merkle root"); } if (!proof.PartialMerkleTree.GetMatchedTransactions().Contains(transaction.GetHash())) { throw new InvalidOperationException("The MerkleBlock does not contains the input transaction"); } } var interesting = false; lock (cs) { foreach (var txin in transaction.Inputs.AsIndexedInputs()) { var key = TrackedOutpoint.GetId(txin.PrevOut); TrackedOutpoint match; if (_TrackedOutpoints.TryGetValue(key, out match)) { TrackedScript parentMetadata; if (_TrackedScripts.TryGetValue(match.TrackedScriptId, out parentMetadata)) { interesting = true; Spent(parentMetadata, txin, match.Coin, chainedBlock, proof); } } } foreach (var txout in transaction.Outputs.AsIndexedOutputs()) { var key = TrackedScript.GetId(txout.TxOut.ScriptPubKey); TrackedScript match; if (_TrackedScripts.TryGetValue(key, out match)) { interesting = true; Received(match, txout, chainedBlock, proof); } } } return(interesting); }
/// <summary> /// Register the specified ScriptPubKey /// </summary> /// <param name="scriptPubKey">The ScriptPubKey</param> /// <param name="isRedeemScript">If true, the P2SH of the destination's script will be tracked (Default: false)</param> /// <param name="isInternal">If true, the scriptPubKey will not belong to tracked data, typically, change addresses (Default: false)</param> /// <param name="filter">The filter in which this key will appear (http://eprint.iacr.org/2014/763.pdf)</param> /// <param name="wallet">The wallet name to which it belongs</param> public bool Add(Script scriptPubKey, bool isRedeemScript = false, bool isInternal = false, string filter = "a", string wallet = "default") { if(filter == null) throw new ArgumentNullException("filter"); if(wallet == null) throw new ArgumentNullException("wallet"); Script redeem = isRedeemScript ? scriptPubKey : null; scriptPubKey = isRedeemScript ? scriptPubKey.Hash.ScriptPubKey : scriptPubKey; var data = scriptPubKey.ToOps().First(o => o.PushData != null).PushData; var trackedScript = new TrackedScript() { ScriptPubKey = scriptPubKey, RedeemScript = redeem, AddedDate = DateTimeOffset.UtcNow, IsInternal = isInternal, Filter = filter, Wallet = wallet }; bool added = false; lock(cs) { added = _TrackedScripts.TryAdd(trackedScript.GetId(), trackedScript); } return added; }
private Operation Received(TrackedScript match, IndexedTxOut txout, ChainedBlock block, MerkleBlock proof) { var operation = new Operation(txout.Transaction, block, proof, _TrackedScripts); SetUnconfirmedSeenIfPossible(txout.Transaction, block, operation); var coin = new Coin(txout); operation.ReceivedCoins.Add(Tuple.Create(coin, match.GetId())); bool merged = false; var returned = _Operations.AddOrUpdate(operation.GetId(), operation, (k, old) => old.Merge(operation, out merged)); var trackedOutpoint = new TrackedOutpoint() { Coin = coin, TrackedScriptId = match.GetId(), Filter = match.Filter }; _TrackedOutpoints.TryAdd(trackedOutpoint.GetId(), trackedOutpoint); return (operation == returned || merged) ? operation : null; }
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; }