go - 如何将任何类型的数据值传递到 Golang 中的 GRPC Protobuf 结构中?

标签 go blockchain grpc protoc ton

我正在尝试通过 tonutils-go 解析 ADNL 库中的数据并通过GRPC传递数据。

我需要的数据结构为

// struct from tonutils-go
type Transaction struct {
    _           Magic         `tlb:"$0111"`
    AccountAddr []byte        `tlb:"bits 256"`
    LT          uint64        `tlb:"## 64"`
    PrevTxHash  []byte        `tlb:"bits 256"`
    PrevTxLT    uint64        `tlb:"## 64"`
    Now         uint32        `tlb:"## 32"`
    OutMsgCount uint16        `tlb:"## 15"`
    OrigStatus  AccountStatus `tlb:"."`
    EndStatus   AccountStatus `tlb:"."`
    IO          struct {
        In  *Message      `tlb:"maybe ^"`
        Out *MessagesList `tlb:"maybe ^"`
    } `tlb:"^"`
    TotalFees   CurrencyCollection     `tlb:"."`
    StateUpdate HashUpdate             `tlb:"^"` // of Account
    Description TransactionDescription `tlb:"^"`

    // not in scheme, but will be filled based on request data for flexibility
    Hash []byte `tlb:"-"`
}

type TransactionDescription struct {
    Description any `tlb:"."`
}


type TransactionDescriptionOrdinary struct {
    _            Magic         `tlb:"$0000"`
    CreditFirst  bool          `tlb:"bool"`
    StoragePhase *StoragePhase `tlb:"maybe ."`
    CreditPhase  *CreditPhase  `tlb:"maybe ."`
    ComputePhase ComputePhase  `tlb:"."`
    ActionPhase  *ActionPhase  `tlb:"maybe ^"`
    Aborted      bool          `tlb:"bool"`
    BouncePhase  *BouncePhase  `tlb:"maybe ."`
    Destroyed    bool          `tlb:"bool"`
}

type ComputePhase struct {
    Phase any `tlb:"."`
}


type ComputePhaseVM struct {
    _                Magic `tlb:"$1"`
    Success          bool  `tlb:"bool"`
    MsgStateUsed     bool  `tlb:"bool"`
    AccountActivated bool  `tlb:"bool"`
    GasFees          Coins `tlb:"."`
    Details          struct {
        GasUsed          *big.Int `tlb:"var uint 7"`
        GasLimit         *big.Int `tlb:"var uint 7"`
        GasCredit        *big.Int `tlb:"maybe var uint 3"`
        Mode             int8     `tlb:"## 8"`
        ExitCode         int32    `tlb:"## 32"`
        ExitArg          *int32   `tlb:"maybe ## 32"`
        VMSteps          uint32   `tlb:"## 32"`
        VMInitStateHash  []byte   `tlb:"bits 256"`
        VMFinalStateHash []byte   `tlb:"bits 256"`
    } `tlb:"^"`
}

TxTest的protobuf:

message TxTest {
   int32 exitCode = 1;
}

我要解析的数据是ExitCode,代码如下:

    list, err := api.ListTransactions(context.Background(), addr, 1, uint64(txInfo.TxLT), data)
    if err != nil {
        log.Printf("send err: %s", err.Error())
        return nil, err
    }
    for _, t := range list {
        a := t.Description.Description

        var result tlb.TransactionDescriptionOrdinary

        b, err := json.MarshalIndent(a, "", "  ")
        if err != nil {
            fmt.Println("error:", err)
        }
        json.Unmarshal([]byte(string(b)), &result)

        var computePhase tlb.ComputePhaseVM

        c, err := json.MarshalIndent(result.ComputePhase.Phase, "", "  ")
        if err != nil {
            fmt.Println("error:", err)
        }

        json.Unmarshal([]byte(string(c)), &computePhase)


        detail := &pb.TxTest{
            ExitCode: computePhase.Details.ExitCode,
        }
        detail2 := struct {
            ExitCode int32 `json:"exit_code"`
        }{
            ExitCode: computePhase.Details.ExitCode,
        }

        fmt.Printf("detail: %+v\n", detail)
        fmt.Printf("detail2: %+v\n", detail2)

    }

一笔交易的数据结构为:

{
  "AccountAddr": "HYmM1/kK6GB2DLV3zVkIRyEpKoHRTF/jG8K7tTG91sQ=",
  "LT": 11898016000001,
  "PrevTxHash": "iKGjsxdT0gzIJXGNIlvxy0+a1gGEQDED4f7ZAJ9dlmc=",
  "PrevTxLT": 11897712000001,
  "Now": 1685602760,
  "OutMsgCount": 1,
  "OrigStatus": "ACTIVE",
  "EndStatus": "ACTIVE",
  "IO": {
    "In": {
      "MsgType": "EXTERNAL_IN",
      "Msg": {
        "SrcAddr": "NONE",
        "DstAddr": "EQAdiYzX-QroYHYMtXfNWQhHISkqgdFMX-Mbwru1Mb3WxN5D",
        "ImportFee": "0",
        "StateInit": null,
        "Body": {}
      }
    },
    "Out": {
      "List": {}
    }
  },
  "TotalFees": {
    "Coins": "22324812",
    "ExtraCurrencies": {}
  },
  "StateUpdate": {
    "OldHash": "WUkeXyOS8hsWyQYRLHPmJHpfMUSID8oDTAq6fY20pyQ=",
    "NewHash": "e8tn4cP4lAkFwvDcGc/VqBZ7lZeB4mhjMbRFE8rpsQA="
  },
  "Description": {
    "Description": {
      "CreditFirst": true,
      "StoragePhase": {
        "StorageFeesCollected": "484",
        "StorageFeesDue": null,
        "StatusChange": {
          "Type": "UNCHANGED"
        }
      },
      "CreditPhase": null,
      "ComputePhase": {
        "Phase": {
          "Success": true,
          "MsgStateUsed": false,
          "AccountActivated": false,
          "GasFees": "19862000",
          "Details": {
            "GasUsed": 19862,
            "GasLimit": 0,
            "GasCredit": 10000,
            "Mode": 0,
            "ExitCode": 0,
            "ExitArg": null,
            "VMSteps": 404,
            "VMInitStateHash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
            "VMFinalStateHash": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
          }
        }
      },
      "ActionPhase": {
        "Success": true,
        "Valid": true,
        "NoFunds": false,
        "StatusChange": {
          "Type": "UNCHANGED"
        },
        "TotalFwdFees": "1000000",
        "TotalActionFees": "333328",
        "ResultCode": 0,
        "ResultArg": null,
        "TotalActions": 1,
        "SpecActions": 0,
        "SkippedActions": 0,
        "MessagesCreated": 1,
        "ActionListHash": "Fkoo2xX9jU4YxTGJlrUjvaYrRWTrYHEBkUywUYg9AV4=",
        "TotalMsgSize": {
          "Cells": 1,
          "Bits": 697
        }
      },
      "Aborted": false,
      "BouncePhase": null,
      "Destroyed": false
    }
  },
  "Hash": "VMXfRKfIEtmAiHm3brTvhSkAidE1CkgRW8RQBVarJtQ="
}

detaildetail2 的输出为:

detail: 
detail2: {ExitCode:0}

我的问题是为什么由 protoc 生成的结构无法解析 transaction 中的 exitCode 但我定义的结构可以很好地工作?

如何将数据注入(inject)到protoc生成的TxTest结构体中,并让我通过GRPC传输数据?

最佳答案

使用 0 以外的退出代码值尝试此操作,我猜您会得到不同的结果。

看看您生成的代码。我相信正在发生的事情是fmt.Printf正在为您的 proto 结构调用生成的 String() 方法,该方法使用 prototext 包来打印消息的内容,而不是默认的 Go 结构打印机。

这是expected behavior for for proto3; 0int32 值和空字段之间没有区别。

关于go - 如何将任何类型的数据值传递到 Golang 中的 GRPC Protobuf 结构中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76395739/

相关文章:

go - grpc:使用 oneof 会导致无效的内存地址或 nil 指针取消引用

protocol-buffers - gRPC 和模式演化保证?

go - 为什么这两个golang整数转换函数会给出不同的结果?

go - 出乎意料的是我的代码基于 `map[int][][]int` 的结果

google-app-engine - 谷歌应用引擎 TCP/IP 连接

blockchain - 如何知道我的 Waves 节点是否在 fork 上?

authentication - gRPC中如何使用Oauth2进行用户认证

go - golang中高效的日志解析

python - 编译AggregatorV2V3Interface导致TypeError : Interfaces cannot inherit.接口(interface)

function - 如何从 Julia 结构的构造函数中调用函数?