我正在尝试通过 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="
}
detail
和 detail2
的输出为:
detail:
detail2: {ExitCode:0}
我的问题是为什么由 protoc
生成的结构无法解析 transaction
中的 exitCode
但我定义的结构可以很好地工作?
如何将数据注入(inject)到protoc
生成的TxTest
结构体中,并让我通过GRPC
传输数据?
最佳答案
使用 0 以外的退出代码值尝试此操作,我猜您会得到不同的结果。
看看您生成的代码。我相信正在发生的事情是fmt.Printf
正在为您的 proto 结构调用生成的 String()
方法,该方法使用 prototext
包来打印消息的内容,而不是默认的 Go 结构打印机。
这是expected behavior for for proto3
; 0
的 int32
值和空字段之间没有区别。
关于go - 如何将任何类型的数据值传递到 Golang 中的 GRPC Protobuf 结构中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76395739/