public static Gtx Decode(byte[] encodedMessage)
        {
            var gtx            = new Gtx();
            var gtxTransaction = new ASN1.AsnReader(encodedMessage);
            var gtxValue       = GTXValue.Decode(gtxTransaction);
            var gtxPayload     = gtxValue.Array[0];

            gtx.BlockchainID = PostchainUtil.ByteArrayToString(gtxPayload.Array[0].ByteArray);

            foreach (var opArr in gtxPayload.Array[1].Array)
            {
                var op = opArr.ToObjectArray();

                var opName = opArr.Array[0].String;
                var opArgs = opArr.Array[1].ToObjectArray();
                gtx.AddOperationToGtx(opName, opArgs);
            }

            foreach (var signer in gtxPayload.Array[2].Array)
            {
                gtx.AddSignerToGtx(signer.ByteArray);
            }

            foreach (var sig in gtxValue.Array[1].Array)
            {
                gtx.Signatures.Add(sig.ByteArray);
            }

            return(gtx);
        }
        public static GTXValue Decode(ASN1.AsnReader sequence)
        {
            var val = new GTXValue();

            byte choice = sequence.ReadChoice();

            sequence.ReadLength();
            switch (choice)
            {
            case ASN1.AsnUtil.TAG_NULL:
            {
                val.Choice = GTXValueChoice.Null;
                sequence.ReadChoice();
                sequence.ReadChoice();
                break;
            }

            case ASN1.AsnUtil.TAG_BYTE_ARRAY:
            {
                val.Choice    = GTXValueChoice.ByteArray;
                val.ByteArray = sequence.ReadOctetString();
                break;
            }

            case ASN1.AsnUtil.TAG_STRING:
            {
                val.Choice = GTXValueChoice.String;
                val.String = sequence.ReadUTF8String();
                break;
            }

            case ASN1.AsnUtil.TAG_INTEGER:
            {
                val.Choice  = GTXValueChoice.Integer;
                val.Integer = sequence.ReadInteger();
                break;
            }

            case ASN1.AsnUtil.TAG_ARRAY:
            {
                val.Choice = GTXValueChoice.Array;
                val.Array  = new List <GTXValue>();
                var innerSequence = sequence.ReadSequence();
                while (innerSequence.RemainingBytes > 0)
                {
                    val.Array.Add(GTXValue.Decode(innerSequence));
                }
                break;
            }

            case ASN1.AsnUtil.TAG_DICT:
            {
                val.Choice = GTXValueChoice.Dict;
                val.Dict   = new List <DictPair>();
                var innerSequence = sequence.ReadSequence();
                while (innerSequence.RemainingBytes > 0)
                {
                    val.Dict.Add(DictPair.Decode(innerSequence));
                }
                break;
            }

            default:
            {
                throw new System.Exception("Unknown choice tag: " + choice.ToString("X2"));
            }
            }

            return(val);
        }