如何通过区块号获取交易哈希?

huangapple go评论82阅读模式
英文:

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" : "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" } ] } }
英文:

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().

huangapple
  • 本文由 发表于 2022年7月13日 01:37:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/72956339.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定