void LoadCore(Stream stream) { lock (cs) { _Operations.Clear(); _TrackedOutpoints.Clear(); _TrackedScripts.Clear(); JObject obj = JObject.Load(new JsonTextReader(new StreamReader(stream)) { DateParseHandling = DateParseHandling.DateTimeOffset }); _Tweak = (uint)(long)obj["Tweak"]; var operations = (JArray)obj["Operations"]; foreach (var operation in operations.OfType <JObject>()) { var op = Operation.FromJson(operation, _TrackedScripts); _Operations.TryAdd(op.GetId(), op); } var outpoints = (JArray)obj["Outpoints"]; foreach (var outpoint in outpoints.OfType <JObject>()) { var op = TrackedOutpoint.FromJson(outpoint); _TrackedOutpoints.TryAdd(op.GetId(), op); } var scripts = (JArray)obj["Scripts"]; foreach (var script in scripts.OfType <JObject>()) { var op = TrackedScript.FromJson(script); _TrackedScripts.TryAdd(op.GetId(), op); } } }
/// <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 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); }
internal static TrackedScript FromJson(JObject obj) { TrackedScript script = new TrackedScript(); script.ScriptPubKey = Script.FromBytesUnsafe(Encoders.Hex.DecodeData((string)obj["ScriptPubKey"])); var redeem = (string)obj["RedeemScript"]; if (redeem != null) { script.RedeemScript = Script.FromBytesUnsafe(Encoders.Hex.DecodeData((string)obj["RedeemScript"])); } script.AddedDate = obj["AddedDate"].Value <DateTimeOffset>(); script.Filter = (string)obj["Filter"]; script.Wallet = (string)obj["Wallet"]; return(script); }
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); }
/// <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; }
internal static TrackedScript FromJson(JObject obj) { TrackedScript script = new TrackedScript(); script.ScriptPubKey = Script.FromBytesUnsafe(Encoders.Hex.DecodeData((string)obj["ScriptPubKey"])); var redeem = (string)obj["RedeemScript"]; if(redeem != null) { script.RedeemScript = Script.FromBytesUnsafe(Encoders.Hex.DecodeData((string)obj["RedeemScript"])); } script.AddedDate = obj["AddedDate"].Value<DateTimeOffset>(); script.Filter = (string)obj["Filter"]; script.Wallet = (string)obj["Wallet"]; return script; }
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; }