public void BeginTransaction( out UncommittedRecord<ChainedHeader> chainTip, out UncommittedRecord<int> unspentTxCount, out UncommittedRecord<int> unspentOutputCount, out UncommittedRecord<int> totalTxCount, out UncommittedRecord<int> totalInputCount, out UncommittedRecord<int> totalOutputCount, out UncommittedRecord<ImmutableSortedDictionary<UInt256, ChainedHeader>.Builder> headers, out UncommittedRecord<ImmutableSortedDictionary<UInt256, UnspentTx>.Builder> unspentTransactions, out UncommittedRecord<ImmutableSortedDictionary<TxOutputKey, TxOutput>.Builder> unspentTxOutputs, out UncommittedRecord<ImmutableDictionary<int, BlockSpentTxes>.Builder> blockSpentTxes, out UncommittedRecord<ImmutableDictionary<UInt256, IImmutableList<UnmintedTx>>.Builder> blockUnmintedTxes) { lock (this.lockObject) { chainTip = this.chainTip.AsUncommitted(); unspentTxCount = this.unspentTxCount.AsUncommitted(); unspentOutputCount = this.unspentOutputCount.AsUncommitted(); totalTxCount = this.totalTxCount.AsUncommitted(); totalInputCount = this.totalInputCount.AsUncommitted(); totalOutputCount = this.totalOutputCount.AsUncommitted(); headers = this.headers.AsUncommitted(x => x.ToImmutable().ToBuilder()); unspentTransactions = this.unspentTransactions.AsUncommitted(x => x.ToImmutable().ToBuilder()); unspentTxOutputs = this.unspentTxOutputs.AsUncommitted(x => x.ToImmutable().ToBuilder()); blockSpentTxes = this.blockSpentTxes.AsUncommitted(x => x.ToImmutable().ToBuilder()); blockUnmintedTxes = this.blockUnmintedTxes.AsUncommitted(x => x.ToImmutable().ToBuilder()); } }
public void BeginTransaction( out UncommittedRecord<ChainedHeader> chainTip, out UncommittedRecord<int> unconfirmedTxCount, out UncommittedRecord<ImmutableDictionary<UInt256, UnconfirmedTx>.Builder> unconfirmedTxes, out UncommittedRecord<ImmutableDictionary<TxOutputKey, ImmutableDictionary<UInt256, UnconfirmedTx>.Builder>.Builder> unconfirmedTxesByPrevTxOutputKey) { lock (this.lockObject) { chainTip = this.chainTip.AsUncommitted(); unconfirmedTxCount = this.unconfirmedTxCount.AsUncommitted(); unconfirmedTxes = this.unconfirmedTxes.AsUncommitted(x => x.ToImmutable().ToBuilder()); unconfirmedTxesByPrevTxOutputKey = this.unconfirmedTxesByPrevTxOutputKey.AsUncommitted(x => x.ToImmutable().ToBuilder()); } }
public void CommitTransaction( UncommittedRecord<ChainedHeader> chainTip, UncommittedRecord<int> unconfirmedTxCount, UncommittedRecord<ImmutableDictionary<UInt256, UnconfirmedTx>.Builder> unconfirmedTxes, UncommittedRecord<ImmutableDictionary<TxOutputKey, ImmutableDictionary<UInt256, UnconfirmedTx>.Builder>.Builder> unconfirmedTxesByPrevTxOutputKey) { lock (this.lockObject) { if (this.chainTip.ConflictsWith(chainTip) || this.unconfirmedTxCount.ConflictsWith(unconfirmedTxCount) || this.unconfirmedTxes.ConflictsWith(unconfirmedTxes) || this.unconfirmedTxesByPrevTxOutputKey.ConflictsWith(unconfirmedTxesByPrevTxOutputKey)) throw new InvalidOperationException(); this.chainTip.Committ(chainTip); this.unconfirmedTxCount.Committ(unconfirmedTxCount); this.unconfirmedTxes.Committ(unconfirmedTxes, x => x.ToImmutable().ToBuilder()); this.unconfirmedTxesByPrevTxOutputKey.Committ(unconfirmedTxesByPrevTxOutputKey, x => x.ToImmutable().ToBuilder()); } }
public void CommitTransaction( UncommittedRecord<ChainedHeader> chainTip, UncommittedRecord<int> unspentTxCount, UncommittedRecord<int> unspentOutputCount, UncommittedRecord<int> totalTxCount, UncommittedRecord<int> totalInputCount, UncommittedRecord<int> totalOutputCount, UncommittedRecord<ImmutableSortedDictionary<UInt256, ChainedHeader>.Builder> headers, UncommittedRecord<ImmutableSortedDictionary<UInt256, UnspentTx>.Builder> unspentTransactions, UncommittedRecord<ImmutableSortedDictionary<TxOutputKey, TxOutput>.Builder> unspentTxOutputs, UncommittedRecord<ImmutableDictionary<int, BlockSpentTxes>.Builder> blockSpentTxes, UncommittedRecord<ImmutableDictionary<UInt256, IImmutableList<UnmintedTx>>.Builder> blockUnmintedTxes) { lock (this.lockObject) { if (this.chainTip.ConflictsWith(chainTip) || this.unspentTxCount.ConflictsWith(unspentTxCount) || this.unspentOutputCount.ConflictsWith(unspentOutputCount) || this.totalTxCount.ConflictsWith(totalTxCount) || this.totalInputCount.ConflictsWith(totalInputCount) || this.totalOutputCount.ConflictsWith(totalOutputCount) || this.headers.ConflictsWith(headers) || this.unspentTransactions.ConflictsWith(unspentTransactions) || this.unspentTxOutputs.ConflictsWith(unspentTxOutputs) || this.blockSpentTxes.ConflictsWith(blockSpentTxes) || this.blockUnmintedTxes.ConflictsWith(blockUnmintedTxes)) throw new InvalidOperationException(); this.chainTip.Committ(chainTip); this.unspentTxCount.Committ(unspentTxCount); this.unspentOutputCount.Committ(unspentOutputCount); this.totalTxCount.Committ(totalTxCount); this.totalInputCount.Committ(totalInputCount); this.totalOutputCount.Committ(totalOutputCount); this.headers.Committ(headers, x => x.ToImmutable().ToBuilder()); this.unspentTransactions.Committ(unspentTransactions, x => x.ToImmutable().ToBuilder()); this.unspentTxOutputs.Committ(unspentTxOutputs, x => x.ToImmutable().ToBuilder()); this.blockSpentTxes.Committ(blockSpentTxes, x => x.ToImmutable().ToBuilder()); this.blockUnmintedTxes.Committ(blockUnmintedTxes, x => x.ToImmutable().ToBuilder()); } }
public void CommitTransaction() { if (!inTransaction) throw new InvalidOperationException(); unconfirmedTxesStorage.CommitTransaction( chainTip, unconfirmedTxCount, unconfirmedTxes, unconfirmedTxesByPrevTxOutputKey); chainTip = null; unconfirmedTxCount = null; unconfirmedTxes = null; unconfirmedTxesByPrevTxOutputKey = null; inTransaction = false; if (!readOnly) unconfirmedTxesStorage.WriteTxLock.Release(); }
public bool TryRemoveTransaction(UInt256 txHash) { CheckWriteTransaction(); UnconfirmedTx unconfirmedTx; if (unconfirmedTxes.Value.TryGetValue(txHash, out unconfirmedTx) && unconfirmedTxes.TryModify(x => x.Remove(txHash))) { // 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.Remove(unconfirmedTx.Hash); if (unconfirmedTxes.Count > 0) unconfirmedTxesByPrevTxOutputKey.Value[input.PrevTxOutputKey] = unconfirmedTxes; else unconfirmedTxesByPrevTxOutputKey.Value.Remove(input.PrevTxOutputKey); } return true; } else return false; }
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 void CommitTransaction() { if (!inTransaction) throw new InvalidOperationException(); chainStateStorage.CommitTransaction( chainTip, unspentTxCount, unspentOutputCount, totalTxCount, totalInputCount, totalOutputCount, headers, unspentTransactions, unspentTxOutputs, blockSpentTxes, blockUnmintedTxes); chainTip = null; unspentTxCount = null; unspentOutputCount = null; totalTxCount = null; totalInputCount = null; totalOutputCount = null; headers = null; unspentTransactions = null; unspentTxOutputs = null; blockSpentTxes = null; blockUnmintedTxes = null; inTransaction = false; if (!readOnly) chainStateStorage.WriteTxLock.Release(); }