Skip to content

Commit

Permalink
Complete rpc gettxoutsetinfo
Browse files Browse the repository at this point in the history
  • Loading branch information
whitefen committed Oct 7, 2018
1 parent a0001aa commit 24e7aa8
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 14 deletions.
77 changes: 64 additions & 13 deletions logic/lchain/stat.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import (

"github.com/copernet/copernicus/conf"
"github.com/copernet/copernicus/log"
mchain "github.com/copernet/copernicus/model/chain"
"github.com/copernet/copernicus/model/chain"
"github.com/copernet/copernicus/model/outpoint"
"github.com/copernet/copernicus/model/utxo"
"github.com/copernet/copernicus/persist/db"
"github.com/copernet/copernicus/util"
Expand All @@ -25,6 +26,18 @@ type stat struct {
nTxOuts uint64
hashSerialized util.Hash
amount int64
bogoSize uint64
}

type UTXOStat struct {
Height int
BestBlock util.Hash
TxCount uint64
TxOutsCount uint64
HashSerialized util.Hash
Amount int64
BogoSize uint64
DiskSize uint64
}

func (s *stat) String() string {
Expand Down Expand Up @@ -60,41 +73,79 @@ func applyStats(stat *stat, hashbuf *bytes.Buffer, txid *util.Hash, outputs map[
if err := util.WriteVarLenInt(hashbuf, uint64(v.GetAmount())); err != nil {
return err
}
txOut := v.GetTxOut()
stat.nTxOuts++
stat.amount += int64(v.GetAmount())
stat.bogoSize += 32 /* txid */ + 4 /* vout index */ + 4 /* height + coinbase */ +
8 /* amount */ + 2 /* scriptPubKey len */ +
uint64(txOut.GetScriptPubKey().SerializeSize()) /* scriptPubKey */
}
err := util.WriteVarLenInt(hashbuf, uint64(0))
return err
}

func GetUTXOStats(cdb utxo.CoinsDB, stat *stat) error {
func GetUTXOStats(cdb utxo.CoinsDB) (*UTXOStat, error) {
stat := &stat{}
b := time.Now()
besthash, err := cdb.GetBestBlock()
if err != nil {
log.Debug("in GetUTXOStats, GetBestBlock(), failed=%v\n", err)
return err
return nil, err
}
stat.bestblock = *besthash
stat.height = int(mchain.GetInstance().FindBlockIndex(*besthash).Height)
stat.height = int(chain.GetInstance().FindBlockIndex(*besthash).Height)

//hashbuf := bytes.NewBuffer(nil)
//hashbuf.Write(stat.bestblock[:])
h := sha256.New()
h.Write(stat.bestblock[:])

iter := cdb.GetDBW().Iterator(nil)
defer iter.Close()
iter.Seek([]byte{db.DbCoin})

var prevHash util.Hash
outputs := make(map[uint32]*utxo.Coin)
for ; iter.Valid(); iter.Next() {
//hashbuf.Write(iter.GetKey())
//hashbuf.Write(iter.GetVal())
h.Write(iter.GetKey())
h.Write(iter.GetVal())
outPoint := &outpoint.OutPoint{}
if err = outPoint.Unserialize(bytes.NewBuffer(iter.GetKey())); err != nil {
return nil, err
}
coin := utxo.NewEmptyCoin()
if err = coin.Unserialize(bytes.NewBuffer(iter.GetVal())); err != nil {
return nil, err
}
if outPoint.Hash != prevHash && len(outputs) > 0 {
hashBuf := bytes.NewBuffer(nil)
if err = applyStats(stat, hashBuf, &prevHash, outputs); err != nil {
return nil, err
}
h.Write(hashBuf.Bytes())
outputs = make(map[uint32]*utxo.Coin)
}
prevHash = outPoint.Hash
outputs[outPoint.Index] = coin
}
if len(outputs) > 0 {
hashBuf := bytes.NewBuffer(nil)
if err = applyStats(stat, hashBuf, &prevHash, outputs); err != nil {
return nil, err
}
h.Write(hashBuf.Bytes())
}
//stat.hashSerialized = util.Sha256Hash(hashbuf.Bytes())
copy(stat.hashSerialized[:], h.Sum(nil))
fmt.Printf("iter utxo db time: %v\n", time.Since(b))
return nil

utxoStat := &UTXOStat{
Height: stat.height,
BestBlock: stat.bestblock,
TxCount: stat.nTx,
TxOutsCount: stat.nTxOuts,
HashSerialized: stat.hashSerialized,
Amount: stat.amount,
BogoSize: stat.bogoSize,
DiskSize: cdb.EstimateSize(),
}

log.Info("GetUTXOStats iter utxo db time: %s", time.Since(b).String())
return utxoStat, nil
}

type utxoTaskArg struct {
Expand Down
12 changes: 12 additions & 0 deletions rpc/btcjson/results.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,18 @@ type GetTxOutResult struct {
Coinbase bool `json:"coinbase"`
}

// GetTxOutSetInfoResult models the data from the gettxoutsetinfo command.
type GetTxOutSetInfoResult struct {
Height int `json:"height"`
BestBlock string `json:"bestblock"`
Transactions uint64 `json:"transactions"`
TxOuts uint64 `json:"txouts"`
BogoSize uint64 `json:"bogosize"`
HashSerialized string `json:"hash_serialized"`
DiskSize uint64 `json:"disk_size"`
TotalAmount float64 `json:"total_amount"`
}

// GetNetTotalsResult models the data returned from the getnettotals command.
type GetNetTotalsResult struct {
TotalBytesRecv uint64 `json:"totalbytesrecv"`
Expand Down
23 changes: 22 additions & 1 deletion rpc/rpcblockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,28 @@ func handleGetTxOut(s *Server, cmd interface{}, closeChan <-chan struct{}) (inte
}

func handleGetTxoutSetInfo(s *Server, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
return nil, nil
// Write the chain state to disk, if necessary.
if err := disk.FlushStateToDisk(disk.FlushStateAlways, 0); err != nil {
return nil, err
}

cdb := utxo.GetUtxoCacheInstance().(*utxo.CoinsLruCache).GetCoinsDB()
stat, err := lchain.GetUTXOStats(cdb)
if err != nil {
return nil, err
}

reply := &btcjson.GetTxOutSetInfoResult{
Height: stat.Height,
BestBlock: stat.BestBlock.String(),
Transactions: stat.TxCount,
TxOuts: stat.TxOutsCount,
BogoSize: stat.BogoSize,
HashSerialized: stat.HashSerialized.String(),
DiskSize: stat.DiskSize,
TotalAmount: valueFromAmount(stat.Amount),
}
return reply, nil
}

func getPrunMode() (bool, error) {
Expand Down

0 comments on commit 24e7aa8

Please sign in to comment.