[Ready] - RPC & UtxoIndex: keep track of, query and test circulating supply. (#2070)

* start

* pass tests, (cannot get before put!) and clean up.

* add rpc call.

* create and pass tests, fix bugs.  fully implement rpc

* As always fmt

* remover old test

* clean up proto comment

* put the logger back in place.

* revert back to 10 sec limit.

* migration, change utxoChanged removal to whole utxoEntryPair, add methods to update circulating supply, intialize circulating supply from reset.

* Update utxoindex.go

* ad

* rename to max, change comment

* one more total to max

Co-authored-by: Ori Newman <orinewman1@gmail.com>
This commit is contained in:
D-Stacks 2022-06-05 15:42:08 +02:00 committed by GitHub
parent fa7ea121ff
commit 3908f274ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 617 additions and 70 deletions

View File

@ -161,6 +161,8 @@ const (
CmdNewBlockTemplateNotificationMessage
CmdGetMempoolEntriesByAddressesRequestMessage
CmdGetMempoolEntriesByAddressesResponseMessage
CmdGetCoinSupplyRequestMessage
CmdGetCoinSupplyResponseMessage
)
// ProtocolMessageCommandToString maps all MessageCommands to their string representation
@ -294,8 +296,10 @@ var RPCMessageCommandToString = map[MessageCommand]string{
CmdNotifyNewBlockTemplateRequestMessage: "NotifyNewBlockTemplateRequest",
CmdNotifyNewBlockTemplateResponseMessage: "NotifyNewBlockTemplateResponse",
CmdNewBlockTemplateNotificationMessage: "NewBlockTemplateNotification",
CmdGetMempoolEntriesByAddressesRequestMessage: "CmdGetMempoolEntriesByAddressesRequest",
CmdGetMempoolEntriesByAddressesResponseMessage: "CmdGetMempoolEntriesByAddressesResponse",
CmdGetMempoolEntriesByAddressesRequestMessage: "GetMempoolEntriesByAddressesRequest",
CmdGetMempoolEntriesByAddressesResponseMessage: "GetMempoolEntriesByAddressesResponse",
CmdGetCoinSupplyRequestMessage: "GetCoinSupplyRequest",
CmdGetCoinSupplyResponseMessage: "GetCoinSupplyResponse",
}
// Message is an interface that describes a kaspa message. A type that

View File

@ -0,0 +1,40 @@
package appmessage
// GetCoinSupplyRequestMessage is an appmessage corresponding to
// its respective RPC message
type GetCoinSupplyRequestMessage struct {
baseMessage
}
// Command returns the protocol command string for the message
func (msg *GetCoinSupplyRequestMessage) Command() MessageCommand {
return CmdGetCoinSupplyRequestMessage
}
// NewGetCoinSupplyRequestMessage returns a instance of the message
func NewGetCoinSupplyRequestMessage() *GetCoinSupplyRequestMessage {
return &GetCoinSupplyRequestMessage{}
}
// GetCoinSupplyResponseMessage is an appmessage corresponding to
// its respective RPC message
type GetCoinSupplyResponseMessage struct {
baseMessage
MaxSompi uint64
CirculatingSompi uint64
Error *RPCError
}
// Command returns the protocol command string for the message
func (msg *GetCoinSupplyResponseMessage) Command() MessageCommand {
return CmdGetCoinSupplyResponseMessage
}
// NewGetCoinSupplyResponseMessage returns a instance of the message
func NewGetCoinSupplyResponseMessage(maxSompi uint64, circulatingSompi uint64) *GetCoinSupplyResponseMessage {
return &GetCoinSupplyResponseMessage{
MaxSompi: maxSompi,
CirculatingSompi: circulatingSompi,
}
}

View File

@ -49,6 +49,7 @@ var handlers = map[appmessage.MessageCommand]handler{
appmessage.CmdEstimateNetworkHashesPerSecondRequestMessage: rpchandlers.HandleEstimateNetworkHashesPerSecond,
appmessage.CmdNotifyVirtualDaaScoreChangedRequestMessage: rpchandlers.HandleNotifyVirtualDaaScoreChanged,
appmessage.CmdNotifyNewBlockTemplateRequestMessage: rpchandlers.HandleNotifyNewBlockTemplate,
appmessage.CmdGetCoinSupplyRequestMessage: rpchandlers.HandleGetCoinSupply,
appmessage.CmdGetMempoolEntriesByAddressesRequestMessage: rpchandlers.HandleGetMempoolEntriesByAddresses,
}

View File

@ -378,9 +378,9 @@ func (nl *NotificationListener) convertUTXOChangesToUTXOsChangedNotification(
notification.Added = append(notification.Added, utxosByAddressesEntries...)
}
}
for scriptPublicKeyString, removedOutpoints := range utxoChanges.Removed {
for scriptPublicKeyString, removedPairs := range utxoChanges.Removed {
if listenerAddress, ok := nl.propagateUTXOsChangedNotificationAddresses[scriptPublicKeyString]; ok {
utxosByAddressesEntries := convertUTXOOutpointsToUTXOsByAddressesEntries(listenerAddress.Address, removedOutpoints)
utxosByAddressesEntries := ConvertUTXOOutpointEntryPairsToUTXOsByAddressesEntries(listenerAddress.Address, removedPairs)
notification.Removed = append(notification.Removed, utxosByAddressesEntries...)
}
}
@ -391,8 +391,8 @@ func (nl *NotificationListener) convertUTXOChangesToUTXOsChangedNotification(
utxosByAddressesEntries := ConvertUTXOOutpointEntryPairsToUTXOsByAddressesEntries(listenerAddress.Address, addedPairs)
notification.Added = append(notification.Added, utxosByAddressesEntries...)
}
if removedOutpoints, ok := utxoChanges.Removed[listenerScriptPublicKeyString]; ok {
utxosByAddressesEntries := convertUTXOOutpointsToUTXOsByAddressesEntries(listenerAddress.Address, removedOutpoints)
if removedPairs, ok := utxoChanges.Removed[listenerScriptPublicKeyString]; ok {
utxosByAddressesEntries := ConvertUTXOOutpointEntryPairsToUTXOsByAddressesEntries(listenerAddress.Address, removedPairs)
notification.Removed = append(notification.Removed, utxosByAddressesEntries...)
}
}
@ -406,13 +406,13 @@ func (nl *NotificationListener) convertUTXOChangesToUTXOsChangedNotification(
utxosByAddressesEntries := ConvertUTXOOutpointEntryPairsToUTXOsByAddressesEntries(addressString, addedPairs)
notification.Added = append(notification.Added, utxosByAddressesEntries...)
}
for scriptPublicKeyString, removedOutpoints := range utxoChanges.Removed {
for scriptPublicKeyString, removedPAirs := range utxoChanges.Removed {
addressString, err := nl.scriptPubKeyStringToAddressString(scriptPublicKeyString)
if err != nil {
return nil, err
}
utxosByAddressesEntries := convertUTXOOutpointsToUTXOsByAddressesEntries(addressString, removedOutpoints)
utxosByAddressesEntries := ConvertUTXOOutpointEntryPairsToUTXOsByAddressesEntries(addressString, removedPAirs)
notification.Removed = append(notification.Removed, utxosByAddressesEntries...)
}
}

View File

@ -0,0 +1,29 @@
package rpchandlers
import (
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
)
// HandleGetCoinSupply handles the respectively named RPC command
func HandleGetCoinSupply(context *rpccontext.Context, _ *router.Router, _ appmessage.Message) (appmessage.Message, error) {
if !context.Config.UTXOIndex {
errorMessage := &appmessage.GetCoinSupplyResponseMessage{}
errorMessage.Error = appmessage.RPCErrorf("Method unavailable when kaspad is run without --utxoindex")
return errorMessage, nil
}
circulatingSompiSupply, err := context.UTXOIndex.GetCirculatingSompiSupply()
if err != nil {
return nil, err
}
response := appmessage.NewGetCoinSupplyResponseMessage(
constants.MaxSompi,
circulatingSompiSupply,
)
return response, nil
}

View File

@ -37,6 +37,7 @@ var commandTypes = []reflect.Type{
reflect.TypeOf(protowire.KaspadMessage_GetUtxosByAddressesRequest{}),
reflect.TypeOf(protowire.KaspadMessage_GetBalanceByAddressRequest{}),
reflect.TypeOf(protowire.KaspadMessage_GetCoinSupplyRequest{}),
reflect.TypeOf(protowire.KaspadMessage_BanRequest{}),
reflect.TypeOf(protowire.KaspadMessage_UnbanRequest{}),

View File

@ -5,7 +5,7 @@ package externalapi
// score of the block that accepts the tx, its public key script, and how
// much it pays.
type UTXOEntry interface {
Amount() uint64
Amount() uint64 // Utxo amount in Sompis
ScriptPublicKey() *ScriptPublicKey // The public key script for the output.
BlockDAAScore() uint64 // Daa score of the block accepting the tx.
IsCoinbase() bool

View File

@ -20,7 +20,7 @@ type UTXOOutpoints map[externalapi.DomainOutpoint]interface{}
// a successful update
type UTXOChanges struct {
Added map[ScriptPublicKeyString]UTXOOutpointEntryPairs
Removed map[ScriptPublicKeyString]UTXOOutpoints
Removed map[ScriptPublicKeyString]UTXOOutpointEntryPairs
}
// ConvertScriptPublicKeyToString converts the given scriptPublicKey to a string

View File

@ -2,6 +2,8 @@ package utxoindex
import (
"encoding/binary"
"github.com/kaspanet/kaspad/domain/consensus/database/binaryserialization"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/infrastructure/db/database"
"github.com/kaspanet/kaspad/infrastructure/logger"
@ -10,11 +12,13 @@ import (
var utxoIndexBucket = database.MakeBucket([]byte("utxo-index"))
var virtualParentsKey = database.MakeBucket([]byte("")).Key([]byte("utxo-index-virtual-parents"))
var circulatingSupplyKey = database.MakeBucket([]byte("")).Key([]byte("utxo-index-circulating-supply"))
type utxoIndexStore struct {
database database.Database
toAdd map[ScriptPublicKeyString]UTXOOutpointEntryPairs
toRemove map[ScriptPublicKeyString]UTXOOutpoints
database database.Database
toAdd map[ScriptPublicKeyString]UTXOOutpointEntryPairs
toRemove map[ScriptPublicKeyString]UTXOOutpointEntryPairs
virtualParents []*externalapi.DomainHash
}
@ -22,7 +26,7 @@ func newUTXOIndexStore(database database.Database) *utxoIndexStore {
return &utxoIndexStore{
database: database,
toAdd: make(map[ScriptPublicKeyString]UTXOOutpointEntryPairs),
toRemove: make(map[ScriptPublicKeyString]UTXOOutpoints),
toRemove: make(map[ScriptPublicKeyString]UTXOOutpointEntryPairs),
}
}
@ -61,7 +65,7 @@ func (uis *utxoIndexStore) add(scriptPublicKey *externalapi.ScriptPublicKey, out
return nil
}
func (uis *utxoIndexStore) remove(scriptPublicKey *externalapi.ScriptPublicKey, outpoint *externalapi.DomainOutpoint) error {
func (uis *utxoIndexStore) remove(scriptPublicKey *externalapi.ScriptPublicKey, outpoint *externalapi.DomainOutpoint, utxoEntry externalapi.UTXOEntry) error {
key := ConvertScriptPublicKeyToString(scriptPublicKey)
log.Tracef("Removing outpoint %s:%d from scriptPublicKey %s",
outpoint.TransactionID, outpoint.Index, key)
@ -76,19 +80,19 @@ func (uis *utxoIndexStore) remove(scriptPublicKey *externalapi.ScriptPublicKey,
}
}
// Create a UTXOOutpoints entry in `toRemove` if it doesn't exist
// Create a UTXOOutpointEntryPair in `toRemove` if it doesn't exist
if _, ok := uis.toRemove[key]; !ok {
log.Tracef("Creating key %s in `toRemove`", key)
uis.toRemove[key] = make(UTXOOutpoints)
uis.toRemove[key] = make(UTXOOutpointEntryPairs)
}
// Return an error if the outpoint already exists in `toRemove`
toRemoveOutpointsOfKey := uis.toRemove[key]
if _, ok := toRemoveOutpointsOfKey[*outpoint]; ok {
toRemovePairsOfKey := uis.toRemove[key]
if _, ok := toRemovePairsOfKey[*outpoint]; ok {
return errors.Errorf("cannot remove outpoint %s because it's being removed already", outpoint)
}
toRemoveOutpointsOfKey[*outpoint] = struct{}{}
toRemovePairsOfKey[*outpoint] = utxoEntry
log.Tracef("Removed outpoint %s:%d from scriptPublicKey %s",
outpoint.TransactionID, outpoint.Index, key)
@ -101,7 +105,7 @@ func (uis *utxoIndexStore) updateVirtualParents(virtualParents []*externalapi.Do
func (uis *utxoIndexStore) discard() {
uis.toAdd = make(map[ScriptPublicKeyString]UTXOOutpointEntryPairs)
uis.toRemove = make(map[ScriptPublicKeyString]UTXOOutpoints)
uis.toRemove = make(map[ScriptPublicKeyString]UTXOOutpointEntryPairs)
uis.virtualParents = nil
}
@ -115,10 +119,12 @@ func (uis *utxoIndexStore) commit() error {
}
defer dbTransaction.RollbackUnlessClosed()
for scriptPublicKeyString, toRemoveOutpointsOfKey := range uis.toRemove {
toRemoveSompiSupply := uint64(0)
for scriptPublicKeyString, toRemoveUTXOOutpointEntryPairs := range uis.toRemove {
scriptPublicKey := ConvertStringToScriptPublicKey(scriptPublicKeyString)
bucket := uis.bucketForScriptPublicKey(scriptPublicKey)
for outpointToRemove := range toRemoveOutpointsOfKey {
for outpointToRemove, utxoEntryToRemove := range toRemoveUTXOOutpointEntryPairs {
key, err := uis.convertOutpointToKey(bucket, &outpointToRemove)
if err != nil {
return err
@ -127,9 +133,12 @@ func (uis *utxoIndexStore) commit() error {
if err != nil {
return err
}
toRemoveSompiSupply = toRemoveSompiSupply + utxoEntryToRemove.Amount()
}
}
toAddSompiSupply := uint64(0)
for scriptPublicKeyString, toAddUTXOOutpointEntryPairs := range uis.toAdd {
scriptPublicKey := ConvertStringToScriptPublicKey(scriptPublicKeyString)
bucket := uis.bucketForScriptPublicKey(scriptPublicKey)
@ -146,6 +155,7 @@ func (uis *utxoIndexStore) commit() error {
if err != nil {
return err
}
toAddSompiSupply = toAddSompiSupply + utxoEntryToAdd.Amount()
}
}
@ -155,6 +165,11 @@ func (uis *utxoIndexStore) commit() error {
return err
}
err = uis.updateCirculatingSompiSupply(dbTransaction, toAddSompiSupply, toRemoveSompiSupply)
if err != nil {
return err
}
err = dbTransaction.Commit()
if err != nil {
return err
@ -165,20 +180,29 @@ func (uis *utxoIndexStore) commit() error {
}
func (uis *utxoIndexStore) addAndCommitOutpointsWithoutTransaction(utxoPairs []*externalapi.OutpointAndUTXOEntryPair) error {
toAddSompiSupply := uint64(0)
for _, pair := range utxoPairs {
bucket := uis.bucketForScriptPublicKey(pair.UTXOEntry.ScriptPublicKey())
key, err := uis.convertOutpointToKey(bucket, pair.Outpoint)
if err != nil {
return err
}
serializedUTXOEntry, err := serializeUTXOEntry(pair.UTXOEntry)
if err != nil {
return err
}
err = uis.database.Put(key, serializedUTXOEntry)
if err != nil {
return err
}
toAddSompiSupply = toAddSompiSupply + pair.UTXOEntry.Amount()
}
err := uis.updateCirculatingSompiSupplyWithoutTransaction(toAddSompiSupply, uint64(0))
if err != nil {
return err
}
return nil
@ -211,7 +235,7 @@ func (uis *utxoIndexStore) convertKeyToOutpoint(key *database.Key) (*externalapi
func (uis *utxoIndexStore) stagedData() (
toAdd map[ScriptPublicKeyString]UTXOOutpointEntryPairs,
toRemove map[ScriptPublicKeyString]UTXOOutpoints,
toRemove map[ScriptPublicKeyString]UTXOOutpointEntryPairs,
virtualParents []*externalapi.DomainHash) {
toAddClone := make(map[ScriptPublicKeyString]UTXOOutpointEntryPairs, len(uis.toAdd))
@ -223,13 +247,13 @@ func (uis *utxoIndexStore) stagedData() (
toAddClone[scriptPublicKeyString] = toAddUTXOOutpointEntryPairsClone
}
toRemoveClone := make(map[ScriptPublicKeyString]UTXOOutpoints, len(uis.toRemove))
for scriptPublicKeyString, toRemoveOutpoints := range uis.toRemove {
toRemoveOutpointsClone := make(UTXOOutpoints, len(toRemoveOutpoints))
for outpoint := range toRemoveOutpoints {
toRemoveOutpointsClone[outpoint] = struct{}{}
toRemoveClone := make(map[ScriptPublicKeyString]UTXOOutpointEntryPairs, len(uis.toRemove))
for scriptPublicKeyString, toRemoveUTXOOutpointEntryPairs := range uis.toRemove {
toRemoveUTXOOutpointEntryPairsClone := make(UTXOOutpointEntryPairs, len(toRemoveUTXOOutpointEntryPairs))
for outpoint, utxoEntry := range toRemoveUTXOOutpointEntryPairs {
toRemoveUTXOOutpointEntryPairsClone[outpoint] = utxoEntry
}
toRemoveClone[scriptPublicKeyString] = toRemoveOutpointsClone
toRemoveClone[scriptPublicKeyString] = toRemoveUTXOOutpointEntryPairsClone
}
return toAddClone, toRemoveClone, uis.virtualParents
@ -294,6 +318,11 @@ func (uis *utxoIndexStore) deleteAll() error {
return err
}
err = uis.database.Delete(circulatingSupplyKey)
if err != nil {
return err
}
cursor, err := uis.database.Cursor(utxoIndexBucket)
if err != nil {
return err
@ -313,3 +342,92 @@ func (uis *utxoIndexStore) deleteAll() error {
return nil
}
func (uis *utxoIndexStore) initializeCirculatingSompiSupply() error {
cursor, err := uis.database.Cursor(utxoIndexBucket)
if err != nil {
return err
}
defer cursor.Close()
circulatingSompiSupplyInDatabase := uint64(0)
for cursor.Next() {
serializedUTXOEntry, err := cursor.Value()
if err != nil {
return err
}
utxoEntry, err := deserializeUTXOEntry(serializedUTXOEntry)
if err != nil {
return err
}
circulatingSompiSupplyInDatabase = circulatingSompiSupplyInDatabase + utxoEntry.Amount()
}
err = uis.database.Put(
circulatingSupplyKey,
binaryserialization.SerializeUint64(circulatingSompiSupplyInDatabase),
)
if err != nil {
return err
}
return nil
}
func (uis *utxoIndexStore) updateCirculatingSompiSupply(dbTransaction database.Transaction, toAddSompiSupply uint64, toRemoveSompiSupply uint64) error {
if toAddSompiSupply != toRemoveSompiSupply {
circulatingSupplyBytes, err := dbTransaction.Get(circulatingSupplyKey)
if err != nil {
return err
}
circulatingSupply, err := binaryserialization.DeserializeUint64(circulatingSupplyBytes)
if err != nil {
return err
}
err = dbTransaction.Put(
circulatingSupplyKey,
binaryserialization.SerializeUint64(circulatingSupply+toAddSompiSupply-toRemoveSompiSupply),
)
if err != nil {
return err
}
}
return nil
}
func (uis *utxoIndexStore) updateCirculatingSompiSupplyWithoutTransaction(toAddSompiSupply uint64, toRemoveSompiSupply uint64) error {
if toAddSompiSupply != toRemoveSompiSupply {
circulatingSupplyBytes, err := uis.database.Get(circulatingSupplyKey)
if err != nil {
return err
}
circulatingSupply, err := binaryserialization.DeserializeUint64(circulatingSupplyBytes)
if err != nil {
return err
}
err = uis.database.Put(
circulatingSupplyKey,
binaryserialization.SerializeUint64(circulatingSupply+toAddSompiSupply-toRemoveSompiSupply),
)
if err != nil {
return err
}
}
return nil
}
func (uis *utxoIndexStore) getCirculatingSompiSupply() (uint64, error) {
if uis.isAnythingStaged() {
return 0, errors.Errorf("cannot get circulatingSupply while staging isn't empty")
}
circulatingSupply, err := uis.database.Get(circulatingSupplyKey)
if err != nil {
return 0, err
}
return binaryserialization.DeserializeUint64(circulatingSupply)
}

View File

@ -25,14 +25,20 @@ func New(domain domain.Domain, database database.Database) (*UTXOIndex, error) {
domain: domain,
store: newUTXOIndexStore(database),
}
isSynced, err := utxoIndex.isSynced()
if err != nil {
return nil, err
}
if !isSynced {
err = utxoIndex.Reset()
///Has check is for migration to circulating supply, can be removed eventually.
hasCirculatingSupplyKey, err := utxoIndex.store.database.Has(circulatingSupplyKey)
if err != nil {
return nil, err
}
if !isSynced || !hasCirculatingSupplyKey {
err := utxoIndex.Reset()
if err != nil {
return nil, err
}
@ -56,6 +62,11 @@ func (ui *UTXOIndex) Reset() error {
return err
}
err = ui.store.initializeCirculatingSompiSupply() //At this point the database is empty, so the sole purpose of this call is to initialize the circulating supply key
if err != nil {
return err
}
var fromOutpoint *externalapi.DomainOutpoint
for {
const step = 1000
@ -161,7 +172,7 @@ func (ui *UTXOIndex) removeUTXOs(toRemove externalapi.UTXOCollection) error {
}
log.Tracef("Removing outpoint %s from UTXO index", outpoint)
err = ui.store.remove(entry.ScriptPublicKey(), outpoint)
err = ui.store.remove(entry.ScriptPublicKey(), outpoint, entry)
if err != nil {
return err
}
@ -179,3 +190,12 @@ func (ui *UTXOIndex) UTXOs(scriptPublicKey *externalapi.ScriptPublicKey) (UTXOOu
return ui.store.getUTXOOutpointEntryPairs(scriptPublicKey)
}
// GetCirculatingSompiSupply returns the current circulating supply of sompis in the network
func (ui *UTXOIndex) GetCirculatingSompiSupply() (uint64, error) {
ui.mutex.Lock()
defer ui.mutex.Unlock()
return ui.store.getCirculatingSompiSupply()
}

View File

@ -154,6 +154,8 @@ type KaspadMessage struct {
// *KaspadMessage_NewBlockTemplateNotification
// *KaspadMessage_GetMempoolEntriesByAddressesRequest
// *KaspadMessage_GetMempoolEntriesByAddressesResponse
// *KaspadMessage_GetCoinSupplyRequest
// *KaspadMessage_GetCoinSupplyResponse
Payload isKaspadMessage_Payload `protobuf_oneof:"payload"`
}
@ -1092,6 +1094,20 @@ func (x *KaspadMessage) GetGetMempoolEntriesByAddressesResponse() *GetMempoolEnt
return nil
}
func (x *KaspadMessage) GetGetCoinSupplyRequest() *GetCoinSupplyRequestMessage {
if x, ok := x.GetPayload().(*KaspadMessage_GetCoinSupplyRequest); ok {
return x.GetCoinSupplyRequest
}
return nil
}
func (x *KaspadMessage) GetGetCoinSupplyResponse() *GetCoinSupplyResponseMessage {
if x, ok := x.GetPayload().(*KaspadMessage_GetCoinSupplyResponse); ok {
return x.GetCoinSupplyResponse
}
return nil
}
type isKaspadMessage_Payload interface {
isKaspadMessage_Payload()
}
@ -1608,6 +1624,14 @@ type KaspadMessage_GetMempoolEntriesByAddressesResponse struct {
GetMempoolEntriesByAddressesResponse *GetMempoolEntriesByAddressesResponseMessage `protobuf:"bytes,1085,opt,name=getMempoolEntriesByAddressesResponse,proto3,oneof"`
}
type KaspadMessage_GetCoinSupplyRequest struct {
GetCoinSupplyRequest *GetCoinSupplyRequestMessage `protobuf:"bytes,1086,opt,name=getCoinSupplyRequest,proto3,oneof"`
}
type KaspadMessage_GetCoinSupplyResponse struct {
GetCoinSupplyResponse *GetCoinSupplyResponseMessage `protobuf:"bytes,1087,opt,name=getCoinSupplyResponse,proto3,oneof"`
}
func (*KaspadMessage_Addresses) isKaspadMessage_Payload() {}
func (*KaspadMessage_Block) isKaspadMessage_Payload() {}
@ -1864,13 +1888,17 @@ func (*KaspadMessage_GetMempoolEntriesByAddressesRequest) isKaspadMessage_Payloa
func (*KaspadMessage_GetMempoolEntriesByAddressesResponse) isKaspadMessage_Payload() {}
func (*KaspadMessage_GetCoinSupplyRequest) isKaspadMessage_Payload() {}
func (*KaspadMessage_GetCoinSupplyResponse) isKaspadMessage_Payload() {}
var File_messages_proto protoreflect.FileDescriptor
var file_messages_proto_rawDesc = []byte{
0x0a, 0x0e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x12, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x1a, 0x09, 0x70, 0x32, 0x70,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x09, 0x72, 0x70, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x22, 0xfe, 0x6b, 0x0a, 0x0d, 0x4b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x4d, 0x65, 0x73, 0x73,
0x6f, 0x22, 0xbf, 0x6d, 0x0a, 0x0d, 0x4b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x4d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x12, 0x3b, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69,
0x72, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x4d, 0x65, 0x73, 0x73,
@ -2733,21 +2761,33 @@ var file_messages_proto_rawDesc = []byte{
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48,
0x00, 0x52, 0x24, 0x67, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x45, 0x6e, 0x74,
0x72, 0x69, 0x65, 0x73, 0x42, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f,
0x61, 0x64, 0x32, 0x50, 0x0a, 0x03, 0x50, 0x32, 0x50, 0x12, 0x49, 0x0a, 0x0d, 0x4d, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x4d, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x1a, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65,
0x2e, 0x4b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00,
0x28, 0x01, 0x30, 0x01, 0x32, 0x50, 0x0a, 0x03, 0x52, 0x50, 0x43, 0x12, 0x49, 0x0a, 0x0d, 0x4d,
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x4d,
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69,
0x72, 0x65, 0x2e, 0x4b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x26, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x6b, 0x61,
0x73, 0x70, 0x61, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5d, 0x0a, 0x14, 0x67, 0x65, 0x74, 0x43, 0x6f,
0x69, 0x6e, 0x53, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18,
0xbe, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69,
0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x75, 0x70, 0x70, 0x6c, 0x79,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48, 0x00,
0x52, 0x14, 0x67, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x60, 0x0a, 0x15, 0x67, 0x65, 0x74, 0x43, 0x6f, 0x69,
0x6e, 0x53, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18,
0xbf, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69,
0x72, 0x65, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x75, 0x70, 0x70, 0x6c, 0x79,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x48,
0x00, 0x52, 0x15, 0x67, 0x65, 0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x75, 0x70, 0x70, 0x6c, 0x79,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c,
0x6f, 0x61, 0x64, 0x32, 0x50, 0x0a, 0x03, 0x50, 0x32, 0x50, 0x12, 0x49, 0x0a, 0x0d, 0x4d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x4d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72,
0x65, 0x2e, 0x4b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22,
0x00, 0x28, 0x01, 0x30, 0x01, 0x32, 0x50, 0x0a, 0x03, 0x52, 0x50, 0x43, 0x12, 0x49, 0x0a, 0x0d,
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x4b, 0x61, 0x73, 0x70, 0x61, 0x64,
0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77,
0x69, 0x72, 0x65, 0x2e, 0x4b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67,
0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x26, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x6b,
0x61, 0x73, 0x70, 0x61, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@ -2892,6 +2932,8 @@ var file_messages_proto_goTypes = []interface{}{
(*NewBlockTemplateNotificationMessage)(nil), // 125: protowire.NewBlockTemplateNotificationMessage
(*GetMempoolEntriesByAddressesRequestMessage)(nil), // 126: protowire.GetMempoolEntriesByAddressesRequestMessage
(*GetMempoolEntriesByAddressesResponseMessage)(nil), // 127: protowire.GetMempoolEntriesByAddressesResponseMessage
(*GetCoinSupplyRequestMessage)(nil), // 128: protowire.GetCoinSupplyRequestMessage
(*GetCoinSupplyResponseMessage)(nil), // 129: protowire.GetCoinSupplyResponseMessage
}
var file_messages_proto_depIdxs = []int32{
1, // 0: protowire.KaspadMessage.addresses:type_name -> protowire.AddressesMessage
@ -3022,15 +3064,17 @@ var file_messages_proto_depIdxs = []int32{
125, // 125: protowire.KaspadMessage.newBlockTemplateNotification:type_name -> protowire.NewBlockTemplateNotificationMessage
126, // 126: protowire.KaspadMessage.getMempoolEntriesByAddressesRequest:type_name -> protowire.GetMempoolEntriesByAddressesRequestMessage
127, // 127: protowire.KaspadMessage.getMempoolEntriesByAddressesResponse:type_name -> protowire.GetMempoolEntriesByAddressesResponseMessage
0, // 128: protowire.P2P.MessageStream:input_type -> protowire.KaspadMessage
0, // 129: protowire.RPC.MessageStream:input_type -> protowire.KaspadMessage
0, // 130: protowire.P2P.MessageStream:output_type -> protowire.KaspadMessage
0, // 131: protowire.RPC.MessageStream:output_type -> protowire.KaspadMessage
130, // [130:132] is the sub-list for method output_type
128, // [128:130] is the sub-list for method input_type
128, // [128:128] is the sub-list for extension type_name
128, // [128:128] is the sub-list for extension extendee
0, // [0:128] is the sub-list for field type_name
128, // 128: protowire.KaspadMessage.getCoinSupplyRequest:type_name -> protowire.GetCoinSupplyRequestMessage
129, // 129: protowire.KaspadMessage.getCoinSupplyResponse:type_name -> protowire.GetCoinSupplyResponseMessage
0, // 130: protowire.P2P.MessageStream:input_type -> protowire.KaspadMessage
0, // 131: protowire.RPC.MessageStream:input_type -> protowire.KaspadMessage
0, // 132: protowire.P2P.MessageStream:output_type -> protowire.KaspadMessage
0, // 133: protowire.RPC.MessageStream:output_type -> protowire.KaspadMessage
132, // [132:134] is the sub-list for method output_type
130, // [130:132] is the sub-list for method input_type
130, // [130:130] is the sub-list for extension type_name
130, // [130:130] is the sub-list for extension extendee
0, // [0:130] is the sub-list for field type_name
}
func init() { file_messages_proto_init() }
@ -3183,6 +3227,8 @@ func file_messages_proto_init() {
(*KaspadMessage_NewBlockTemplateNotification)(nil),
(*KaspadMessage_GetMempoolEntriesByAddressesRequest)(nil),
(*KaspadMessage_GetMempoolEntriesByAddressesResponse)(nil),
(*KaspadMessage_GetCoinSupplyRequest)(nil),
(*KaspadMessage_GetCoinSupplyResponse)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{

View File

@ -137,6 +137,8 @@ message KaspadMessage {
NewBlockTemplateNotificationMessage newBlockTemplateNotification = 1083;
GetMempoolEntriesByAddressesRequestMessage getMempoolEntriesByAddressesRequest = 1084;
GetMempoolEntriesByAddressesResponseMessage getMempoolEntriesByAddressesResponse = 1085;
GetCoinSupplyRequestMessage getCoinSupplyRequest = 1086;
GetCoinSupplyResponseMessage getCoinSupplyResponse= 1087;
}
}

View File

@ -110,6 +110,8 @@
- [MempoolEntryByAddress](#protowire.MempoolEntryByAddress)
- [GetMempoolEntriesByAddressesRequestMessage](#protowire.GetMempoolEntriesByAddressesRequestMessage)
- [GetMempoolEntriesByAddressesResponseMessage](#protowire.GetMempoolEntriesByAddressesResponseMessage)
- [GetCoinSupplyRequestMessage](#protowire.GetCoinSupplyRequestMessage)
- [GetCoinSupplyResponseMessage](#protowire.GetCoinSupplyResponseMessage)
- [SubmitBlockResponseMessage.RejectReason](#protowire.SubmitBlockResponseMessage.RejectReason)
@ -1817,6 +1819,33 @@ See NotifyNewBlockTemplateRequestMessage
<a name="protowire.GetCoinSupplyRequestMessage"></a>
### GetCoinSupplyRequestMessage
<a name="protowire.GetCoinSupplyResponseMessage"></a>
### GetCoinSupplyResponseMessage
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| maxSompi | [uint64](#uint64) | | note: this is a hard coded maxSupply, actual maxSupply is expected to deviate by upto -5%, but cannot be measured exactly. |
| circulatingSompi | [uint64](#uint64) | | |
| error | [RPCError](#protowire.RPCError) | | |

View File

@ -5953,6 +5953,107 @@ func (x *GetMempoolEntriesByAddressesResponseMessage) GetError() *RPCError {
return nil
}
type GetCoinSupplyRequestMessage struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *GetCoinSupplyRequestMessage) Reset() {
*x = GetCoinSupplyRequestMessage{}
if protoimpl.UnsafeEnabled {
mi := &file_rpc_proto_msgTypes[106]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetCoinSupplyRequestMessage) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetCoinSupplyRequestMessage) ProtoMessage() {}
func (x *GetCoinSupplyRequestMessage) ProtoReflect() protoreflect.Message {
mi := &file_rpc_proto_msgTypes[106]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetCoinSupplyRequestMessage.ProtoReflect.Descriptor instead.
func (*GetCoinSupplyRequestMessage) Descriptor() ([]byte, []int) {
return file_rpc_proto_rawDescGZIP(), []int{106}
}
type GetCoinSupplyResponseMessage struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
MaxSompi uint64 `protobuf:"varint,1,opt,name=maxSompi,proto3" json:"maxSompi,omitempty"` // note: this is a hard coded maxSupply, actual maxSupply is expected to deviate by upto -5%, but cannot be measured exactly.
CirculatingSompi uint64 `protobuf:"varint,2,opt,name=circulatingSompi,proto3" json:"circulatingSompi,omitempty"`
Error *RPCError `protobuf:"bytes,1000,opt,name=error,proto3" json:"error,omitempty"`
}
func (x *GetCoinSupplyResponseMessage) Reset() {
*x = GetCoinSupplyResponseMessage{}
if protoimpl.UnsafeEnabled {
mi := &file_rpc_proto_msgTypes[107]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GetCoinSupplyResponseMessage) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetCoinSupplyResponseMessage) ProtoMessage() {}
func (x *GetCoinSupplyResponseMessage) ProtoReflect() protoreflect.Message {
mi := &file_rpc_proto_msgTypes[107]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetCoinSupplyResponseMessage.ProtoReflect.Descriptor instead.
func (*GetCoinSupplyResponseMessage) Descriptor() ([]byte, []int) {
return file_rpc_proto_rawDescGZIP(), []int{107}
}
func (x *GetCoinSupplyResponseMessage) GetMaxSompi() uint64 {
if x != nil {
return x.MaxSompi
}
return 0
}
func (x *GetCoinSupplyResponseMessage) GetCirculatingSompi() uint64 {
if x != nil {
return x.CirculatingSompi
}
return 0
}
func (x *GetCoinSupplyResponseMessage) GetError() *RPCError {
if x != nil {
return x.Error
}
return nil
}
var File_rpc_proto protoreflect.FileDescriptor
var file_rpc_proto_rawDesc = []byte{
@ -6724,10 +6825,21 @@ var file_rpc_proto_rawDesc = []byte{
0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2a,
0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x72,
0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x42, 0x26, 0x5a, 0x24, 0x67, 0x69,
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x6e, 0x65,
0x74, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69,
0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x1d, 0x0a, 0x1b, 0x47, 0x65,
0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x92, 0x01, 0x0a, 0x1c, 0x47, 0x65,
0x74, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x75, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x61,
0x78, 0x53, 0x6f, 0x6d, 0x70, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61,
0x78, 0x53, 0x6f, 0x6d, 0x70, 0x69, 0x12, 0x2a, 0x0a, 0x10, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6c,
0x61, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x6f, 0x6d, 0x70, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
0x52, 0x10, 0x63, 0x69, 0x72, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x6f, 0x6d,
0x70, 0x69, 0x12, 0x2a, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0xe8, 0x07, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x2e, 0x52,
0x50, 0x43, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x42, 0x26,
0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x73,
0x70, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x64, 0x2f, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x77, 0x69, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@ -6743,7 +6855,7 @@ func file_rpc_proto_rawDescGZIP() []byte {
}
var file_rpc_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_rpc_proto_msgTypes = make([]protoimpl.MessageInfo, 106)
var file_rpc_proto_msgTypes = make([]protoimpl.MessageInfo, 108)
var file_rpc_proto_goTypes = []interface{}{
(SubmitBlockResponseMessage_RejectReason)(0), // 0: protowire.SubmitBlockResponseMessage.RejectReason
(*RPCError)(nil), // 1: protowire.RPCError
@ -6852,6 +6964,8 @@ var file_rpc_proto_goTypes = []interface{}{
(*MempoolEntryByAddress)(nil), // 104: protowire.MempoolEntryByAddress
(*GetMempoolEntriesByAddressesRequestMessage)(nil), // 105: protowire.GetMempoolEntriesByAddressesRequestMessage
(*GetMempoolEntriesByAddressesResponseMessage)(nil), // 106: protowire.GetMempoolEntriesByAddressesResponseMessage
(*GetCoinSupplyRequestMessage)(nil), // 107: protowire.GetCoinSupplyRequestMessage
(*GetCoinSupplyResponseMessage)(nil), // 108: protowire.GetCoinSupplyResponseMessage
}
var file_rpc_proto_depIdxs = []int32{
3, // 0: protowire.RpcBlock.header:type_name -> protowire.RpcBlockHeader
@ -6929,11 +7043,12 @@ var file_rpc_proto_depIdxs = []int32{
33, // 72: protowire.MempoolEntryByAddress.receiving:type_name -> protowire.MempoolEntry
104, // 73: protowire.GetMempoolEntriesByAddressesResponseMessage.entries:type_name -> protowire.MempoolEntryByAddress
1, // 74: protowire.GetMempoolEntriesByAddressesResponseMessage.error:type_name -> protowire.RPCError
75, // [75:75] is the sub-list for method output_type
75, // [75:75] is the sub-list for method input_type
75, // [75:75] is the sub-list for extension type_name
75, // [75:75] is the sub-list for extension extendee
0, // [0:75] is the sub-list for field type_name
1, // 75: protowire.GetCoinSupplyResponseMessage.error:type_name -> protowire.RPCError
76, // [76:76] is the sub-list for method output_type
76, // [76:76] is the sub-list for method input_type
76, // [76:76] is the sub-list for extension type_name
76, // [76:76] is the sub-list for extension extendee
0, // [0:76] is the sub-list for field type_name
}
func init() { file_rpc_proto_init() }
@ -8214,6 +8329,30 @@ func file_rpc_proto_init() {
return nil
}
}
file_rpc_proto_msgTypes[106].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetCoinSupplyRequestMessage); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_rpc_proto_msgTypes[107].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetCoinSupplyResponseMessage); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@ -8221,7 +8360,7 @@ func file_rpc_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_rpc_proto_rawDesc,
NumEnums: 1,
NumMessages: 106,
NumMessages: 108,
NumExtensions: 0,
NumServices: 0,
},

View File

@ -705,3 +705,12 @@ message GetMempoolEntriesByAddressesResponseMessage{
RPCError error = 1000;
}
message GetCoinSupplyRequestMessage{
}
message GetCoinSupplyResponseMessage{
uint64 maxSompi = 1; // note: this is a hard coded maxSupply, actual maxSupply is expected to deviate by upto -5%, but cannot be measured exactly.
uint64 circulatingSompi = 2;
RPCError error = 1000;
}

View File

@ -0,0 +1,54 @@
package protowire
import (
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/pkg/errors"
)
func (x *KaspadMessage_GetCoinSupplyRequest) toAppMessage() (appmessage.Message, error) {
return &appmessage.GetCoinSupplyRequestMessage{}, nil
}
func (x *KaspadMessage_GetCoinSupplyRequest) fromAppMessage(_ *appmessage.GetCoinSupplyRequestMessage) error {
x.GetCoinSupplyRequest = &GetCoinSupplyRequestMessage{}
return nil
}
func (x *KaspadMessage_GetCoinSupplyResponse) toAppMessage() (appmessage.Message, error) {
if x == nil {
return nil, errors.Wrapf(errorNil, "KaspadMessage_GetCoinSupplyResponse is nil")
}
return x.GetCoinSupplyResponse.toAppMessage()
}
func (x *KaspadMessage_GetCoinSupplyResponse) fromAppMessage(message *appmessage.GetCoinSupplyResponseMessage) error {
var err *RPCError
if message.Error != nil {
err = &RPCError{Message: message.Error.Message}
}
x.GetCoinSupplyResponse = &GetCoinSupplyResponseMessage{
MaxSompi: message.MaxSompi,
CirculatingSompi: message.CirculatingSompi,
Error: err,
}
return nil
}
func (x *GetCoinSupplyResponseMessage) toAppMessage() (appmessage.Message, error) {
if x == nil {
return nil, errors.Wrapf(errorNil, "GetCoinSupplyResponseMessage is nil")
}
rpcErr, err := x.Error.toAppMessage()
// Error is an optional field
if err != nil && !errors.Is(err, errorNil) {
return nil, err
}
return &appmessage.GetCoinSupplyResponseMessage{
MaxSompi: x.MaxSompi,
CirculatingSompi: x.CirculatingSompi,
Error: rpcErr,
}, nil
}

View File

@ -954,6 +954,20 @@ func toRPCPayload(message appmessage.Message) (isKaspadMessage_Payload, error) {
return nil, err
}
return payload, nil
case *appmessage.GetCoinSupplyRequestMessage:
payload := new(KaspadMessage_GetCoinSupplyRequest)
err := payload.fromAppMessage(message)
if err != nil {
return nil, err
}
return payload, nil
case *appmessage.GetCoinSupplyResponseMessage:
payload := new(KaspadMessage_GetCoinSupplyResponse)
err := payload.fromAppMessage(message)
if err != nil {
return nil, err
}
return payload, nil
default:
return nil, nil
}

View File

@ -0,0 +1,20 @@
package rpcclient
import "github.com/kaspanet/kaspad/app/appmessage"
// GetCoinSupply sends an RPC request respective to the function's name and returns the RPC server's response
func (c *RPCClient) GetCoinSupply() (*appmessage.GetCoinSupplyResponseMessage, error) {
err := c.rpcRouter.outgoingRoute().Enqueue(appmessage.NewGetCoinSupplyRequestMessage())
if err != nil {
return nil, err
}
response, err := c.route(appmessage.CmdGetCoinSupplyResponseMessage).DequeueWithTimeout(c.timeout)
if err != nil {
return nil, err
}
geCoinSupplyResponse := response.(*appmessage.GetCoinSupplyResponseMessage)
if geCoinSupplyResponse.Error != nil {
return nil, c.convertRPCError(geCoinSupplyResponse.Error)
}
return geCoinSupplyResponse, nil
}

View File

@ -49,6 +49,27 @@ func TestUTXOIndex(t *testing.T) {
mineNextBlock(t, kaspad)
}
//check if rewards corrosponds to circulating supply.
getCoinSupplyResponse, err := kaspad.rpcClient.GetCoinSupply()
if err != nil {
t.Fatalf("Error Retriving Coin supply: %s", err)
}
rewardsMinedSompi := uint64(blockAmountToMine * constants.SompiPerKaspa * 500)
getBlockCountResponse, err := kaspad.rpcClient.GetBlockCount()
if err != nil {
t.Fatalf("Error Retriving BlockCount: %s", err)
}
rewardsMinedViaBlockCountSompi := uint64(
(getBlockCountResponse.BlockCount - 2) * constants.SompiPerKaspa * 500, // -2 because of genesis and virtual.
)
if getCoinSupplyResponse.CirculatingSompi != rewardsMinedSompi {
t.Fatalf("Error: Circulating supply Mismatch - Circulating Sompi: %d Sompi Mined: %d", getCoinSupplyResponse.CirculatingSompi, rewardsMinedSompi)
} else if getCoinSupplyResponse.CirculatingSompi != rewardsMinedViaBlockCountSompi {
t.Fatalf("Error: Circulating supply Mismatch - Circulating Sompi: %d Sompi Mined via Block count: %d", getCoinSupplyResponse.CirculatingSompi, rewardsMinedViaBlockCountSompi)
}
// Collect the UTXO and make sure there's nothing in Removed
// Note that we expect blockAmountToMine-1 messages because
// the last block won't be accepted until the next block is