public void ForkFromChainWithDeletion() { IStore store = Fx.Store; Guid chainA = Guid.NewGuid(); Guid chainB = Guid.NewGuid(); Guid chainC = Guid.NewGuid(); // We need `Block<T>`s because `IStore` can't retrive index(long) by block hash without // actual block... store.PutBlock(Fx.GenesisBlock); store.PutBlock(Fx.Block1); store.PutBlock(Fx.Block2); store.PutBlock(Fx.Block3); store.AppendIndex(chainA, Fx.GenesisBlock.Hash); store.AppendIndex(chainA, Fx.Block1.Hash); store.ForkBlockIndexes(chainA, chainB, Fx.Block1.Hash); store.DeleteChainId(chainA); store.ForkBlockIndexes(chainB, chainC, Fx.Block1.Hash); Assert.Equal( Fx.Block1.Hash, store.IndexBlockHash(chainC, Fx.Block1.Index) ); }
public void ForkWithBranch() { IStore store = Fx.Store; Guid chainA = Guid.NewGuid(); Guid chainB = Guid.NewGuid(); // We need `Block<T>`s because `IStore` can't retrive index(long) by block hash without // actual block... Block <DumbAction> anotherBlock3 = MineNextBlock(Fx.Block2, Fx.GetHashAlgorithm, Fx.Miner); store.PutBlock(Fx.GenesisBlock); store.PutBlock(Fx.Block1); store.PutBlock(Fx.Block2); store.PutBlock(Fx.Block3); store.PutBlock(anotherBlock3); store.AppendIndex(chainA, Fx.GenesisBlock.Hash); store.AppendIndex(chainA, Fx.Block1.Hash); store.AppendIndex(chainA, Fx.Block2.Hash); store.AppendIndex(chainA, Fx.Block3.Hash); store.ForkBlockIndexes(chainA, chainB, Fx.Block2.Hash); store.AppendIndex(chainB, anotherBlock3.Hash); Assert.Equal( new[] { Fx.Block2.Hash, anotherBlock3.Hash, }, store.IterateIndexes(chainB, 2, 2) ); Assert.Equal( new[] { Fx.Block2.Hash, anotherBlock3.Hash, }, store.IterateIndexes(chainB, 2) ); Assert.Equal( new[] { anotherBlock3.Hash, }, store.IterateIndexes(chainB, 3, 1) ); Assert.Equal( new[] { anotherBlock3.Hash, }, store.IterateIndexes(chainB, 3) ); }
public static void Copy(this IStore from, IStore to) { // TODO: take a IProgress<> so that a caller can be aware the progress of cloning. if (to.ListChainIds().Any()) { throw new ArgumentException("The destination store has to be empty.", nameof(to)); } foreach (Guid chainId in from.ListChainIds().ToArray()) { foreach (BlockHash blockHash in from.IterateIndexes(chainId)) { Block <NullAction> block = from.GetBlock <NullAction>( _ => HashAlgorithmType.Of <SHA256>(), // thunk getter; doesn't matter here blockHash ); to.PutBlock(block); to.AppendIndex(chainId, blockHash); } foreach (KeyValuePair <Address, long> kv in from.ListTxNonces(chainId)) { to.IncreaseTxNonce(chainId, kv.Key, kv.Value); } } if (from.GetCanonicalChainId() is Guid canonId) { to.SetCanonicalChainId(canonId); } }
public void PruneOutdatedChains() { IStore store = Fx.Store; store.PutBlock(Fx.GenesisBlock); store.PutBlock(Fx.Block1); store.PutBlock(Fx.Block2); store.PutBlock(Fx.Block3); Guid cid1 = Guid.NewGuid(); store.AppendIndex(cid1, Fx.GenesisBlock.Hash); store.AppendIndex(cid1, Fx.Block1.Hash); store.AppendIndex(cid1, Fx.Block2.Hash); Assert.Single(store.ListChainIds()); Assert.Equal( new[] { Fx.GenesisBlock.Hash, Fx.Block1.Hash, Fx.Block2.Hash }, store.IterateIndexes(cid1, 0, null)); Guid cid2 = Guid.NewGuid(); store.ForkBlockIndexes(cid1, cid2, Fx.Block1.Hash); store.AppendIndex(cid2, Fx.Block2.Hash); store.AppendIndex(cid2, Fx.Block3.Hash); Assert.Equal(2, store.ListChainIds().Count()); Assert.Equal( new[] { Fx.GenesisBlock.Hash, Fx.Block1.Hash, Fx.Block2.Hash, Fx.Block3.Hash }, store.IterateIndexes(cid2, 0, null)); Guid cid3 = Guid.NewGuid(); store.ForkBlockIndexes(cid1, cid3, Fx.Block2.Hash); Assert.Equal(3, store.ListChainIds().Count()); Assert.Equal( new[] { Fx.GenesisBlock.Hash, Fx.Block1.Hash, Fx.Block2.Hash }, store.IterateIndexes(cid3, 0, null)); Assert.Throws <InvalidOperationException>(() => store.PruneOutdatedChains()); store.PruneOutdatedChains(true); store.SetCanonicalChainId(cid3); store.PruneOutdatedChains(); Assert.Single(store.ListChainIds()); Assert.Equal( new[] { Fx.GenesisBlock.Hash, Fx.Block1.Hash, Fx.Block2.Hash }, store.IterateIndexes(cid3, 0, null)); Assert.Equal(3, store.CountIndex(cid3)); }
/// <summary> /// Makes a store, <paramref name="to"/>, logically (but not necessarily physically) /// identical to another store, <paramref name="from"/>. As this copies the contents /// of the store, instead of its physicall data, this can be used for migrating /// between two different types of <see cref="IStore"/> implementations. /// </summary> /// <param name="from">The store containing the source contents.</param> /// <param name="to">The store to contain the copied contents. Expected to be empty.</param> /// <exception cref="ArgumentException">Thrown when the store passed through /// <paramref name="to"/> is not empty.</exception> public static void Copy(this IStore from, IStore to) { // TODO: take a IProgress<> so that a caller can be aware the progress of cloning. if (to.ListChainIds().Any()) { throw new ArgumentException("The destination store has to be empty.", nameof(to)); } foreach (Guid chainId in from.ListChainIds().ToArray()) { foreach (HashDigest <SHA256> blockHash in from.IterateIndexes(chainId)) { Block <NullAction> block = from.GetBlock <NullAction>(blockHash); to.PutBlock(block); IImmutableDictionary <string, IValue> states = from.GetBlockStates(blockHash); to.SetBlockStates(blockHash, states); to.AppendIndex(chainId, blockHash); } foreach (KeyValuePair <Address, long> kv in from.ListTxNonces(chainId)) { to.IncreaseTxNonce(chainId, kv.Key, kv.Value); } foreach (string key in from.ListStateKeys(chainId)) { foreach (var pair in from.IterateStateReferences(chainId, key).Reverse()) { pair.Deconstruct(out HashDigest <SHA256> refHash, out long refIndex); to.StoreStateReference( chainId, ImmutableHashSet.Create(key), refHash, refIndex ); } } } ImmutableHashSet <TxId> stagedTxIds = from.IterateStagedTransactionIds().ToImmutableHashSet(); foreach (TxId txid in stagedTxIds) { to.PutTransaction(from.GetTransaction <NullAction>(txid)); } to.StageTransactionIds(stagedTxIds); if (from.GetCanonicalChainId() is Guid canonId) { to.SetCanonicalChainId(canonId); } }
public async Task Inspect(StoreType storeType) { Block <NCAction> genesisBlock = BlockChain <NCAction> .MakeGenesisBlock( HashAlgorithmType.Of <SHA256>() ); IStore store = storeType.CreateStore(_storePath2); Guid chainId = Guid.NewGuid(); store.SetCanonicalChainId(chainId); store.PutBlock(genesisBlock); store.AppendIndex(chainId, genesisBlock.Hash); var stateStore = new TrieStateStore(new DefaultKeyValueStore(null)); IStagePolicy <NCAction> stagePolicy = new VolatileStagePolicy <PolymorphicAction <ActionBase> >(); IBlockPolicy <NCAction> blockPolicy = new BlockPolicySource(Logger.None).GetPolicy(); BlockChain <NCAction> chain = new BlockChain <NCAction>( blockPolicy, stagePolicy, store, stateStore, genesisBlock); var action = new HackAndSlash { costumes = new List <Guid>(), equipments = new List <Guid>(), foods = new List <Guid>(), worldId = 1, stageId = 1, avatarAddress = default }; var minerKey = new PrivateKey(); chain.MakeTransaction(minerKey, new PolymorphicAction <ActionBase>[] { action }); await chain.MineBlock(minerKey, DateTimeOffset.Now); store.Dispose(); _command.Inspect(storeType, _storePath2); List <double> output = _console.Out.ToString().Split("\n")[1] .Split(',').Select(double.Parse).ToList(); var totalTxCount = Convert.ToInt32(output[2]); var hackandslashCount = Convert.ToInt32(output[3]); Assert.Equal(1, totalTxCount); Assert.Equal(1, hackandslashCount); }
public void GetGenesisBlock(StoreType storeType) { IStore store = storeType.CreateStore(_storePath); Block <NCAction> genesisBlock = BlockChain <NCAction> .MakeGenesisBlock(); Guid chainId = Guid.NewGuid(); store.SetCanonicalChainId(chainId); store.PutBlock(genesisBlock); store.AppendIndex(chainId, genesisBlock.Hash); Assert.Equal(genesisBlock, store.GetGenesisBlock <NCAction>()); (store as IDisposable)?.Dispose(); }
public void Tip(StoreType storeType) { Block <NCAction> genesisBlock = BlockChain <NCAction> .MakeGenesisBlock(); IStore store = storeType.CreateStore(_storePath); Guid chainId = Guid.NewGuid(); store.SetCanonicalChainId(chainId); store.PutBlock(genesisBlock); store.AppendIndex(chainId, genesisBlock.Hash); (store as IDisposable)?.Dispose(); _command.Tip(storeType, _storePath); Assert.Equal(JsonSerializer.Serialize(genesisBlock.Header) + "\n", _console.Out.ToString()); }
/// <summary> /// Makes a store, <paramref name="to"/>, logically (but not necessarily physically) /// identical to another store, <paramref name="from"/>. As this copies the contents /// of the store, instead of its physicall data, this can be used for migrating /// between two different types of <see cref="IStore"/> implementations. /// </summary> /// <param name="from">The store containing the source contents.</param> /// <param name="to">The store to contain the copied contents. Expected to be empty.</param> /// <exception cref="ArgumentException">Thrown when the store passed through /// <paramref name="to"/> is not empty.</exception> public static void Copy(this IStore from, IStore to) { // TODO: take a IProgress<> so that a caller can be aware the progress of cloning. if (to.ListChainIds().Any()) { throw new ArgumentException("The destination store has to be empty.", nameof(to)); } foreach (Guid chainId in from.ListChainIds().ToArray()) { foreach (BlockHash blockHash in from.IterateIndexes(chainId)) { Block <NullAction> block = from.GetBlock <NullAction>(blockHash); to.PutBlock(block); to.AppendIndex(chainId, blockHash); } foreach (KeyValuePair <Address, long> kv in from.ListTxNonces(chainId)) { to.IncreaseTxNonce(chainId, kv.Key, kv.Value); } } ImmutableHashSet <TxId> stagedTxIds = from.IterateStagedTransactionIds().ToImmutableHashSet(); foreach (TxId txid in stagedTxIds) { to.PutTransaction(from.GetTransaction <NullAction>(txid)); } to.StageTransactionIds(stagedTxIds); if (from.GetCanonicalChainId() is Guid canonId) { to.SetCanonicalChainId(canonId); } }
public void Tip(StoreType storeType) { HashAlgorithmType hashAlgo = HashAlgorithmType.Of <SHA256>(); Block <NCAction> genesisBlock = BlockChain <NCAction> .MakeGenesisBlock(hashAlgo); IStore store = storeType.CreateStore(_storePath); Guid chainId = Guid.NewGuid(); store.SetCanonicalChainId(chainId); store.PutBlock(genesisBlock); store.AppendIndex(chainId, genesisBlock.Hash); store.Dispose(); // FIXME For an unknown reason, BlockHeader.TimeStamp precision issue occurred and the store we should open it again. store = storeType.CreateStore(_storePath); genesisBlock = store.GetBlock <NCAction>(_ => hashAlgo, genesisBlock.Hash); store.Dispose(); _command.Tip(storeType, _storePath); Assert.Equal( Utils.SerializeHumanReadable(genesisBlock.Header), _console.Out.ToString().Trim() ); }
/// <inheritdoc cref="IStore.AppendIndex(Guid, BlockHash)"/> public long AppendIndex(Guid chainId, BlockHash hash) => _store.AppendIndex(chainId, hash);
public void ForkBlockIndex() { IStore store = Fx.Store; Guid chainA = Guid.NewGuid(); Guid chainB = Guid.NewGuid(); Guid chainC = Guid.NewGuid(); // We need `Block<T>`s because `IStore` can't retrive index(long) by block hash without // actual block... store.PutBlock(Fx.GenesisBlock); store.PutBlock(Fx.Block1); store.PutBlock(Fx.Block2); store.PutBlock(Fx.Block3); store.AppendIndex(chainA, Fx.GenesisBlock.Hash); store.AppendIndex(chainB, Fx.GenesisBlock.Hash); store.AppendIndex(chainC, Fx.GenesisBlock.Hash); store.AppendIndex(chainA, Fx.Block1.Hash); store.ForkBlockIndexes(chainA, chainB, Fx.Block1.Hash); store.AppendIndex(chainB, Fx.Block2.Hash); Assert.Equal( new[] { Fx.GenesisBlock.Hash, Fx.Block1.Hash, }, store.IterateIndexes(chainA) ); Assert.Equal( new[] { Fx.GenesisBlock.Hash, Fx.Block1.Hash, Fx.Block2.Hash, }, store.IterateIndexes(chainB) ); store.ForkBlockIndexes(chainB, chainC, Fx.Block2.Hash); store.AppendIndex(chainC, Fx.Block3.Hash); Assert.Equal( new[] { Fx.GenesisBlock.Hash, Fx.Block1.Hash, }, store.IterateIndexes(chainA) ); Assert.Equal( new[] { Fx.GenesisBlock.Hash, Fx.Block1.Hash, Fx.Block2.Hash, }, store.IterateIndexes(chainB) ); Assert.Equal( new[] { Fx.GenesisBlock.Hash, Fx.Block1.Hash, Fx.Block2.Hash, Fx.Block3.Hash, }, store.IterateIndexes(chainC) ); Assert.Equal(Fx.Block1.Hash, store.IndexBlockHash(chainA, 1)); Assert.Equal(Fx.Block1.Hash, store.IndexBlockHash(chainB, 1)); Assert.Equal(Fx.Block1.Hash, store.IndexBlockHash(chainC, 1)); Assert.Equal(Fx.Block2.Hash, store.IndexBlockHash(chainB, 2)); Assert.Equal(Fx.Block2.Hash, store.IndexBlockHash(chainC, 2)); Assert.Equal(Fx.Block3.Hash, store.IndexBlockHash(chainC, 3)); Assert.Throws <ChainIdNotFoundException>( () => store.ForkBlockIndexes(Guid.NewGuid(), Guid.NewGuid(), Fx.Block2.Hash) ); }
public void DeleteChainIdWithForksReverse() { IStore store = Fx.Store; Guid chainA = Guid.NewGuid(); Guid chainB = Guid.NewGuid(); Guid chainC = Guid.NewGuid(); // We need `Block<T>`s because `IStore` can't retrive index(long) by block hash without // actual block... store.PutBlock(Fx.GenesisBlock); store.PutBlock(Fx.Block1); store.PutBlock(Fx.Block2); store.PutBlock(Fx.Block3); store.AppendIndex(chainA, Fx.GenesisBlock.Hash); store.AppendIndex(chainB, Fx.GenesisBlock.Hash); store.AppendIndex(chainC, Fx.GenesisBlock.Hash); store.AppendIndex(chainA, Fx.Block1.Hash); store.ForkBlockIndexes(chainA, chainB, Fx.Block1.Hash); store.AppendIndex(chainB, Fx.Block2.Hash); store.ForkBlockIndexes(chainB, chainC, Fx.Block2.Hash); store.AppendIndex(chainC, Fx.Block3.Hash); store.DeleteChainId(chainC); Assert.Equal( new[] { Fx.GenesisBlock.Hash, Fx.Block1.Hash, }, store.IterateIndexes(chainA) ); Assert.Equal( new[] { Fx.GenesisBlock.Hash, Fx.Block1.Hash, Fx.Block2.Hash, }, store.IterateIndexes(chainB) ); Assert.Empty(store.IterateIndexes(chainC)); store.DeleteChainId(chainB); Assert.Equal( new[] { Fx.GenesisBlock.Hash, Fx.Block1.Hash, }, store.IterateIndexes(chainA) ); Assert.Empty(store.IterateIndexes(chainB)); Assert.Empty(store.IterateIndexes(chainC)); store.DeleteChainId(chainA); Assert.Empty(store.IterateIndexes(chainA)); Assert.Empty(store.IterateIndexes(chainB)); Assert.Empty(store.IterateIndexes(chainC)); }
public long AppendIndex(Guid chainId, HashDigest <SHA256> hash) { Log(nameof(AppendIndex), chainId, hash); return(_store.AppendIndex(chainId, hash)); }
public long AppendIndex(Guid chainId, BlockHash hash) { Log(nameof(AppendIndex), chainId, hash); return(_store.AppendIndex(chainId, hash)); }
/// <inheritdoc cref="IStore"/> public long AppendIndex(Guid chainId, HashDigest <SHA256> hash) { return(_store.AppendIndex(chainId, hash)); }