/// <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); }
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))); }
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 ); }
/// <inheritdoc cref="IStore.PutTxExecution(Libplanet.Tx.TxSuccess)"/> public void PutTxExecution(TxSuccess txSuccess) => _store.PutTxExecution(txSuccess);
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)); }
/// <inheritdoc cref="BaseStore.PutTxExecution(Libplanet.Tx.TxSuccess)"/> public override void PutTxExecution(TxSuccess txSuccess) => _txExecutionDb.Put( TxExecutionKey(txSuccess), Codec.Encode(SerializeTxExecution(txSuccess)) );
public void PutTxExecution(TxSuccess txSuccess) { Log(nameof(PutTxExecution), txSuccess); _store.PutTxExecution(txSuccess); }
/// <inheritdoc cref="IStore.PutTxExecution(TxSuccess)"/> public virtual void PutTxExecution(TxSuccess txSuccess) => Store.PutTxExecution(txSuccess);
/// <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)); }