示例#1
0
 internal SubmitMessageReceipt FillProperties(TransactionID transactionId, SubmitMessageReceipt receipt)
 {
     FillCommonProperties(transactionId, receipt);
     receipt.RunningHash        = TopicRunningHash?.ToByteArray();
     receipt.RunningHashVersion = TopicRunningHashVersion;
     receipt.SequenceNumber     = TopicSequenceNumber;
     return(receipt);
 }
示例#2
0
 protected async Task HandleValidSubmit()
 {
     _output = null;
     await _network.ExecuteAsync(_input.Gateway, _input.Payer, async client =>
     {
         var message = _input.MessageIsHex ? Hex.ToBytes(_input.Message) : Encoding.UTF8.GetBytes(_input.Message);
         _output     = await client.SubmitMessageAsync(_input.Topic, message, ctx => ctx.Memo = _input.Memo?.Trim());
     });
 }
示例#3
0
        /// <summary>
        /// Sends an HCS message of arbitrary size
        /// to the network by breaking the message
        /// into segments, submitting each segment
        /// in sequence.  Manages the segment metadata
        /// internally, returning an array of receipts
        /// representing the transactions required to
        /// upload the entier message.
        /// </summary>
        /// <param name="client">
        /// A Hashgraph Client instance.
        /// </param>
        /// <param name="topic">
        /// The address of the topic for the message.
        /// </param>
        /// <param name="message">
        /// The value of the message, may exceed the
        /// network limit size.
        /// </param>
        /// <param name="segmentSize">
        /// The maximum size of each segment.  Must
        /// be under the current allowed size for
        /// transactions currently supported by the
        /// network.  The method will break the
        /// message into as many segments as necessary
        /// to fulfill uploading the entire message.
        /// </param>
        /// <param name="signatory">
        /// The signatory containing any additional private keys or callbacks
        /// to meet the key signing requirements for participants.
        /// </param>
        /// <param name="configure">
        /// Optional callback method providing an opportunity to modify
        /// the execution configuration for just this method call.
        /// It is executed prior to submitting the request to the network.
        /// </param>
        /// <returns>
        /// An array of Submit Message Receipts indicating success, one for each
        /// segment uploaded.  The Transaction ID of the first receipt matches
        /// the correlation transaction ID for the series of message segments
        /// as a whole.
        /// </returns>
        /// <exception cref="ArgumentOutOfRangeException">If required arguments are missing.</exception>
        /// <exception cref="InvalidOperationException">If required context configuration is missing.</exception>
        /// <exception cref="PrecheckException">If the gateway node create rejected the request upon submission.</exception>
        /// <exception cref="ConsensusException">If the network was unable to come to consensus before the duration of the transaction expired.</exception>
        /// <exception cref="TransactionException">If the network rejected the create request as invalid or had missing data.</exception>

        public static async Task <SubmitMessageReceipt[]> SubmitLargeMessageAsync(this Client client, Address topic, ReadOnlyMemory <byte> message, int segmentSize, Signatory?signatory = null, Action <IContext>?configure = null)
        {
            await using var configuredClient = client.Clone(configure);
            var segmentCount = (message.Length - 1) / segmentSize + 1;
            var receipts     = new SubmitMessageReceipt[segmentCount];

            receipts[0] = await configuredClient.SubmitMessageAsync(new SubmitMessageParams
            {
                Topic             = topic,
                Segment           = segmentCount > 1 ? message.Slice(0, segmentSize) : message,
                Index             = 1,
                TotalSegmentCount = segmentCount,
                Signatory         = signatory
            }).ConfigureAwait(false);

            var parentTx = receipts[0].Id;

            for (int i = 1; i < segmentCount - 1; i++)
            {
                receipts[i] = await configuredClient.SubmitMessageAsync(new SubmitMessageParams
                {
                    Topic             = topic,
                    Segment           = message.Slice(segmentSize *i, segmentSize),
                    ParentTxId        = parentTx,
                    Index             = i + 1,
                    TotalSegmentCount = segmentCount,
                    Signatory         = signatory
                }).ConfigureAwait(false);
            }
            if (segmentCount > 1)
            {
                receipts[segmentCount - 1] = await configuredClient.SubmitMessageAsync(new SubmitMessageParams
                {
                    Topic             = topic,
                    Segment           = message.Slice(segmentSize * (segmentCount - 1)),
                    ParentTxId        = parentTx,
                    Index             = segmentCount,
                    TotalSegmentCount = segmentCount,
                    Signatory         = signatory
                }).ConfigureAwait(false);
            }
            return(receipts);
        }
    public async Task CanSubmitTwoSegmentedMessage()
    {
        await using var fx = await TestTopic.CreateAsync(_network);

        var submitParams = new SubmitMessageParams[2];
        var receipt      = new SubmitMessageReceipt[2];

        submitParams[0] = new SubmitMessageParams
        {
            Topic             = fx.Record.Topic,
            Segment           = Encoding.ASCII.GetBytes(Generator.String(120, 199)),
            Index             = 1,
            TotalSegmentCount = 2,
            Signatory         = fx.ParticipantPrivateKey
        };
        receipt[0] = await fx.Client.SubmitMessageAsync(submitParams[0]);

        Assert.Equal(ResponseCode.Success, receipt[0].Status);
        Assert.Equal(1ul, receipt[0].SequenceNumber);
        Assert.False(receipt[0].RunningHash.IsEmpty);
        Assert.Equal(3ul, receipt[0].RunningHashVersion);
        var txId = receipt[0].Id;

        submitParams[1] = new SubmitMessageParams
        {
            Topic             = fx.Record.Topic,
            Segment           = Encoding.ASCII.GetBytes(Generator.String(120, 199)),
            ParentTxId        = txId,
            Index             = 2,
            TotalSegmentCount = 2,
            Signatory         = fx.ParticipantPrivateKey
        };
        receipt[1] = await fx.Client.SubmitMessageAsync(submitParams[1]);

        Assert.Equal(ResponseCode.Success, receipt[1].Status);
        Assert.Equal(2ul, receipt[1].SequenceNumber);
        Assert.False(receipt[1].RunningHash.IsEmpty);
        Assert.Equal(3ul, receipt[1].RunningHashVersion);

        var info = await fx.Client.GetTopicInfoAsync(fx.Record.Topic);

        Assert.Equal(fx.Memo, info.Memo);
        Assert.NotEmpty(info.RunningHash.ToArray());
        Assert.Equal(2UL, info.SequenceNumber);
        Assert.True(info.Expiration > DateTime.MinValue);
        Assert.Equal(new Endorsement(fx.AdminPublicKey), info.Administrator);
        Assert.Equal(new Endorsement(fx.ParticipantPublicKey), info.Participant);
        Assert.True(info.AutoRenewPeriod > TimeSpan.MinValue);
        Assert.Equal(fx.TestAccount.Record.Address, info.RenewAccount);
        AssertHg.NotEmpty(info.Ledger);

        await Task.Delay(7000); // give the beta net time to sync

        try
        {
            await using var mirror = _network.NewMirror();
            var topicMessages = await TopicMessageCapture.CaptureOrTimeoutAsync(mirror, fx.Record.Topic, submitParams.Length, 7000);

            if (topicMessages.Length == 0)
            {
                _network.Output?.WriteLine("INDETERMINATE TEST - MIRROR NODE DID NOT RETURN TOPIC IN ALLOWED TIME");
            }
            else
            {
                Assert.Equal(2, topicMessages.Length);
                for (int i = 0; i < topicMessages.Length; i++)
                {
                    var topicMessage = topicMessages[i];
                    Assert.Equal(fx.Record.Topic, topicMessage.Topic);
                    Assert.Equal((ulong)i + 1, topicMessage.SequenceNumber);
                    Assert.Equal(receipt[i].RunningHash.ToArray(), topicMessage.RunningHash.ToArray());
                    Assert.Equal(submitParams[i].Segment.ToArray(), topicMessage.Messsage.ToArray());
                    Assert.NotNull(topicMessage.SegmentInfo);
                    Assert.Equal(txId, topicMessage.SegmentInfo.ParentTxId);
                    Assert.Equal(i + 1, topicMessage.SegmentInfo.Index);
                    Assert.Equal(submitParams.Length, topicMessage.SegmentInfo.TotalSegmentCount);
                }
            }
        }
        catch (MirrorException mex) when(mex.Code == MirrorExceptionCode.TopicNotFound)
        {
            _network.Output?.WriteLine("INDETERMINATE TEST - MIRROR NODE DID NOT RECEIVE TOPIC CREATE IN ALLOWED TIME");
            return;
        }
    }