public bool TryGetTransaction(UInt256 txHash, out UnconfirmedTx unconfirmedTx) { using (var handle = this.cursorCache.TakeItem()) { var cursor = handle.Item.Item; return(cursor.TryGetTransaction(txHash, out unconfirmedTx)); } }
public bool TryGetTransaction(UInt256 txHash, out UnconfirmedTx unconfirmedTx) { using (var handle = this.cursorCache.TakeItem()) { var cursor = handle.Item.Item; return cursor.TryGetTransaction(txHash, out unconfirmedTx); } }
public bool TryAddTransaction(UnconfirmedTx unconfirmedTx) { CheckWriteTransaction(); try { unconfirmedTxes.Modify(x => x.Add(unconfirmedTx.Hash, unconfirmedTx)); // update index of txes spending each input's prev tx for (var inputIndex = 0; inputIndex < unconfirmedTx.Transaction.Inputs.Length; inputIndex++) { var input = unconfirmedTx.Transaction.Inputs[inputIndex]; unconfirmedTxesByPrevTxOutputKey.Modify(_ => { }); ImmutableDictionary<UInt256, UnconfirmedTx>.Builder unconfirmedTxes; if (unconfirmedTxesByPrevTxOutputKey.Value.TryGetValue(input.PrevTxOutputKey, out unconfirmedTxes)) // ensure a copy of the builder is modified or underlying storage will see uncomitted state unconfirmedTxes = unconfirmedTxes.ToImmutable().ToBuilder(); else unconfirmedTxes = ImmutableDictionary.CreateBuilder<UInt256, UnconfirmedTx>(); unconfirmedTxes.Add(unconfirmedTx.Hash, unconfirmedTx); unconfirmedTxesByPrevTxOutputKey.Value[input.PrevTxOutputKey] = unconfirmedTxes; } return true; } catch (ArgumentException) { return false; } }
public bool TryGetTransaction(UInt256 txHash, out UnconfirmedTx unconfimedTx) { CheckTransaction(); return unconfirmedTxes.Value.TryGetValue(txHash, out unconfimedTx); }
public UnconfirmedTxAddedEventArgs(UnconfirmedTx unconfirmedTx) { UnconfirmedTx = unconfirmedTx; }
public bool TryAddTransaction(DecodedTx decodedTx) { if (ContainsTransaction(decodedTx.Hash)) // unconfirmed tx already exists return false; var tx = decodedTx.Transaction; UnconfirmedTx unconfirmedTx; // allow concurrent transaction adds if underlying storage supports it // in either case, lock waits for block add/rollback to finish if (storageManager.IsUnconfirmedTxesConcurrent) updateLock.EnterReadLock(); else updateLock.EnterWriteLock(); try { using (var chainState = coreDaemon.GetChainState()) { // verify each input is available to spend var prevTxOutputKeys = new HashSet<TxOutputKey>(); var prevTxOutputs = ImmutableArray.CreateBuilder<PrevTxOutput>(tx.Inputs.Length); var inputValue = 0UL; for (var inputIndex = 0; inputIndex < tx.Inputs.Length; inputIndex++) { var input = tx.Inputs[inputIndex]; if (!prevTxOutputKeys.Add(input.PrevTxOutputKey)) // tx double spends one of its own inputs return false; UnspentTx unspentTx; if (!chainState.TryGetUnspentTx(input.PrevTxHash, out unspentTx)) // input's prev output does not exist return false; if (input.PrevTxOutputIndex >= unspentTx.OutputStates.Length) // input's prev output does not exist return false; if (unspentTx.OutputStates[(int)input.PrevTxOutputIndex] != OutputState.Unspent) // input's prev output has already been spent return false; TxOutput txOutput; if (!chainState.TryGetUnspentTxOutput(input.PrevTxOutputKey, out txOutput)) // input's prev output does not exist return false; var prevTxOutput = new PrevTxOutput(txOutput, unspentTx); prevTxOutputs.Add(prevTxOutput); checked { inputValue += prevTxOutput.Value; } } var outputValue = 0UL; for (var outputIndex = 0; outputIndex < tx.Outputs.Length; outputIndex++) { var output = tx.Outputs[outputIndex]; checked { outputValue += output.Value; } } if (outputValue > inputValue) // transaction spends more than its inputs return false; // validation passed // create the unconfirmed tx var blockTx = new DecodedBlockTx(-1, decodedTx); var validatableTx = new ValidatableTx(blockTx, null, prevTxOutputs.ToImmutable()); unconfirmedTx = new UnconfirmedTx(validatableTx, DateTimeOffset.Now); // add the unconfirmed tx using (var handle = storageManager.OpenUnconfirmedTxesCursor()) { var unconfirmedTxesCursor = handle.Item; unconfirmedTxesCursor.BeginTransaction(); if (unconfirmedTxesCursor.TryAddTransaction(unconfirmedTx)) { unconfirmedTxesCursor.CommitTransaction(); } else // unconfirmed tx already exists return false; } } } finally { if (storageManager.IsUnconfirmedTxesConcurrent) updateLock.ExitReadLock(); else updateLock.ExitWriteLock(); } UnconfirmedTxAdded?.Invoke(this, new UnconfirmedTxAddedEventArgs(unconfirmedTx)); return true; }
public bool TryGetTransaction(UInt256 txHash, out UnconfirmedTx unconfirmedTx) { using (var handle = storageManager.OpenUnconfirmedTxesCursor()) { var unconfirmedTxesCursor = handle.Item; unconfirmedTxesCursor.BeginTransaction(readOnly: true); return unconfirmedTxesCursor.TryGetTransaction(txHash, out unconfirmedTx); } }