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 void RollbackTransaction() { if (!inTransaction) { throw new InvalidOperationException(); } 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(); } }
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 Committ <U>(UncommittedRecord <U> uncommittedRecord, Func <U, T> transformFunc) { if (uncommittedRecord.ValueModified) { Value = transformFunc(uncommittedRecord.Value); ValueVersion++; } }
public void Committ(UncommittedRecord <T> uncommittedRecord) { if (ConflictsWith(uncommittedRecord)) { throw new InvalidOperationException(); } if (uncommittedRecord.ValueModified) { Value = uncommittedRecord.Value; ValueVersion++; } }
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 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 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( 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 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 ConflictsWith <U>(UncommittedRecord <U> uncommittedRecord) { return(uncommittedRecord.ValueModified && uncommittedRecord.ValueVersion != ValueVersion); }