七. 查询余额

其实这个章节的一些知识点在转账交易那一章节均有所涉及,所以,查询余额这个功能相对而言比较简单,只要熟悉了UTXO模型,加上对交易流程的了解之后,对查询余额基本上已经有了思路。

1.命令行代码

func (cli *CLI) GetBalance(address string) { bc := GetBlockChainObject() if bc == nil { fmt.Println("没有BlockChain,无法查询。。") os.Exit(1) } defer bc.DB.Close() utxoSet :=&UTXOSet{bc} total:=utxoSet.GetBalance(address) fmt.Printf("%s,余额是:%d\n", address, total)}获取区块链对象获取utxoSet对象通过utxoSet的GetBalance方法获得对应的余额2. 查询余额代码

GetBalance

func (utxoSet *UTXOSet) GetBalance(address string) int64 { utxos := utxoSet.FindUnspentUTXOsByAddress(address) var total int64 for _, utxo := range utxos { total += utxo.Output.Value } return total}通过FindUnspentUTXOsByAddress获得utxo的数组对象utxos通过对utxos进行遍历得到utxo对象将utxo对象的Output的Value属性值进行累加得到余额3.通过地址获取未花费utxo数组

FindUnspentUTXOsByAddress

func (utxoSet *UTXOSet) FindUnspentUTXOsByAddress(address string) []*UTXO { var utxos []*UTXO err := utxoSet.BlockChian.DB.View(func(tx *bolt.Tx) error { b := tx.Bucket([]byte(utxosettable)) if b != nil { /* 获取表中的所有的数据 key,value key:TxID value:TxOuputs */ c := b.Cursor() for k, v := c.First(); k != nil; k, v = c.Next() { txOutputs := DeserializeTxOutputs(v) for _, utxo := range txOutputs.UTXOs { //txid, index,output if utxo.Output.UnlockWithAddress(address) { utxos = append(utxos, utxo) } } } } return nil }) if err != nil { log.Panic(err) } return utxos}4.代码测试4.1 获取所有地址

$ ./mybtc getaddresslists

返回结果

钱包地址列表为: 1DHPNHKfk9uUdog2f2xBvx9dq4NxpF5Q4Q 1HtJve4MwW4LVko3yjkj3UUvzXsuGHb1Yq4.2 查询余额

$ ./mybtc getbalance -address 1DHPNHKfk9uUdog2f2xBvx9dq4NxpF5Q4Q

返回结果

1DHPNHKfk9uUdog2f2xBvx9dq4NxpF5Q4Q,余额是:12

分析

1.创建创世区块,该地址获得10元2.第一笔转账,给地址1HtJve4MwW4LVko3yjkj3UUvzXsuGHb1Yq转账2元, 剩余8元,得到10元奖励,余额为18元3.第二笔转账,给地址1HtJve4MwW4LVko3yjkj3UUvzXsuGHb1Yq转账3元, 剩余15元,得到10元奖励,余额为25元4.第三笔转账,给地址1HtJve4MwW4LVko3yjkj3UUvzXsuGHb1Yq转账23元,剩余2元,得到10元奖励,余额为12元

10元奖励是代码中设定每个区块的CoinBase交易给转账用户的,实际比特币场景是给矿工的,这里是测试场景,请大家勿要混淆。

./mybtc getbalance -address 1HtJve4MwW4LVko3yjkj3UUvzXsuGHb1Yq

返回结果

1HtJve4MwW4LVko3yjkj3UUvzXsuGHb1Yq,余额是:28

分析

2 + 3 + 23 = 28元

到此,我们查询余额的功能基本完毕。