英文:
How can i get transactionHash by blockNumber?
问题
如何通过blockNumber获取transactionHash?
我尝试了block.transactions.0.transactionHash,但没有获取到(为空字符串)。我该如何获取transactionHash?
以下是要翻译的代码部分:
func GetBlockTransactions(number int) string {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
var hashHeaders []models.Block
defer cancel()
options := options.Find().SetProjection(bson.M{"block.transactions.0.transactionHash": 1})
options.SetLimit(1)
results, err := blocksCollections.Find(ctx, bson.M{"block.header.blockNumber": strconv.Itoa(number)}, options)
if err != nil {
fmt.Println(err)
}
//reading from the db in an optimal way
defer results.Close(ctx)
for results.Next(ctx) {
var singleHashHeader models.Block
if err = results.Decode(&singleHashHeader); err != nil {
fmt.Println(err)
}
hashHeaders = append(hashHeaders, singleHashHeader)
}
fmt.Println("%v", hashHeaders[0].Transactions.TransactionHash)
return string(hashHeaders[0].Transactions.TransactionHash)
}
编辑:
我的结构体如下(已编辑):
type BlockHeader struct {
HashHeader string `json:"hashHeader,omitempty"`
BlockNumber string `json:"blockNumber,omitempty"`
TimestampSeconds string `json:"timestampSeconds,omitempty"`
HashHeaderPrev string `json:"hashHeaderPrev,omitempty"`
RewardBlock string `json:"rewardBlock,omitempty"`
MerkleRoot string `json:"merkleRoot,omitempty"`
MiningNonce int `json:"miningNonce,omitempty"`
ExtraNonce string `json:"extraNonce,omitempty"`
}
type Header struct {
Header BlockHeader
}
type CoinbaseTransaction struct {
AddrTo string `json:"addrTo,omitempty"`
Amount string `json:"amount,omitempty"`
}
type BlockTransaction struct {
MasterAddr string `json:"masterAddr,omitempty"`
Nonce string `json:"nonce,omitempty"`
TransactionHash string `json:"transactionHash,omitempty"`
Coinbase []CoinbaseTransaction `json:"coinbase"`
}
type Block struct {
Block Header `json:"block"`
Transactions []BlockTransaction `json:"transactions"`
}
当前代码:
func GetBlockTransactions(number int) (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// options := options.Find().
// SetProjection(bson.M{"block.transactions.transactionHash": 1}).
// SetLimit(1)
results, err := blocksCollections.Find(ctx, bson.M{"block.header.blockNumber": strconv.Itoa(number)})
if err != nil {
return "", fmt.Errorf("Find() failed: %w", err)
}
var blocks []models.Block
err = results.All(ctx, &blocks)
if err != nil {
return "", fmt.Errorf("Cursor.All() failed: %w", err)
}
for _, block := range blocks {
fmt.Printf("header: %v", block.Block.Header)
for _, tx := range block.Transactions {
fmt.Printf("transaction: %v", tx)
}
}
fmt.Printf("hash: %v\n", blocks[0].Transactions[0].TransactionHash)
return string(blocks[0].Transactions[0].TransactionHash), nil
}
mongo shell 输出
这是一个示例文档,例如块编号为15。以下是所有详细信息。
{ "_id" : ObjectId("62caea8923ca1b926b789122"), "block" : { "header" : { "hashHeader" : "6WKsUtRXGWqIMs/VcwT8CAU384Uab8NMOwB7wMoAAAA=", "blockNumber" : "15", "timestampSeconds" : "1530015361", "hashHeaderPrev" : "y4G/O/Oj19+AOZNMF4yPL2xVdl/TQI+ErBjhihUAAAA=", "rewardBlock" : "6656333953", "rewardFee" : "1000000", "merkleRoot" : "/gRuLu8UGAG621xvGA7M4rZmWbsMophiQ3xPprTVJkU=", "miningNonce" : NumberLong("2781151944"), "extraNonce" : "16980399104" }, "transactions" : [ { "masterAddr" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", "nonce" : "16", "transactionHash" : "Jp8fU6h9yqh6onymq/lFEJq/XRHPKKbj+drmvHOi5gY=", "coinbase" : { "addrTo" : "AQYAHTRijaCHM53dZQqEPhMfpKPzsQfptiItYJ9trThgtHmMxbNh", "amount" : "6657333953" } }, { "fee" : "1000000", "publicKey" : "AAYAs6Tt7+YeX6sEZfTeaKUAMF7RAURH7Khcs2vnTW23LrVBf+FCFer87crYcsUx9ureHHugTG+J/tKwcYPBgMk6vw==", "signature" : "AAAAAH8Tfjt2e/4J+xec8eWlgWXPlPOquRu+RZz5yT3hXdVF3uwhvbxasw9oj6+SpAwjy1ICSdlBeefasS970ker/DvBzLX93ryAxHI66+WqZQ9aj7gSVEhqTzylMzDj/I4P34ScaQ7kwRF/6Q3DnA/qiG/q4zc5MmHeU/pBp/+ngEMcM/cFSrCNQE+Us7B7Sp2Ws6inix3y+SGbrznsBDWdTcxIpq4k/0Od9VIBFA09th/svLZCbH5YGfZ7IboT4NQx7hTnANLNTLo4ztkX2u6B8WkFrJ3LV6VS3C7w7pRuhItlSIl/slVMhYizgCjVpzNb0C8JMtZeqb6sarcqSwarQiX65NVrj6ux7pJtJT08gCc2nxh3HwjhYahzjRoCkIGQbHYqfGkKkAyRIig3wu4K+NsoG13UKxIaVy/kJSB5NRMEFVG1Xp2JLj3WqlnTeNnIMAGz7V/srVji8EXtcODjuOL0Qoenhesocl5+dbX0lyMu++qhXQuXzcxm+dBW4TMSyoI2xSlgCLdqRNuHstOwmAdZ7qnTOKOASp5EsZGj5vPTjnP+9GcLxM5ms++MU57A3ciAjDaVpX2AoShLcP9xW/jBI0/ijGZvzA4mRIIkmwCC+EOklXH/c0JB832SrhQy/cc3v1kYYITu4pkqFl7EAzzGCEy3yLdrdhzsYSN6tlTOqO57rHzehu/1xJg9LmT5LyixJVzW58DsO0swSeT+dZMNR5AZmyWp4aj633YUEi8p9KKmCgEceF4T+54MZJbIQExwX4CFQ1GLJVQiEZdXy/PR3cr6AFUQGwp5ZJ8+gFLDhWGFVuHPH3HxTstyepTSQQUb8JFv4G0nM/INXpWXHvNdEvOEyDUzkfJ11yhbkCrMLak8AumtPnoNnZQXyxaUa4YX5Z8tkmbNRQWtjC/6NGTcHWQ8IKf6MxVjQCdHtqTRzgfRYOh/+/bzRy7p3o0p95Hn4Yxuf3BBshnJJmg2mKoS6sc8V8cA44YpaA9eP9Ce4G3knJ/wxuWRWzZmxC+yl43qgofPU5xGWQEf6vtTS0JJ7fv61mFYhM4REt+FocXf3bjifP08qrAFZNDejODjycLNXlmBahqp8mqKTvllofbeLrYnYrcCH9KMfXGGL4PZLKnmh+bHlolWEn8Y4hxOlVkfRjYvBakfEsAgS+MQEtkN4tGqHwT2Taz1014PAbO90O8HFZb5I146Yb4JpL38wpuvfKMBR161MNn7LLO8vOv4aZE2SBySJE6XoYIxfFL+KlP4MXqGGm2kWomR2+HtvSCl7dRwfUapLlrE1xcP44HbYsDYM+z5z6mWMvxQHj9WDovi7OvdwoIV3kMChSTA9DR8gqOgtDItZ9UrsDjJdhLF7aZ8/D6vyEJGAwRi3NCUYo4mBLPF5EnhXqHnmogwWh+vzW37RiyHHnUxwQWDJPc81RMlXnGjIT6/KCXjrvCeYUr2Lj+K8OIaNKgiuRsRjC5h/83btOWJ7PMjLMyyg1aklgkam4Hp13bVZo3zIwNsTlOt9jAn+QNPPUtzToKaD+twG3m+GglN/kaeA6/Bmm10qIKAWkPCNP0xkEDKYDIUhxaix++sZLYSPRWRi/M3sEc79WwSZVc7sunNYWnHOvPhubDgLfO6AjFpbqYU7g6q06A4+zG85bu0vXxRucZMMO7njrHnW30Xw3vU3oFQlpFEmWBZ8S+a53wyXBK+fNC6PgBIqyF4qhVk8YJDHpkJW9zBwjytE8nSkTV4wCD+qexfrvJvREQESDzT3eT2YfWoqEKWqPknwGK0W6TNXwmv7xMWB8zKS2LThAqotZRH6S9V1zJVbSsSrsO2+Ct8kVXGrioWxZ84Wj3R5tGBghwLbOTBlfP/jxKFbUIyEJ6hUiCFhYI/qoayi3j9Tdh1ChhnhF+4Id32QhzMemQvO/+2uKxvu3CE5grZmRD93TdNRBz751QI+EsoAMLT7Gx6LUqHVLd4q1NnO79hQFr+YBunt0KYZolVZoEnMqUhkmyPUkSjadoBKHMD6MEViDcGgaqNs7n+0Z+Mr7leOJXwg67hG2MX6M23VAANMagEgPw4ub1fZF1p7rpHGakW8j4apLVVHOibJNj8HNWXtElALQI8ZThlIhkdc/e7mSIlio4jiNYkuuhaXd5I8X67u2GYkqGlPibSf+90u/qQ22iRsIBE63fgbjNxv9KN6CR1XEhWaZA+jgWCtcFTo46Ge3ZBbEZ7DWL6ExDM/U4+CHnpw8n7RUKV1GUCCzr9KFqFpxqdzCCdBUct9pu6ejcph+5vKH/Gh6H7MBNGVwlwSuxloBBHS6xfb7ho6UFqzvO1qfNjCH3/50Wc3MhLZxftmTf2VO4/emW1XdfFvH9WaA8968Fhr4WJ+tuPWSZ/U88drb2siLavdkhGHPOdXWSuDOvnFr9qIK1TlFpylWkNQrHRsrOscDlCgllbS8v9GOg1Yp2X/KDGFXzZa1elaqJazur43Q6ktyA2RIz9O2l//R3ktU2SME9fB2anh+Oiz3+VUyNRjJRNF3oC82NxIEt/cRDvcLI+qEB/HVBvv1nXQ728Ri0EXocER2EvDr9C1jiBZu2VOuRjPzeo1QMaCABqQCipJBNgWUXMHvTAvK1GwCxQg8q4gSDkfMyKeSlinoJI8vs8oNicFJlnVembWrCYt/+tn9UD2ygguklwXpwbv+WypHg3nagpk2bsi0EAZ3wJaAXwvFxwREsxyvq6SWl2u3o+loyuu322NbgQeA+/HGYvSaKmb7CjSSBl2EtDpQI77LzYcFZmEtD+8DM3JHza85/g0x4VNL5GzZ6UTLtpd1B/g3XxmNcrqBp/ppJYYDBK9NK79FodDpQlAWlPREkWPsV7X8IkxzG7i6jHxTIiuO0Nyrb1yiPWfa/onjOJVRp4wW4yVOY8vWOkTaz1zNBqR3mZ0RnebHWKr4/0wNM0jV3WaZd096es/D1nrDEQytAnb6ORlbxKAqX/2zHWexMgCCgzuj1jz5NJIkMKQxhtKnHBPTbCz1ZUzfL9tPjzFqAQ99shrusUXdueuLXjoIVFVn+gULAx5+uDSIU7ERiqtc5LgVeeyzeA35E/gSHNKqu1v822xGg/70csYT69nMzHHVjwSnaC0/GOs5esFS7S4QkaOMgkS6MZiKdAqYkJ9nJN+wqY15JNxbmB0tU7C2XjdKGxV1mRcjtxAdxS9JNYurBPw7l4zviAqXzmL/So/rwJUnaw0L/gha92vgECXu16lqDKuKydGSssFvFuCJpA6IzEEIkvuqV+CLcEto35nkwrjBl4YZGM/nRmoI1y/qSvqJx9PNoMkeZZGQsoFtPggXYge53v5pX9I2kZ3hgY9zNXOGdzDqEUlqTVVHYLnBddo3eIfRSz31+IoOvG0QCO/Qvu9rwtuZCIltnhQWfRc4FmWsj9JUs=" } ] } }
英文:
How to get the transactionHash by blockNumber?
I entered block.transactions.0.transactionHash but that didn't catch it (empty string). How can i get the transactionHash?
func GetBlockTransactions(number int) string {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
var hashHeaders []models.Block
defer cancel()
options := options.Find().SetProjection(bson.M{"block.transactions.0.transactionHash": 1})
options.SetLimit(1)
results, err := blocksCollections.Find(ctx, bson.M{"block.header.blockNumber": strconv.Itoa(number)}, options)
if err != nil {
fmt.Println(err)
}
//reading from the db in an optimal way
defer results.Close(ctx)
for results.Next(ctx) {
var singleHashHeader models.Block
if err = results.Decode(&singleHashHeader); err != nil {
fmt.Println(err)
}
hashHeaders = append(hashHeaders, singleHashHeader)
}
fmt.Println("%v", hashHeaders[0].Transactions.TransactionHash)
return string(hashHeaders[0].Transactions.TransactionHash)
}
Edit:
My structs look like this (edited):
type BlockHeader struct {
HashHeader string `json:"hashHeader,omitempty"`
BlockNumber string `json:"blockNumber,omitempty"`
TimestampSeconds string `json:"timestampSeconds,omitempty"`
HashHeaderPrev string `json:"hashHeaderPrev,omitempty"`
RewardBlock string `json:"rewardBlock,omitempty"`
MerkleRoot string `json:"merkleRoot,omitempty"`
MiningNonce int `json:"miningNonce,omitempty"`
ExtraNonce string `json:"extraNonce,omitempty"`
}
type Header struct {
Header BlockHeader
}
type CoinbaseTransaction struct {
AddrTo string `json:"addrTo,omitempty"`
Amount string `json:"amount,omitempty"`
}
type BlockTransaction struct {
MasterAddr string `json:"masterAddr,omitempty"`
Nonce string `json:"nonce,omitempty"`
TransactionHash string `json:"transactionHash,omitempty"`
Coinbase []CoinbaseTransaction
}
type Block struct {
Block Header
Transactions []BlockTransaction
}
Current code:
func GetBlockTransactions(number int) (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// options := options.Find().
// SetProjection(bson.M{"block.transactions.transactionHash": 1}).
// SetLimit(1)
results, err := blocksCollections.Find(ctx, bson.M{"block.header.blockNumber": strconv.Itoa(number)})
if err != nil {
return "", fmt.Errorf("Find() failed: %w", err)
}
var blocks []models.Block
err = results.All(ctx, &blocks)
if err != nil {
return "", fmt.Errorf("Cursor.All() failed: %w", err)
}
for _, block := range blocks {
fmt.Printf("header: %v", block.Block.Header)
for _, tx := range block.Transactions {
fmt.Printf("transaction: %v", tx)
}
}
fmt.Printf("hash: %v\n", blocks[0].Transactions[0].TransactionHash)
return string(blocks[0].Transactions[0].TransactionHash), nil
}
mongo shell output
Here is the document, block number 15 for example. Here are all the details, included below.
{ "_id" : ObjectId("62caea8923ca1b926b789122"), "block" : { "header" : { "hashHeader" : "6WKsUtRXGWqIMs/VcwT8CAU384Uab8NMOwB7wMoAAAA=", "blockNumber" : "15", "timestampSeconds" : "1530015361", "hashHeaderPrev" : "y4G/O/Oj19+AOZNMF4yPL2xVdl/TQI+ErBjhihUAAAA=", "rewardBlock" : "6656333953", "rewardFee" : "1000000", "merkleRoot" : "/gRuLu8UGAG621xvGA7M4rZmWbsMophiQ3xPprTVJkU=", "miningNonce" : NumberLong("2781151944"), "extraNonce" : "16980399104" }, "transactions" : [ { "masterAddr" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", "nonce" : "16", "transactionHash" : "Jp8fU6h9yqh6onymq/lFEJq/XRHPKKbj+drmvHOi5gY=", "coinbase" : { "addrTo" : "AQYAHTRijaCHM53dZQqEPhMfpKPzsQfptiItYJ9trThgtHmMxbNh", "amount" : "6657333953" } }, { "fee" : "1000000", "publicKey" : "AAYAs6Tt7+YeX6sEZfTeaKUAMF7RAURH7Khcs2vnTW23LrVBf+FCFer87crYcsUx9ureHHugTG+J/tKwcYPBgMk6vw==", "signature" : "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", "nonce" : "1", "transactionHash" : "vGS9M6aerWCoEj0BqbW5IwZ7jyw4jpECEJ/b1uL5oc0=", "token" : { "symbol" : "RnIxdDI=", "name" : "RnIxdDI=", "owner" : "AAYAPHpYp+dc/fVXo8Oi3LnaBPDhCCVEh6/H8mBuuoCbMzffYw1r", "decimals" : "10", "initialBalances" : [ { "address" : "AAYAPHpYp+dc/fVXo8Oi3LnaBPDhCCVEh6/H8mBuuoCbMzffYw1r", "amount" : "1000000000000000000" } ] } } ] } }
答案1
得分: 1
你的方法存在3个错误。
首先,对blocks集合的find()
操作返回的是完整的文档,而不仅仅是block文档(即block
字段)。因此,需要将解组的结果存储到一个描述完整文档的类型中,例如:
type Doc struct {
ID primitive.ObjectID `bson:"_id"`
Block Block `bson:"block"`
}
解组的代码如下:
var doc Doc
if err = results.Decode(&doc); err != nil {
fmt.Println(err)
}
hashHeaders = append(hashHeaders, doc.Block)
其次,transactions
是一个数组,在Go中需要使用切片来表示:
type Block struct {
Transactions []BlockTransaction
}
第三,投影和过滤器中的对象数组字段的属性不需要使用索引,因此使用投影:
options := options.Find().
SetProjection(bson.M{"block.transactions.transactionHash": 1})
另外,请注意你可以使用Cursor.All()
方法简单地解码结果,如下所示:
var docs []Doc
err = results.All(ctx, &docs)
if err != nil {
fmt.Println(err)
}
完整的工作代码如下:
func GetBlockTransactions(number int) string {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
options := options.Find().
SetProjection(bson.M{"block.transactions.transactionHash": 1}).
SetLimit(1)
results, err := blocksCollections.Find(ctx, bson.M{"block.header.blockNumber": strconv.Itoa(number)}, options)
if err != nil {
fmt.Println(err)
}
var docs []Doc
err = results.All(ctx, &docs)
if err != nil {
fmt.Println(err)
}
fmt.Printf("hash: %v\n", docs[0].Block.Transactions[0].TransactionHash)
return string(docs[0].Block.Transactions[0].TransactionHash)
}
此外,请注意如果遇到错误,后续的代码很可能会失败,因此应该提前返回。你还应该返回一个带有注释的错误。
像这样:
func GetBlockTransactions(number int) (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
options := options.Find().
SetProjection(bson.M{"block.transactions.transactionHash": 1}).
SetLimit(1)
results, err := blocksCollections.Find(ctx, bson.M{"block.header.blockNumber": strconv.Itoa(number)}, options)
if err != nil {
return "", fmt.Errorf("Find() failed: %w", err)
}
var docs []Doc
err = results.All(ctx, &docs)
if err != nil {
return "", fmt.Errorf("Cursor.All() failed: %w", err)
}
fmt.Printf("hash: %v\n", docs[0].Block.Transactions[0].TransactionHash)
return string(docs[0].Block.Transactions[0].TransactionHash), nil
}
另外请注意,如果你只期望得到一个结果,更简单的解决方案是使用Collection.FindOne()
。
英文:
3 errors in your approach.
First, a find()
on the blocks collection returns complete documents, not just the block documents (being the block
field). So unmarshal results into a value of type that describes the complete documents, e.g.:
type Doc struct {
ID primitive.ObjectID `bson:"_id"`
Block Block `bson:"block"`
}
And the unmarshaling code:
var doc Doc
if err = results.Decode(&doc); err != nil {
fmt.Println(err)
}
hashHeaders = append(hashHeaders, doc.Block)
Second, transactions
is an array, so in Go you must model it with a slice:
type Block struct {
Transactions []BlockTransaction
}
Third, Properties of objects array fields in projections and filters are referred to without indices, so use a projection:
options := options.Find().
SetProjection(bson.M{"block.transactions.transactionHash": 1})
Also note that you can simply decode results using the Cursor.All()
method like this:
var docs []Doc
err = results.All(ctx, &docs)
if err != nil {
fmt.Println(err)
}
Working complete code:
func GetBlockTransactions(number int) string {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
options := options.Find().
SetProjection(bson.M{"block.transactions.transactionHash": 1}).
SetLimit(1)
results, err := blocksCollections.Find(ctx, bson.M{"block.header.blockNumber": strconv.Itoa(number)}, options)
if err != nil {
fmt.Println(err)
}
var docs []Doc
err = results.All(ctx, &docs)
if err != nil {
fmt.Println(err)
}
fmt.Printf("hash: %v\n", docs[0].Block.Transactions[0].TransactionHash)
return string(docs[0].Block.Transactions[0].TransactionHash)
}
Also note that if an error is encountered, subsequent code is likely to fail, so you should return early. You should also return an annotated error.
Like this:
func GetBlockTransactions(number int) (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
options := options.Find().
SetProjection(bson.M{"block.transactions.transactionHash": 1}).
SetLimit(1)
results, err := blocksCollections.Find(ctx, bson.M{"block.header.blockNumber": strconv.Itoa(number)}, options)
if err != nil {
return "", fmt.Errorf("Find() failed: %w", err)
}
var docs []Doc
err = results.All(ctx, &docs)
if err != nil {
return "", fmt.Errorf("Cursor.All() failed: %w", err)
}
fmt.Printf("hash: %v\n", docs[0].Block.Transactions[0].TransactionHash)
return string(docs[0].Block.Transactions[0].TransactionHash), nil
}
Also note that if you're expected exactly one result, a simpler solution is to use Collection.FindOne()
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论