Example #1
0
        /// <inheritdoc cref="BaseStore.PutTxExecution(Libplanet.Tx.TxSuccess)"/>
        public override void PutTxExecution(TxSuccess txSuccess)
        {
            UPath path    = TxExecutionPath(txSuccess);
            UPath dirPath = path.GetDirectory();

            CreateDirectoryRecursively(_txExecutions, dirPath);
            using Stream f =
                      _txExecutions.OpenFile(path, System.IO.FileMode.OpenOrCreate, FileAccess.Write);
            Codec.Encode(SerializeTxExecution(txSuccess), f);
        }
        public void PutTxExecution(TxSuccess txSuccess)
        {
            // Omit TxSuccess.UpdatedStates as it is unused by Nine Chronicles and too big.
            TxSuccess reducedTxSuccess = new TxSuccess(
                txSuccess.BlockHash,
                txSuccess.TxId,
                updatedStates: ImmutableDictionary <Address, IValue> .Empty,
                fungibleAssetsDelta: txSuccess.FungibleAssetsDelta,
                updatedFungibleAssets: txSuccess.UpdatedFungibleAssets
                );

            InternalStore.PutTxExecution(reducedTxSuccess);
        }
Example #3
0
        protected static IValue SerializeTxExecution(TxSuccess txSuccess)
        {
            var sDelta = new Dictionary(
                txSuccess.UpdatedStates.Select(kv =>
                                               new KeyValuePair <IKey, IValue>(
                                                   new Binary(kv.Key.ByteArray),
                                                   kv.Value is { } v?List.Empty.Add(v) : List.Empty
                                                   )
                                               )
                );
            var favDelta    = SerializeGroupedFAVs(txSuccess.FungibleAssetsDelta);
            var updatedFAVs = SerializeGroupedFAVs(txSuccess.UpdatedFungibleAssets);

            return((Dictionary)Dictionary.Empty
                   .Add("fail", false)
                   .Add("sDelta", sDelta)
                   .Add((IKey)(Text)"favDelta", new Dictionary(favDelta))
                   .Add((IKey)(Text)"updatedFAVs", new Dictionary(updatedFAVs)));
        }
Example #4
0
        public TxSuccessTest()
        {
            var random = new Random();

            _blockHash     = random.NextBlockHash();
            _txid          = random.NextTxId();
            _updatedStates = Enumerable.Repeat(random, 5).ToImmutableDictionary(
                RandomExtensions.NextAddress,
                _ => (IValue) new Bencodex.Types.Integer(random.Next())
                );
            var currencies = Currencies.ToList();

            _updatedFungibleAssets = Enumerable.Repeat(random, 5).ToImmutableDictionary(
                RandomExtensions.NextAddress,
                _ => (IImmutableDictionary <Currency, FAV>)Enumerable.Repeat(
                    0,
                    random.Next(currencies.Count))
                .Select(__ =>
            {
                int i      = random.Next(currencies.Count);
                Currency c = currencies[i];
                currencies.RemoveAt(i);
                return(c);
            })
                .ToImmutableDictionary(
                    c => c,
                    c => c * random.Next()
                    )
                );
            _fungibleAssetsDelta = _updatedFungibleAssets.SelectWithinValues(favs =>
                                                                             (IImmutableDictionary <Currency, FAV>)favs.SelectWithinValues(
                                                                                 fav => fav.Currency * random.Next(1, int.MaxValue)
                                                                                 ).ToImmutableDictionary()
                                                                             ).ToImmutableDictionary();
            _fx = new TxSuccess(
                _blockHash,
                _txid,
                _updatedStates,
                _fungibleAssetsDelta,
                _updatedFungibleAssets
                );
        }
Example #5
0
 /// <inheritdoc cref="IStore.PutTxExecution(Libplanet.Tx.TxSuccess)"/>
 public void PutTxExecution(TxSuccess txSuccess) =>
 _store.PutTxExecution(txSuccess);
Example #6
0
        public void TxExecution()
        {
            void AssertTxSuccessesEqual(TxSuccess expected, TxExecution actual)
            {
                Assert.IsType <TxSuccess>(actual);
                var success = (TxSuccess)actual;

                Assert.Equal(expected.TxId, success.TxId);
                Assert.Equal(expected.BlockHash, success.BlockHash);
                Assert.Equal(expected.UpdatedStates, success.UpdatedStates);
                Assert.Equal(expected.FungibleAssetsDelta, success.FungibleAssetsDelta);
                Assert.Equal(expected.UpdatedFungibleAssets, success.UpdatedFungibleAssets);
            }

            void AssertTxFailuresEqual(TxFailure expected, TxExecution actual)
            {
                Assert.IsType <TxFailure>(actual);
                var failure = (TxFailure)actual;

                Assert.Equal(expected.TxId, failure.TxId);
                Assert.Equal(expected.BlockHash, failure.BlockHash);
                Assert.Equal(expected.ExceptionName, failure.ExceptionName);
                Assert.Equal(expected.ExceptionMetadata, failure.ExceptionMetadata);
            }

            Assert.Null(Fx.Store.GetTxExecution(Fx.Hash1, Fx.TxId1));
            Assert.Null(Fx.Store.GetTxExecution(Fx.Hash1, Fx.TxId2));
            Assert.Null(Fx.Store.GetTxExecution(Fx.Hash2, Fx.TxId1));
            Assert.Null(Fx.Store.GetTxExecution(Fx.Hash2, Fx.TxId2));

            var random = new System.Random();
            var inputA = new TxSuccess(
                Fx.Hash1,
                Fx.TxId1,
                ImmutableDictionary <Address, IValue> .Empty.Add(
                    random.NextAddress(),
                    (Text)"state value"
                    ),
                ImmutableDictionary <Address, IImmutableDictionary <Currency, FAV> > .Empty
                .Add(
                    random.NextAddress(),
                    ImmutableDictionary <Currency, FAV> .Empty.Add(
                        DumbAction.DumbCurrency,
                        DumbAction.DumbCurrency * 5
                        )
                    ),
                ImmutableDictionary <Address, IImmutableDictionary <Currency, FAV> > .Empty
                .Add(
                    random.NextAddress(),
                    ImmutableDictionary <Currency, FAV> .Empty.Add(
                        DumbAction.DumbCurrency,
                        DumbAction.DumbCurrency * 10
                        )
                    )
                );

            Fx.Store.PutTxExecution(inputA);

            AssertTxSuccessesEqual(inputA, Fx.Store.GetTxExecution(Fx.Hash1, Fx.TxId1));
            Assert.Null(Fx.Store.GetTxExecution(Fx.Hash1, Fx.TxId2));
            Assert.Null(Fx.Store.GetTxExecution(Fx.Hash2, Fx.TxId1));
            Assert.Null(Fx.Store.GetTxExecution(Fx.Hash2, Fx.TxId2));

            var inputB = new TxFailure(
                Fx.Hash1,
                Fx.TxId2,
                "AnExceptionName",
                Dictionary.Empty.Add("foo", 1).Add("bar", "baz")
                );

            Fx.Store.PutTxExecution(inputB);

            AssertTxSuccessesEqual(inputA, Fx.Store.GetTxExecution(Fx.Hash1, Fx.TxId1));
            AssertTxFailuresEqual(inputB, Fx.Store.GetTxExecution(Fx.Hash1, Fx.TxId2));
            Assert.Null(Fx.Store.GetTxExecution(Fx.Hash2, Fx.TxId1));
            Assert.Null(Fx.Store.GetTxExecution(Fx.Hash2, Fx.TxId2));

            var inputC = new TxFailure(
                Fx.Hash2,
                Fx.TxId1,
                "AnotherExceptionName",
                null
                );

            Fx.Store.PutTxExecution(inputC);

            AssertTxSuccessesEqual(inputA, Fx.Store.GetTxExecution(Fx.Hash1, Fx.TxId1));
            AssertTxFailuresEqual(inputB, Fx.Store.GetTxExecution(Fx.Hash1, Fx.TxId2));
            AssertTxFailuresEqual(inputC, Fx.Store.GetTxExecution(Fx.Hash2, Fx.TxId1));
            Assert.Null(Fx.Store.GetTxExecution(Fx.Hash2, Fx.TxId2));
        }
Example #7
0
 /// <inheritdoc cref="BaseStore.PutTxExecution(Libplanet.Tx.TxSuccess)"/>
 public override void PutTxExecution(TxSuccess txSuccess) =>
 _txExecutionDb.Put(
     TxExecutionKey(txSuccess),
     Codec.Encode(SerializeTxExecution(txSuccess))
     );
Example #8
0
 public void PutTxExecution(TxSuccess txSuccess)
 {
     Log(nameof(PutTxExecution), txSuccess);
     _store.PutTxExecution(txSuccess);
 }
Example #9
0
 /// <inheritdoc cref="IStore.PutTxExecution(TxSuccess)"/>
 public virtual void PutTxExecution(TxSuccess txSuccess) =>
 Store.PutTxExecution(txSuccess);
Example #10
0
 /// <inheritdoc cref="IStore.PutTxExecution(Libplanet.Tx.TxSuccess)"/>
 public abstract void PutTxExecution(TxSuccess txSuccess);
        public TransactionHeadlessQuery(StandaloneContext standaloneContext)
        {
            Field <NonNullGraphType <LongGraphType> >(
                name: "nextTxNonce",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <AddressType> > {
                Name = "address", Description = "Target address to query"
            }
                    ),
                resolve: context =>
            {
                if (!(standaloneContext.BlockChain is BlockChain <PolymorphicAction <ActionBase> > blockChain))
                {
                    throw new ExecutionError(
                        $"{nameof(StandaloneContext)}.{nameof(StandaloneContext.BlockChain)} was not set yet!");
                }

                Address address = context.GetArgument <Address>("address");
                return(blockChain.GetNextTxNonce(address));
            }
                );

            Field <TransactionType <NCAction> >(
                name: "getTx",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <TxIdType> >
            {
                Name = "txId", Description = "transaction id."
            }
                    ),
                resolve: context =>
            {
                if (!(standaloneContext.BlockChain is BlockChain <PolymorphicAction <ActionBase> > blockChain))
                {
                    throw new ExecutionError(
                        $"{nameof(StandaloneContext)}.{nameof(StandaloneContext.BlockChain)} was not set yet!");
                }

                var txId = context.GetArgument <TxId>("txId");
                return(blockChain.GetTransaction(txId));
            }
                );

            Field <NonNullGraphType <StringGraphType> >(
                name: "createUnsignedTx",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <StringGraphType> >
            {
                Name        = "publicKey",
                Description = "The base64-encoded public key for Transaction.",
            },
                    new QueryArgument <NonNullGraphType <StringGraphType> >
            {
                Name        = "plainValue",
                Description = "The base64-encoded plain value of action for Transaction.",
            }
                    ),
                resolve: context =>
            {
                if (!(standaloneContext.BlockChain is BlockChain <PolymorphicAction <ActionBase> > blockChain))
                {
                    throw new ExecutionError(
                        $"{nameof(StandaloneContext)}.{nameof(StandaloneContext.BlockChain)} was not set yet!");
                }

                string plainValueString = context.GetArgument <string>("plainValue");
                var plainValue          = new Bencodex.Codec().Decode(System.Convert.FromBase64String(plainValueString));
#pragma warning disable 612
                var action = new NCAction();
#pragma warning restore 612
                action.LoadPlainValue(plainValue);

                var publicKey  = new PublicKey(Convert.FromBase64String(context.GetArgument <string>("publicKey")));
                Address signer = publicKey.ToAddress();
                long nonce     = blockChain.GetNextTxNonce(signer);
                Transaction <NCAction> unsignedTransaction =
                    Transaction <NCAction> .CreateUnsigned(nonce, publicKey, blockChain.Genesis.Hash, new[] { action });
                return(Convert.ToBase64String(unsignedTransaction.Serialize(false)));
            });

            Field <NonNullGraphType <StringGraphType> >(
                name: "attachSignature",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <StringGraphType> >
            {
                Name        = "unsignedTransaction",
                Description = "The base64-encoded unsigned transaction to attach the given signature."
            },
                    new QueryArgument <NonNullGraphType <StringGraphType> >
            {
                Name        = "signature",
                Description = "The base64-encoded signature of the given unsigned transaction."
            }
                    ),
                resolve: context =>
            {
                byte[] signature = Convert.FromBase64String(context.GetArgument <string>("signature"));
                Transaction <NCAction> unsignedTransaction =
                    Transaction <NCAction> .Deserialize(
                        Convert.FromBase64String(context.GetArgument <string>("unsignedTransaction")),
                        false);
                Transaction <NCAction> signedTransaction = new Transaction <NCAction>(
                    unsignedTransaction.Nonce,
                    unsignedTransaction.Signer,
                    unsignedTransaction.PublicKey,
                    unsignedTransaction.GenesisHash,
                    unsignedTransaction.UpdatedAddresses,
                    unsignedTransaction.Timestamp,
                    unsignedTransaction.Actions,
                    signature);

                return(Convert.ToBase64String(signedTransaction.Serialize(true)));
            });

            Field <NonNullGraphType <TxResultType> >(
                name: "transactionResult",
                arguments: new QueryArguments(
                    new QueryArgument <NonNullGraphType <TxIdType> >
            {
                Name = "txId", Description = "transaction id."
            }
                    ),
                resolve: context =>
            {
                if (!(standaloneContext.BlockChain is BlockChain <PolymorphicAction <ActionBase> > blockChain))
                {
                    throw new ExecutionError(
                        $"{nameof(StandaloneContext)}.{nameof(StandaloneContext.BlockChain)} was not set yet!");
                }

                if (!(standaloneContext.Store is IStore store))
                {
                    throw new ExecutionError(
                        $"{nameof(StandaloneContext)}.{nameof(StandaloneContext.Store)} was not set yet!");
                }

                TxId txId = context.GetArgument <TxId>("txId");
                if (!(store.GetFirstTxIdBlockHashIndex(txId) is { } txExecutedBlockHash))
                {
                    return(blockChain.GetStagedTransactionIds().Contains(txId)
                            ? new TxResult(TxStatus.STAGING, null, null)
                            : new TxResult(TxStatus.INVALID, null, null));
                }

                try
                {
                    TxExecution execution = blockChain.GetTxExecution(txExecutedBlockHash, txId);
                    Block <PolymorphicAction <ActionBase> > txExecutedBlock = blockChain[txExecutedBlockHash];
                    return(execution switch
                    {
                        TxSuccess txSuccess => new TxResult(TxStatus.SUCCESS, txExecutedBlock.Index,
                                                            txExecutedBlock.Hash.ToString()),
                        TxFailure txFailure => new TxResult(TxStatus.FAILURE, txExecutedBlock.Index,
                                                            txExecutedBlock.Hash.ToString()),
                        _ => throw new NotImplementedException(
                            $"{nameof(execution)} is not expected concrete class.")
                    });
                }
                catch (Exception)
                {
                    return(new TxResult(TxStatus.INVALID, null, null));
                }
            }
        public void UpdateTxExecutions(bool getTxExecutionViaStore)
        {
            void AssertTxSuccessesEqual(TxSuccess expected, TxExecution actual)
            {
                Assert.IsType <TxSuccess>(actual);
                var success = (TxSuccess)actual;

                Assert.Equal(expected.TxId, success.TxId);
                Assert.Equal(expected.BlockHash, success.BlockHash);
                Assert.Equal(expected.UpdatedStates, success.UpdatedStates);
                Assert.Equal(expected.FungibleAssetsDelta, success.FungibleAssetsDelta);
                Assert.Equal(expected.UpdatedFungibleAssets, success.UpdatedFungibleAssets);
            }

            void AssertTxFailuresEqual(TxFailure expected, TxExecution actual)
            {
                Assert.IsType <TxFailure>(actual);
                var failure = (TxFailure)actual;

                Assert.Equal(expected.TxId, failure.TxId);
                Assert.Equal(expected.BlockHash, failure.BlockHash);
                Assert.Equal(expected.ExceptionName, failure.ExceptionName);
                Assert.Equal(expected.ExceptionMetadata, failure.ExceptionMetadata);
            }

            Func <BlockHash, TxId, TxExecution> getTxExecution
                = getTxExecutionViaStore
                ? (Func <BlockHash, TxId, TxExecution>)_blockChain.Store.GetTxExecution
                : _blockChain.GetTxExecution;

            Assert.Null(getTxExecution(_fx.Hash1, _fx.TxId1));
            Assert.Null(getTxExecution(_fx.Hash1, _fx.TxId2));
            Assert.Null(getTxExecution(_fx.Hash2, _fx.TxId1));
            Assert.Null(getTxExecution(_fx.Hash2, _fx.TxId2));

            var random = new System.Random();
            var inputA = new TxSuccess(
                _fx.Hash1,
                _fx.TxId1,
                ImmutableDictionary <Address, IValue> .Empty.Add(
                    random.NextAddress(),
                    (Text)"state value"
                    ),
                ImmutableDictionary <Address, IImmutableDictionary <Currency, FAV> > .Empty
                .Add(
                    random.NextAddress(),
                    ImmutableDictionary <Currency, FAV> .Empty.Add(
                        DumbAction.DumbCurrency,
                        DumbAction.DumbCurrency * 5
                        )
                    ),
                ImmutableDictionary <Address, IImmutableDictionary <Currency, FAV> > .Empty
                .Add(
                    random.NextAddress(),
                    ImmutableDictionary <Currency, FAV> .Empty.Add(
                        DumbAction.DumbCurrency,
                        DumbAction.DumbCurrency * 10
                        )
                    )
                );
            var inputB = new TxFailure(
                _fx.Hash1,
                _fx.TxId2,
                "AnExceptionName",
                Dictionary.Empty.Add("foo", 1).Add("bar", "baz")
                );
            var inputC = new TxFailure(
                _fx.Hash2,
                _fx.TxId1,
                "AnotherExceptionName",
                null
                );

            _blockChain.UpdateTxExecutions(new TxExecution[] { inputA, inputB, inputC });

            AssertTxSuccessesEqual(inputA, getTxExecution(_fx.Hash1, _fx.TxId1));
            AssertTxFailuresEqual(inputB, getTxExecution(_fx.Hash1, _fx.TxId2));
            AssertTxFailuresEqual(inputC, getTxExecution(_fx.Hash2, _fx.TxId1));
            Assert.Null(getTxExecution(_fx.Hash2, _fx.TxId2));
        }