利用go语言获取比特币余额

如何获取余额

我们输入一个比特币地址,然后获取对应比特币地址拥有者对应的pubkey,由该公钥检测utxo集,获取未花费交易,累加value,从而获取地址对应的余额

代码实现

func (cli *CLI) getBalance(address, nodeID string) {
    if !ValidateAddress(address) {
        log.Panic("ERROR: Address is not valid")
    }
    bc := NewBlockchain(nodeID)
    UTXOSet := UTXOSet{bc}
    defer bc.db.Close()
    balance := 0
    pubKeyHash := Base58Decode([]byte(address))
    pubKeyHash = pubKeyHash[1 : len(pubKeyHash)-4]
    UTXOs := UTXOSet.FindUTXO(pubKeyHash)
    for _, out := range UTXOs {
        balance += out.Value
    }
    fmt.Printf("Balance of '%s': %d\n", address, balance)
}
type Blockchain struct {
    tip []byte
    Db  *bolt.DB
}
type UTXOSet struct {
    Blockchain *Blockchain
}

第一步ValidateAddress(address)检测地址的有效性,详细代码解释见我的博客
第二步从数据库中获取区块链实例,我们将区块链存储在数据库中,如果你没有使用数据库存储,可以直接获取区块链实例,然后创建一个utxo集合

func NewBlockchain(nodeID string) *Blockchain {
    dbFile := fmt.Sprintf(dbFile, nodeID)
    if dbExists(dbFile) == false {
        fmt.Println("No existing blockchain found. Create one first.")
        os.Exit(1)
    }
    var tip []byte
    db, err := bolt.Open(dbFile, 0600, nil)
    if err != nil {
        log.Panic(err)
    }
    err = db.Update(func(tx *bolt.Tx) error {
        b := tx.Bucket([]byte(blocksBucket))
        tip = b.Get([]byte("l"))
        return nil
    })
    if err != nil {
        log.Panic(err)
    }
    bc := Blockchain{tip, db}
    return &bc
}

第三步将地址变为公钥的hash
这里写图片描述
该图片是由公钥变化为地址的示意图,从而解释代码意图

    pubKeyHash := Base58Decode([]byte(address))    //解码
    pubKeyHash = pubKeyHash[1 : len(pubKeyHash)-4]    //去掉版本号和校验码

第四步是找到所有的UTXO

func (u UTXOSet) FindUTXO(pubKeyHash []byte) []TXOutput {
    var UTXOs []TXOutput
    db := u.Blockchain.db
    err := db.View(func(tx *bolt.Tx) error {
        b := tx.Bucket([]byte(utxoBucket))
        c := b.Cursor()
        for k, v := c.First(); k != nil; k, v = c.Next() {
            outs := DeserializeOutputs(v)
            for _, out := range outs.Outputs {
                if out.IsLockedWithKey(pubKeyHash) {   //如果公钥hash能够解锁UTXO集合中的交易输出,则该交易内部的值属于该地址
                    UTXOs = append(UTXOs, out)   //添加到UTXOS中
                }
            }
        }
        return nil
    })
    if err != nil {
        log.Panic(err)
    }
    return UTXOs
}
func (out *TXOutput) IsLockedWithKey(pubKeyHash []byte) bool {
    return bytes.Compare(out.PubKeyHash, pubKeyHash) == 0
}

最后将输出后的UTXOs进行遍历,将余额进行累加,就能够找到余额

参考

https://jeiwan.cc/

猜你喜欢

转载自blog.csdn.net/m0_37719047/article/details/82016913