示例#1
0
        public override void SetBlockStates(
            HashDigest <SHA256> blockHash,
            AddressStateMap states
            )
        {
            var statesFile = new FileInfo(GetStatesPath(blockHash));

            if (!statesFile.Directory.Exists)
            {
                statesFile.Directory.Create();
            }

            using (Stream stream = statesFile.OpenWrite())
            {
                var formatter = new BinaryFormatter();
                formatter.Serialize(stream, states);
            }
        }
示例#2
0
        public AddressStateMap GetStates(
            IEnumerable <Address> addresses, HashDigest <SHA256>?offset = null)
        {
            _rwlock.EnterReadLock();
            try
            {
                if (offset == null)
                {
                    offset = Store.IndexBlockHash(Id.ToString(), -1);
                }
            }
            finally
            {
                _rwlock.ExitReadLock();
            }

            var states = new AddressStateMap();

            while (offset != null)
            {
                states = (AddressStateMap)states.SetItems(
                    Store.GetBlockStates(offset.Value)
                    .Where(
                        kv => addresses.Contains(kv.Key) &&
                        !states.ContainsKey(kv.Key))
                    );

                if (states.Keys.SequenceEqual(addresses))
                {
                    break;
                }

                offset = Blocks[offset.Value].PreviousHash;
            }

            return(states);
        }
示例#3
0
        public void StoreBlockState()
        {
            Assert.Empty(_fx.Store.GetBlockStates(_fx.Hash1));
            AddressStateMap states = new AddressStateMap(
                new Dictionary <Address, object>()
            {
                [_fx.Address1] = new Dictionary <string, int>()
                {
                    { "a", 1 },
                },
                [_fx.Address2] = new Dictionary <string, int>()
                {
                    { "b", 2 },
                },
            }.ToImmutableDictionary()
                );

            _fx.Store.SetBlockStates(_fx.Hash1, states);

            AddressStateMap actual = _fx.Store.GetBlockStates(_fx.Hash1);

            Assert.Equal(states[_fx.Address1], actual[_fx.Address1]);
            Assert.Equal(states[_fx.Address2], actual[_fx.Address2]);
        }
示例#4
0
        public void BlockState()
        {
            Assert.Null(Fx.Store.GetBlockStates(Fx.Hash1));
            AddressStateMap states = new AddressStateMap(
                new Dictionary <Address, IValue>()
            {
                [Fx.Address1] = new Bencodex.Types.Dictionary(new Dictionary <IKey, IValue>
                {
                    { (Text)"a", (Integer)1 },
                }),
                [Fx.Address2] = new Bencodex.Types.Dictionary(new Dictionary <IKey, IValue>
                {
                    { (Text)"b", (Integer)2 },
                }),
            }.ToImmutableDictionary()
                );

            Fx.Store.SetBlockStates(Fx.Hash1, states);

            AddressStateMap actual = Fx.Store.GetBlockStates(Fx.Hash1);

            Assert.Equal(states[Fx.Address1], actual[Fx.Address1]);
            Assert.Equal(states[Fx.Address2], actual[Fx.Address2]);
        }
示例#5
0
        private void EvaluateActions(Block <T> block)
        {
            HashDigest <SHA256>?prevHash = block.PreviousHash;
            var states = new AddressStateMap();

            int seed = BitConverter.ToInt32(block.Hash.ToByteArray(), 0);

            foreach (Transaction <T> tx in block.Transactions)
            {
                int txSeed = seed ^ BitConverter.ToInt32(tx.Signature, 0);
                foreach (T action in tx.Actions)
                {
                    IEnumerable <Address> requestedAddresses =
                        action.RequestStates(tx.Sender, tx.Recipient);
                    AddressStateMap requested = GetStates(
                        requestedAddresses.Except(states.Keys),
                        prevHash);
                    states = (AddressStateMap)requested.SetItems(states);
                    var prevState = new AddressStateMap(
                        requestedAddresses
                        .Where(states.ContainsKey)
                        .ToImmutableDictionary(a => a, a => states[a]));
                    var context = new ActionContext(
                        @from: tx.Sender,
                        to: tx.Recipient,
                        blockIndex: block.Index,
                        previousStates: prevState,
                        randomSeed: unchecked (txSeed++)
                        );
                    AddressStateMap changes = action.Execute(context);
                    states = (AddressStateMap)states.SetItems(changes);
                }
            }

            Store.SetBlockStates(Id.ToString(), block.Hash, states);
        }
示例#6
0
        /// <summary>
        /// Gets the state of the given <paramref name="addresses"/> in the
        /// <see cref="BlockChain{T}"/> from <paramref name="offset"/>.
        /// </summary>
        /// <param name="addresses">The list of <see cref="Address"/>es to get
        /// their states.</param>
        /// <param name="offset">The <see cref="HashDigest{T}"/> of the block to
        /// start finding the state. It will be The tip of the
        /// <see cref="BlockChain{T}"/> if it is <c>null</c>.</param>
        /// <param name="completeStates">When the <see cref="BlockChain{T}"/>
        /// instance does not contain states dirty of the block which lastly
        /// updated states of a requested address, this option makes
        /// the incomplete states calculated and filled on the fly.
        /// If this option is turned off (which is default) this method throws
        /// <see cref="IncompleteBlockStatesException"/> instead
        /// for the same situation.
        /// Just-in-time calculation of states could take a long time so that
        /// the overall latency of an application may rise.</param>
        /// <returns>The <see cref="AddressStateMap"/> of given
        /// <paramref name="addresses"/>.</returns>
        /// <exception cref="IncompleteBlockStatesException">Thrown when
        /// the <see cref="BlockChain{T}"/> instance does not contain
        /// states dirty of the block which lastly updated states of a requested
        /// address, because actions in the block have never been executed.
        /// If <paramref name="completeStates"/> option is turned on
        /// this exception is not thrown and incomplete states are calculated
        /// and filled on the fly instead.
        /// </exception>
        public AddressStateMap GetStates(
            IEnumerable <Address> addresses,
            HashDigest <SHA256>?offset = null,
            bool completeStates        = false
            )
        {
            _rwlock.EnterReadLock();
            try
            {
                if (offset == null)
                {
                    offset = Store.IndexBlockHash(Id, -1);
                }
            }
            finally
            {
                _rwlock.ExitReadLock();
            }

            var states = new AddressStateMap();

            if (offset == null)
            {
                return(states);
            }

            Block <T> block = Blocks[offset.Value];

            ImmutableHashSet <Address> requestedAddresses =
                addresses.ToImmutableHashSet();
            var stateReferences = new HashSet <Tuple <HashDigest <SHA256>, long> >();

            foreach (var address in requestedAddresses)
            {
                Tuple <HashDigest <SHA256>, long> sr;
                _rwlock.EnterReadLock();
                try
                {
                    sr = Store.LookupStateReference(Id, address, block);
                }
                finally
                {
                    _rwlock.ExitReadLock();
                }

                if (!(sr is null))
                {
                    stateReferences.Add(sr);
                }
            }

            IEnumerable <HashDigest <SHA256> > hashValues = stateReferences
                                                            .OrderByDescending(sr => sr.Item2)
                                                            .Select(sr => sr.Item1);

            foreach (var hashValue in hashValues)
            {
                AddressStateMap blockStates = Store.GetBlockStates(hashValue);
                if (blockStates is null)
                {
                    if (completeStates)
                    {
                        // Calculates and fills the incomplete states
                        // on the fly.
                        foreach (Block <T> b in this)
                        {
                            if (!(Store.GetBlockStates(b.Hash) is null))
                            {
                                continue;
                            }

                            List <ActionEvaluation> evaluations =
                                b.Evaluate(
                                    DateTimeOffset.UtcNow,
                                    a => GetStates(
                                        new[] { a },
                                        b.PreviousHash
                                        ).GetValueOrDefault(a)
                                    ).ToList();

                            if (Policy.BlockAction is IAction)
                            {
                                evaluations.Add(EvaluateBlockAction(b, evaluations));
                            }

                            _rwlock.EnterWriteLock();

                            try
                            {
                                SetStates(b, evaluations, buildStateReferences: false);
                            }
                            finally
                            {
                                _rwlock.ExitWriteLock();
                            }
                        }

                        blockStates = Store.GetBlockStates(hashValue);
                        if (blockStates is null)
                        {
                            throw new NullReferenceException();
                        }
                    }
                    else
                    {
                        throw new IncompleteBlockStatesException(hashValue);
                    }
                }

                states = (AddressStateMap)states.SetItems(
                    blockStates.Where(kv =>
                                      requestedAddresses.Contains(kv.Key) &&
                                      !states.ContainsKey(kv.Key)
                                      )
                    );
            }

            return(states);
        }
示例#7
0
        public void CanProcessActions()
        {
            var actions1 = new List <BaseAction>()
            {
                new Attack()
                {
                    Weapon = "sword",
                    Target = "goblin",
                },
                new Attack()
                {
                    Weapon = "sword",
                    Target = "orc",
                },
                new Attack()
                {
                    Weapon = "staff",
                    Target = "goblin",
                },
            };
            Transaction <BaseAction> tx1 = Transaction <BaseAction> .Make(
                new PrivateKey(),
                _fx.Address1,
                actions1,
                DateTimeOffset.UtcNow
                );

            _blockChain.StageTransactions(new HashSet <Transaction <BaseAction> > {
                tx1
            });
            _blockChain.MineBlock(_fx.Address1);

            AddressStateMap states = _blockChain.GetStates(new List <Address> {
                _fx.Address1
            });

            Assert.NotEmpty(states);

            var result = (BattleResult)states[_fx.Address1];

            Assert.Contains("sword", result.UsedWeapons);
            Assert.Contains("staff", result.UsedWeapons);
            Assert.Contains("orc", result.Targets);
            Assert.Contains("goblin", result.Targets);

            var actions2 = new List <BaseAction>()
            {
                new Attack()
                {
                    Weapon = "bow",
                    Target = "goblin",
                },
            };
            Transaction <BaseAction> tx2 = Transaction <BaseAction> .Make(
                new PrivateKey(),
                _fx.Address1,
                actions2,
                DateTimeOffset.UtcNow
                );

            _blockChain.StageTransactions(new HashSet <Transaction <BaseAction> > {
                tx2
            });
            _blockChain.MineBlock(_fx.Address1);

            states = _blockChain.GetStates(new List <Address> {
                _fx.Address1
            });
            result = (BattleResult)states[_fx.Address1];
            Assert.Contains("bow", result.UsedWeapons);
        }
示例#8
0
 public abstract void SetBlockStates(
     string @namespace,
     HashDigest <SHA256> blockHash,
     AddressStateMap states
     );
示例#9
0
 public abstract AddressStateMap Execute(Address from, Address to, AddressStateMap states);
示例#10
0
        public void ProcessActions()
        {
            var actions1 = new List <PolymorphicAction <BaseAction> >()
            {
                new Attack
                {
                    Weapon        = "sword",
                    Target        = "goblin",
                    TargetAddress = _fx.Address1,
                },
                new Attack
                {
                    Weapon        = "sword",
                    Target        = "orc",
                    TargetAddress = _fx.Address1,
                },
                new Attack
                {
                    Weapon        = "staff",
                    Target        = "goblin",
                    TargetAddress = _fx.Address1,
                },
            };
            var tx1 = Transaction <PolymorphicAction <BaseAction> > .Create(
                new PrivateKey(),
                actions1
                );

            var chain = new BlockChain <PolymorphicAction <BaseAction> >(
                new BlockPolicy <PolymorphicAction <BaseAction> >(),
                _fx.Store
                );

            chain.StageTransactions(
                new HashSet <Transaction <PolymorphicAction <BaseAction> > > {
                tx1
            }
                );
            var lastBlock = chain.MineBlock(_fx.Address1);

            AddressStateMap states = chain.GetStates(
                new List <Address> {
                _fx.Address1
            }
                );

            Assert.NotEmpty(states);

            var result = (BattleResult)states[_fx.Address1];

            Assert.Contains("sword", result.UsedWeapons);
            Assert.Contains("staff", result.UsedWeapons);
            Assert.Contains("orc", result.Targets);
            Assert.Contains("goblin", result.Targets);

            PolymorphicAction <BaseAction>[] actions2 =
            {
                new Attack
                {
                    Weapon        = "bow",
                    Target        = "goblin",
                    TargetAddress = _fx.Address1,
                },
            };
            var tx2 = Transaction <PolymorphicAction <BaseAction> > .Create(
                new PrivateKey(),
                actions2
                );

            chain.StageTransactions(
                new HashSet <Transaction <PolymorphicAction <BaseAction> > > {
                tx2
            }
                );
            chain.MineBlock(_fx.Address1);

            states = chain.GetStates(new List <Address> {
                _fx.Address1
            });
            result = (BattleResult)states[_fx.Address1];
            Assert.Contains("bow", result.UsedWeapons);
        }
示例#11
0
 public abstract void SetBlockStates(
     HashDigest <SHA256> blockHash,
     AddressStateMap states
     );
示例#12
0
 public override AddressStateMap Execute(Address from, Address to, AddressStateMap states)
 {
     throw new NotImplementedException();
 }
示例#13
0
        /// <summary>
        /// Gets the state of the given <paramref name="address"/> in the
        /// <see cref="BlockChain{T}"/> from <paramref name="offset"/>.
        /// </summary>
        /// <param name="address">An <see cref="Address"/> to get
        /// the states of.</param>
        /// <param name="offset">The <see cref="HashDigest{T}"/> of the block to
        /// start finding the state. It will be The tip of the
        /// <see cref="BlockChain{T}"/> if it is <c>null</c>.</param>
        /// <param name="completeStates">When the <see cref="BlockChain{T}"/>
        /// instance does not contain states dirty of the block which lastly
        /// updated states of a requested address, this option makes
        /// the incomplete states calculated and filled on the fly.
        /// If this option is turned off (which is default) this method throws
        /// <see cref="IncompleteBlockStatesException"/> instead
        /// for the same situation.
        /// Just-in-time calculation of states could take a long time so that
        /// the overall latency of an application may rise.</param>
        /// <returns>The <see cref="AddressStateMap"/> of given
        /// <paramref name="address"/>.</returns>
        /// <exception cref="IncompleteBlockStatesException">Thrown when
        /// the <see cref="BlockChain{T}"/> instance does not contain
        /// states dirty of the block which lastly updated states of a requested
        /// address, because actions in the block have never been executed.
        /// If <paramref name="completeStates"/> option is turned on
        /// this exception is not thrown and incomplete states are calculated
        /// and filled on the fly instead.
        /// </exception>
        public AddressStateMap GetState(
            Address address,
            HashDigest <SHA256>?offset = null,
            bool completeStates        = false
            )
        {
            _rwlock.EnterReadLock();
            try
            {
                if (offset == null)
                {
                    offset = Store.IndexBlockHash(Id, -1);
                }
            }
            finally
            {
                _rwlock.ExitReadLock();
            }

            var states = new AddressStateMap();

            if (offset == null)
            {
                return(states);
            }

            Block <T> block = Blocks[offset.Value];
            Tuple <HashDigest <SHA256>, long> stateReference;

            _rwlock.EnterReadLock();
            try
            {
                stateReference = Store.LookupStateReference(Id, address, block);
            }
            finally
            {
                _rwlock.ExitReadLock();
            }

            if (stateReference is null)
            {
                return(states);
            }

            HashDigest <SHA256> hashValue = stateReference.Item1;

            AddressStateMap blockStates = Store.GetBlockStates(hashValue);

            if (blockStates is null)
            {
                if (completeStates)
                {
                    // Calculates and fills the incomplete states
                    // on the fly.
                    foreach (Block <T> b in this)
                    {
                        if (!(Store.GetBlockStates(b.Hash) is null))
                        {
                            continue;
                        }

                        List <ActionEvaluation> evaluations =
                            b.Evaluate(
                                DateTimeOffset.UtcNow,
                                a => GetState(
                                    a,
                                    b.PreviousHash
                                    ).GetValueOrDefault(a)
                                ).ToList();

                        if (Policy.BlockAction is IAction)
                        {
                            evaluations.Add(EvaluateBlockAction(b, evaluations));
                        }

                        _rwlock.EnterWriteLock();

                        try
                        {
                            SetStates(b, evaluations, buildStateReferences: false);
                        }
                        finally
                        {
                            _rwlock.ExitWriteLock();
                        }
                    }

                    blockStates = Store.GetBlockStates(hashValue);
                    if (blockStates is null)
                    {
                        throw new NullReferenceException();
                    }
                }
                else
                {
                    throw new IncompleteBlockStatesException(hashValue);
                }
            }

            states = (AddressStateMap)states.SetItems(
                blockStates.Where(kv => address.Equals(kv.Key))
                );

            return(states);
        }
示例#14
0
        /// <summary>
        /// Gets the state of the given <paramref name="address"/> in the
        /// <see cref="BlockChain{T}"/> from <paramref name="offset"/>.
        /// </summary>
        /// <param name="address">An <see cref="Address"/> to get
        /// the states of.</param>
        /// <param name="offset">The <see cref="HashDigest{T}"/> of the block to
        /// start finding the state. It will be The tip of the
        /// <see cref="BlockChain{T}"/> if it is <c>null</c>.</param>
        /// <param name="completeStates">When the <see cref="BlockChain{T}"/>
        /// instance does not contain states dirty of the block which lastly
        /// updated states of a requested address, this option makes
        /// the incomplete states calculated and filled on the fly.
        /// If this option is turned off (which is default) this method throws
        /// <see cref="IncompleteBlockStatesException"/> instead
        /// for the same situation.
        /// Just-in-time calculation of states could take a long time so that
        /// the overall latency of an application may rise.</param>
        /// <returns>The <see cref="AddressStateMap"/> of given
        /// <paramref name="address"/>.</returns>
        /// <exception cref="IncompleteBlockStatesException">Thrown when
        /// the <see cref="BlockChain{T}"/> instance does not contain
        /// states dirty of the block which lastly updated states of a requested
        /// address, because actions in the block have never been executed.
        /// If <paramref name="completeStates"/> option is turned on
        /// this exception is not thrown and incomplete states are calculated
        /// and filled on the fly instead.
        /// </exception>
        public AddressStateMap GetState(
            Address address,
            HashDigest <SHA256>?offset = null,
            bool completeStates        = false
            )
        {
            _rwlock.EnterReadLock();
            try
            {
                if (offset == null)
                {
                    offset = Store.IndexBlockHash(Id, -1);
                }
            }
            finally
            {
                _rwlock.ExitReadLock();
            }

            var states = new AddressStateMap();

            if (offset == null)
            {
                return(states);
            }

            Block <T> block = this[offset.Value];
            Tuple <HashDigest <SHA256>, long> stateReference;

            _rwlock.EnterReadLock();
            try
            {
                stateReference = Store.LookupStateReference(Id, address, block);
            }
            finally
            {
                _rwlock.ExitReadLock();
            }

            if (stateReference is null)
            {
                return(states);
            }

            HashDigest <SHA256> hashValue = stateReference.Item1;

            AddressStateMap blockStates = Store.GetBlockStates(hashValue);

            if (blockStates is null)
            {
                if (completeStates)
                {
                    // Calculates and fills the incomplete states
                    // on the fly.
                    foreach (HashDigest <SHA256> hash in BlockHashes)
                    {
                        Block <T> b = this[hash];
                        if (!(Store.GetBlockStates(b.Hash) is null))
                        {
                            continue;
                        }

                        IReadOnlyList <ActionEvaluation> evaluations = EvaluateActions(b);

                        _rwlock.EnterWriteLock();

                        try
                        {
                            SetStates(b, evaluations, buildStateReferences: false);
                        }
                        finally
                        {
                            _rwlock.ExitWriteLock();
                        }
                    }

                    blockStates = Store.GetBlockStates(hashValue);
                    if (blockStates is null)
                    {
                        throw new NullReferenceException();
                    }
                }
                else
                {
                    throw new IncompleteBlockStatesException(hashValue);
                }
            }

            states = (AddressStateMap)states.SetItems(
                blockStates.Where(kv => address.Equals(kv.Key))
                );

            return(states);
        }
示例#15
0
 public override AddressStateMap Execute(Address sender, Address recipient, AddressStateMap requestedStates)
 {
     throw new NotImplementedException();
 }