mirror of
https://github.com/kaspanet/kaspad.git
synced 2026-02-25 21:01:44 +00:00
Compare commits
1 Commits
patch9
...
v0.11.3-ti
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b8d36a1772 |
2
.github/workflows/race.yaml
vendored
2
.github/workflows/race.yaml
vendored
@@ -46,4 +46,4 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
git checkout "${{ env.run_on }}"
|
git checkout "${{ env.run_on }}"
|
||||||
git status
|
git status
|
||||||
go test -timeout 20m -race ./...
|
go test -race ./...
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ If you want to make a big change it's better to discuss it first by opening an i
|
|||||||
|
|
||||||
## Pull Request process
|
## Pull Request process
|
||||||
|
|
||||||
Any pull request should be opened against the development branch `dev`.
|
Any pull request should be opened against the development branch of the target version. The development branch format is
|
||||||
|
as follows: `vx.y.z-dev`, for example: `v0.8.5-dev`.
|
||||||
|
|
||||||
All pull requests should pass the checks written in `build_and_test.sh`, so it's recommended to run this script before
|
All pull requests should pass the checks written in `build_and_test.sh`, so it's recommended to run this script before
|
||||||
submitting your PR.
|
submitting your PR.
|
||||||
@@ -1,13 +1,16 @@
|
|||||||
|
|
||||||
Kaspad
|
Kaspad
|
||||||
====
|
====
|
||||||
|
Warning: This is pre-alpha software. There's no guarantee anything works.
|
||||||
|
====
|
||||||
|
|
||||||
[](https://choosealicense.com/licenses/isc/)
|
[](https://choosealicense.com/licenses/isc/)
|
||||||
[](http://godoc.org/github.com/kaspanet/kaspad)
|
[](http://godoc.org/github.com/kaspanet/kaspad)
|
||||||
|
|
||||||
Kaspad is the reference full node Kaspa implementation written in Go (golang).
|
Kaspad is the reference full node Kaspa implementation written in Go (golang).
|
||||||
|
|
||||||
This project is currently under active development and is in Beta state.
|
This project is currently under active development and is in a pre-Alpha state.
|
||||||
|
Some things still don't work and APIs are far from finalized. The code is provided for reference only.
|
||||||
|
|
||||||
## What is kaspa
|
## What is kaspa
|
||||||
|
|
||||||
|
|||||||
@@ -20,10 +20,7 @@ import (
|
|||||||
"github.com/kaspanet/kaspad/version"
|
"github.com/kaspanet/kaspad/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const leveldbCacheSizeMiB = 256
|
||||||
leveldbCacheSizeMiB = 256
|
|
||||||
defaultDataDirname = "datadir2"
|
|
||||||
)
|
|
||||||
|
|
||||||
var desiredLimits = &limits.DesiredLimits{
|
var desiredLimits = &limits.DesiredLimits{
|
||||||
FileLimitWant: 2048,
|
FileLimitWant: 2048,
|
||||||
@@ -87,7 +84,6 @@ func (app *kaspadApp) main(startedChan chan<- struct{}) error {
|
|||||||
if app.cfg.Profile != "" {
|
if app.cfg.Profile != "" {
|
||||||
profiling.Start(app.cfg.Profile, log)
|
profiling.Start(app.cfg.Profile, log)
|
||||||
}
|
}
|
||||||
profiling.TrackHeap(app.cfg.AppDir, log)
|
|
||||||
|
|
||||||
// Return now if an interrupt signal was triggered.
|
// Return now if an interrupt signal was triggered.
|
||||||
if signal.InterruptRequested(interrupt) {
|
if signal.InterruptRequested(interrupt) {
|
||||||
@@ -163,7 +159,7 @@ func (app *kaspadApp) main(startedChan chan<- struct{}) error {
|
|||||||
|
|
||||||
// dbPath returns the path to the block database given a database type.
|
// dbPath returns the path to the block database given a database type.
|
||||||
func databasePath(cfg *config.Config) string {
|
func databasePath(cfg *config.Config) string {
|
||||||
return filepath.Join(cfg.AppDir, defaultDataDirname)
|
return filepath.Join(cfg.AppDir, "data")
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeDatabase(cfg *config.Config) error {
|
func removeDatabase(cfg *config.Config) error {
|
||||||
|
|||||||
@@ -436,10 +436,10 @@ func RPCBlockToDomainBlock(block *RPCBlock) (*externalapi.DomainBlock, error) {
|
|||||||
|
|
||||||
// BlockWithTrustedDataToDomainBlockWithTrustedData converts *MsgBlockWithTrustedData to *externalapi.BlockWithTrustedData
|
// BlockWithTrustedDataToDomainBlockWithTrustedData converts *MsgBlockWithTrustedData to *externalapi.BlockWithTrustedData
|
||||||
func BlockWithTrustedDataToDomainBlockWithTrustedData(block *MsgBlockWithTrustedData) *externalapi.BlockWithTrustedData {
|
func BlockWithTrustedDataToDomainBlockWithTrustedData(block *MsgBlockWithTrustedData) *externalapi.BlockWithTrustedData {
|
||||||
daaWindow := make([]*externalapi.TrustedDataDataDAAHeader, len(block.DAAWindow))
|
daaWindow := make([]*externalapi.TrustedDataDataDAABlock, len(block.DAAWindow))
|
||||||
for i, daaBlock := range block.DAAWindow {
|
for i, daaBlock := range block.DAAWindow {
|
||||||
daaWindow[i] = &externalapi.TrustedDataDataDAAHeader{
|
daaWindow[i] = &externalapi.TrustedDataDataDAABlock{
|
||||||
Header: BlockHeaderToDomainBlockHeader(&daaBlock.Block.Header),
|
Block: MsgBlockToDomainBlock(daaBlock.Block),
|
||||||
GHOSTDAGData: ghostdagDataToDomainGHOSTDAGData(daaBlock.GHOSTDAGData),
|
GHOSTDAGData: ghostdagDataToDomainGHOSTDAGData(daaBlock.GHOSTDAGData),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -454,27 +454,12 @@ func BlockWithTrustedDataToDomainBlockWithTrustedData(block *MsgBlockWithTrusted
|
|||||||
|
|
||||||
return &externalapi.BlockWithTrustedData{
|
return &externalapi.BlockWithTrustedData{
|
||||||
Block: MsgBlockToDomainBlock(block.Block),
|
Block: MsgBlockToDomainBlock(block.Block),
|
||||||
|
DAAScore: block.DAAScore,
|
||||||
DAAWindow: daaWindow,
|
DAAWindow: daaWindow,
|
||||||
GHOSTDAGData: ghostdagData,
|
GHOSTDAGData: ghostdagData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrustedDataDataDAABlockV4ToTrustedDataDataDAAHeader converts *TrustedDataDAAHeader to *externalapi.TrustedDataDataDAAHeader
|
|
||||||
func TrustedDataDataDAABlockV4ToTrustedDataDataDAAHeader(daaBlock *TrustedDataDAAHeader) *externalapi.TrustedDataDataDAAHeader {
|
|
||||||
return &externalapi.TrustedDataDataDAAHeader{
|
|
||||||
Header: BlockHeaderToDomainBlockHeader(daaBlock.Header),
|
|
||||||
GHOSTDAGData: ghostdagDataToDomainGHOSTDAGData(daaBlock.GHOSTDAGData),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GHOSTDAGHashPairToDomainGHOSTDAGHashPair converts *BlockGHOSTDAGDataHashPair to *externalapi.BlockGHOSTDAGDataHashPair
|
|
||||||
func GHOSTDAGHashPairToDomainGHOSTDAGHashPair(datum *BlockGHOSTDAGDataHashPair) *externalapi.BlockGHOSTDAGDataHashPair {
|
|
||||||
return &externalapi.BlockGHOSTDAGDataHashPair{
|
|
||||||
Hash: datum.Hash,
|
|
||||||
GHOSTDAGData: ghostdagDataToDomainGHOSTDAGData(datum.GHOSTDAGData),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ghostdagDataToDomainGHOSTDAGData(data *BlockGHOSTDAGData) *externalapi.BlockGHOSTDAGData {
|
func ghostdagDataToDomainGHOSTDAGData(data *BlockGHOSTDAGData) *externalapi.BlockGHOSTDAGData {
|
||||||
bluesAnticoneSizes := make(map[externalapi.DomainHash]externalapi.KType, len(data.BluesAnticoneSizes))
|
bluesAnticoneSizes := make(map[externalapi.DomainHash]externalapi.KType, len(data.BluesAnticoneSizes))
|
||||||
for _, pair := range data.BluesAnticoneSizes {
|
for _, pair := range data.BluesAnticoneSizes {
|
||||||
@@ -515,9 +500,7 @@ func DomainBlockWithTrustedDataToBlockWithTrustedData(block *externalapi.BlockWi
|
|||||||
daaWindow := make([]*TrustedDataDataDAABlock, len(block.DAAWindow))
|
daaWindow := make([]*TrustedDataDataDAABlock, len(block.DAAWindow))
|
||||||
for i, daaBlock := range block.DAAWindow {
|
for i, daaBlock := range block.DAAWindow {
|
||||||
daaWindow[i] = &TrustedDataDataDAABlock{
|
daaWindow[i] = &TrustedDataDataDAABlock{
|
||||||
Block: &MsgBlock{
|
Block: DomainBlockToMsgBlock(daaBlock.Block),
|
||||||
Header: *DomainBlockHeaderToBlockHeader(daaBlock.Header),
|
|
||||||
},
|
|
||||||
GHOSTDAGData: domainGHOSTDAGDataGHOSTDAGData(daaBlock.GHOSTDAGData),
|
GHOSTDAGData: domainGHOSTDAGDataGHOSTDAGData(daaBlock.GHOSTDAGData),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -532,41 +515,7 @@ func DomainBlockWithTrustedDataToBlockWithTrustedData(block *externalapi.BlockWi
|
|||||||
|
|
||||||
return &MsgBlockWithTrustedData{
|
return &MsgBlockWithTrustedData{
|
||||||
Block: DomainBlockToMsgBlock(block.Block),
|
Block: DomainBlockToMsgBlock(block.Block),
|
||||||
DAAScore: block.Block.Header.DAAScore(),
|
DAAScore: block.DAAScore,
|
||||||
DAAWindow: daaWindow,
|
|
||||||
GHOSTDAGData: ghostdagData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainBlockWithTrustedDataToBlockWithTrustedDataV4 converts a set of *externalapi.DomainBlock, daa window indices and ghostdag data indices
|
|
||||||
// to *MsgBlockWithTrustedDataV4
|
|
||||||
func DomainBlockWithTrustedDataToBlockWithTrustedDataV4(block *externalapi.DomainBlock, daaWindowIndices, ghostdagDataIndices []uint64) *MsgBlockWithTrustedDataV4 {
|
|
||||||
return &MsgBlockWithTrustedDataV4{
|
|
||||||
Block: DomainBlockToMsgBlock(block),
|
|
||||||
DAAWindowIndices: daaWindowIndices,
|
|
||||||
GHOSTDAGDataIndices: ghostdagDataIndices,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainTrustedDataToTrustedData converts *externalapi.BlockWithTrustedData to *MsgBlockWithTrustedData
|
|
||||||
func DomainTrustedDataToTrustedData(domainDAAWindow []*externalapi.TrustedDataDataDAAHeader, domainGHOSTDAGData []*externalapi.BlockGHOSTDAGDataHashPair) *MsgTrustedData {
|
|
||||||
daaWindow := make([]*TrustedDataDAAHeader, len(domainDAAWindow))
|
|
||||||
for i, daaBlock := range domainDAAWindow {
|
|
||||||
daaWindow[i] = &TrustedDataDAAHeader{
|
|
||||||
Header: DomainBlockHeaderToBlockHeader(daaBlock.Header),
|
|
||||||
GHOSTDAGData: domainGHOSTDAGDataGHOSTDAGData(daaBlock.GHOSTDAGData),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ghostdagData := make([]*BlockGHOSTDAGDataHashPair, len(domainGHOSTDAGData))
|
|
||||||
for i, datum := range domainGHOSTDAGData {
|
|
||||||
ghostdagData[i] = &BlockGHOSTDAGDataHashPair{
|
|
||||||
Hash: datum.Hash,
|
|
||||||
GHOSTDAGData: domainGHOSTDAGDataGHOSTDAGData(datum.GHOSTDAGData),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &MsgTrustedData{
|
|
||||||
DAAWindow: daaWindow,
|
DAAWindow: daaWindow,
|
||||||
GHOSTDAGData: ghostdagData,
|
GHOSTDAGData: ghostdagData,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,10 +38,6 @@ type RPCError struct {
|
|||||||
Message string
|
Message string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (err RPCError) Error() string {
|
|
||||||
return err.Message
|
|
||||||
}
|
|
||||||
|
|
||||||
// RPCErrorf formats according to a format specifier and returns the string
|
// RPCErrorf formats according to a format specifier and returns the string
|
||||||
// as an RPCError.
|
// as an RPCError.
|
||||||
func RPCErrorf(format string, args ...interface{}) *RPCError {
|
func RPCErrorf(format string, args ...interface{}) *RPCError {
|
||||||
|
|||||||
@@ -66,9 +66,6 @@ const (
|
|||||||
CmdPruningPoints
|
CmdPruningPoints
|
||||||
CmdRequestPruningPointProof
|
CmdRequestPruningPointProof
|
||||||
CmdPruningPointProof
|
CmdPruningPointProof
|
||||||
CmdReady
|
|
||||||
CmdTrustedData
|
|
||||||
CmdBlockWithTrustedDataV4
|
|
||||||
|
|
||||||
// rpc
|
// rpc
|
||||||
CmdGetCurrentNetworkRequestMessage
|
CmdGetCurrentNetworkRequestMessage
|
||||||
@@ -127,8 +124,6 @@ const (
|
|||||||
CmdStopNotifyingUTXOsChangedResponseMessage
|
CmdStopNotifyingUTXOsChangedResponseMessage
|
||||||
CmdGetUTXOsByAddressesRequestMessage
|
CmdGetUTXOsByAddressesRequestMessage
|
||||||
CmdGetUTXOsByAddressesResponseMessage
|
CmdGetUTXOsByAddressesResponseMessage
|
||||||
CmdGetBalanceByAddressRequestMessage
|
|
||||||
CmdGetBalanceByAddressResponseMessage
|
|
||||||
CmdGetVirtualSelectedParentBlueScoreRequestMessage
|
CmdGetVirtualSelectedParentBlueScoreRequestMessage
|
||||||
CmdGetVirtualSelectedParentBlueScoreResponseMessage
|
CmdGetVirtualSelectedParentBlueScoreResponseMessage
|
||||||
CmdNotifyVirtualSelectedParentBlueScoreChangedRequestMessage
|
CmdNotifyVirtualSelectedParentBlueScoreChangedRequestMessage
|
||||||
@@ -150,8 +145,6 @@ const (
|
|||||||
CmdNotifyVirtualDaaScoreChangedRequestMessage
|
CmdNotifyVirtualDaaScoreChangedRequestMessage
|
||||||
CmdNotifyVirtualDaaScoreChangedResponseMessage
|
CmdNotifyVirtualDaaScoreChangedResponseMessage
|
||||||
CmdVirtualDaaScoreChangedNotificationMessage
|
CmdVirtualDaaScoreChangedNotificationMessage
|
||||||
CmdGetBalancesByAddressesRequestMessage
|
|
||||||
CmdGetBalancesByAddressesResponseMessage
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProtocolMessageCommandToString maps all MessageCommands to their string representation
|
// ProtocolMessageCommandToString maps all MessageCommands to their string representation
|
||||||
@@ -192,9 +185,6 @@ var ProtocolMessageCommandToString = map[MessageCommand]string{
|
|||||||
CmdPruningPoints: "PruningPoints",
|
CmdPruningPoints: "PruningPoints",
|
||||||
CmdRequestPruningPointProof: "RequestPruningPointProof",
|
CmdRequestPruningPointProof: "RequestPruningPointProof",
|
||||||
CmdPruningPointProof: "PruningPointProof",
|
CmdPruningPointProof: "PruningPointProof",
|
||||||
CmdReady: "Ready",
|
|
||||||
CmdTrustedData: "TrustedData",
|
|
||||||
CmdBlockWithTrustedDataV4: "BlockWithTrustedDataV4",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RPCMessageCommandToString maps all MessageCommands to their string representation
|
// RPCMessageCommandToString maps all MessageCommands to their string representation
|
||||||
@@ -253,8 +243,6 @@ var RPCMessageCommandToString = map[MessageCommand]string{
|
|||||||
CmdStopNotifyingUTXOsChangedResponseMessage: "StopNotifyingUTXOsChangedResponse",
|
CmdStopNotifyingUTXOsChangedResponseMessage: "StopNotifyingUTXOsChangedResponse",
|
||||||
CmdGetUTXOsByAddressesRequestMessage: "GetUTXOsByAddressesRequest",
|
CmdGetUTXOsByAddressesRequestMessage: "GetUTXOsByAddressesRequest",
|
||||||
CmdGetUTXOsByAddressesResponseMessage: "GetUTXOsByAddressesResponse",
|
CmdGetUTXOsByAddressesResponseMessage: "GetUTXOsByAddressesResponse",
|
||||||
CmdGetBalanceByAddressRequestMessage: "GetBalanceByAddressRequest",
|
|
||||||
CmdGetBalanceByAddressResponseMessage: "GetBalancesByAddressResponse",
|
|
||||||
CmdGetVirtualSelectedParentBlueScoreRequestMessage: "GetVirtualSelectedParentBlueScoreRequest",
|
CmdGetVirtualSelectedParentBlueScoreRequestMessage: "GetVirtualSelectedParentBlueScoreRequest",
|
||||||
CmdGetVirtualSelectedParentBlueScoreResponseMessage: "GetVirtualSelectedParentBlueScoreResponse",
|
CmdGetVirtualSelectedParentBlueScoreResponseMessage: "GetVirtualSelectedParentBlueScoreResponse",
|
||||||
CmdNotifyVirtualSelectedParentBlueScoreChangedRequestMessage: "NotifyVirtualSelectedParentBlueScoreChangedRequest",
|
CmdNotifyVirtualSelectedParentBlueScoreChangedRequestMessage: "NotifyVirtualSelectedParentBlueScoreChangedRequest",
|
||||||
@@ -276,8 +264,6 @@ var RPCMessageCommandToString = map[MessageCommand]string{
|
|||||||
CmdNotifyVirtualDaaScoreChangedRequestMessage: "NotifyVirtualDaaScoreChangedRequest",
|
CmdNotifyVirtualDaaScoreChangedRequestMessage: "NotifyVirtualDaaScoreChangedRequest",
|
||||||
CmdNotifyVirtualDaaScoreChangedResponseMessage: "NotifyVirtualDaaScoreChangedResponse",
|
CmdNotifyVirtualDaaScoreChangedResponseMessage: "NotifyVirtualDaaScoreChangedResponse",
|
||||||
CmdVirtualDaaScoreChangedNotificationMessage: "VirtualDaaScoreChangedNotification",
|
CmdVirtualDaaScoreChangedNotificationMessage: "VirtualDaaScoreChangedNotification",
|
||||||
CmdGetBalancesByAddressesRequestMessage: "GetBalancesByAddressesRequest",
|
|
||||||
CmdGetBalancesByAddressesResponseMessage: "GetBalancesByAddressesResponse",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Message is an interface that describes a kaspa message. A type that
|
// Message is an interface that describes a kaspa message. A type that
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import (
|
|||||||
|
|
||||||
// TestBlock tests the MsgBlock API.
|
// TestBlock tests the MsgBlock API.
|
||||||
func TestBlock(t *testing.T) {
|
func TestBlock(t *testing.T) {
|
||||||
pver := uint32(4)
|
pver := ProtocolVersion
|
||||||
|
|
||||||
// Block 1 header.
|
// Block 1 header.
|
||||||
parents := blockOne.Header.Parents
|
parents := blockOne.Header.Parents
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// MsgBlockWithTrustedDataV4 represents a kaspa BlockWithTrustedDataV4 message
|
|
||||||
type MsgBlockWithTrustedDataV4 struct {
|
|
||||||
baseMessage
|
|
||||||
|
|
||||||
Block *MsgBlock
|
|
||||||
DAAWindowIndices []uint64
|
|
||||||
GHOSTDAGDataIndices []uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *MsgBlockWithTrustedDataV4) Command() MessageCommand {
|
|
||||||
return CmdBlockWithTrustedDataV4
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMsgBlockWithTrustedDataV4 returns a new MsgBlockWithTrustedDataV4.
|
|
||||||
func NewMsgBlockWithTrustedDataV4() *MsgBlockWithTrustedDataV4 {
|
|
||||||
return &MsgBlockWithTrustedDataV4{}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// MsgTrustedData represents a kaspa TrustedData message
|
|
||||||
type MsgTrustedData struct {
|
|
||||||
baseMessage
|
|
||||||
|
|
||||||
DAAWindow []*TrustedDataDAAHeader
|
|
||||||
GHOSTDAGData []*BlockGHOSTDAGDataHashPair
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *MsgTrustedData) Command() MessageCommand {
|
|
||||||
return CmdTrustedData
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMsgTrustedData returns a new MsgTrustedData.
|
|
||||||
func NewMsgTrustedData() *MsgTrustedData {
|
|
||||||
return &MsgTrustedData{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TrustedDataDAAHeader is an appmessage representation of externalapi.TrustedDataDataDAAHeader
|
|
||||||
type TrustedDataDAAHeader struct {
|
|
||||||
Header *MsgBlockHeader
|
|
||||||
GHOSTDAGData *BlockGHOSTDAGData
|
|
||||||
}
|
|
||||||
@@ -22,7 +22,7 @@ import (
|
|||||||
|
|
||||||
// TestTx tests the MsgTx API.
|
// TestTx tests the MsgTx API.
|
||||||
func TestTx(t *testing.T) {
|
func TestTx(t *testing.T) {
|
||||||
pver := uint32(4)
|
pver := ProtocolVersion
|
||||||
|
|
||||||
txIDStr := "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
|
txIDStr := "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
|
||||||
txID, err := transactionid.FromString(txIDStr)
|
txID, err := transactionid.FromString(txIDStr)
|
||||||
|
|||||||
@@ -82,12 +82,12 @@ func (msg *MsgVersion) Command() MessageCommand {
|
|||||||
// Message interface using the passed parameters and defaults for the remaining
|
// Message interface using the passed parameters and defaults for the remaining
|
||||||
// fields.
|
// fields.
|
||||||
func NewMsgVersion(addr *NetAddress, id *id.ID, network string,
|
func NewMsgVersion(addr *NetAddress, id *id.ID, network string,
|
||||||
subnetworkID *externalapi.DomainSubnetworkID, protocolVersion uint32) *MsgVersion {
|
subnetworkID *externalapi.DomainSubnetworkID) *MsgVersion {
|
||||||
|
|
||||||
// Limit the timestamp to one millisecond precision since the protocol
|
// Limit the timestamp to one millisecond precision since the protocol
|
||||||
// doesn't support better.
|
// doesn't support better.
|
||||||
return &MsgVersion{
|
return &MsgVersion{
|
||||||
ProtocolVersion: protocolVersion,
|
ProtocolVersion: ProtocolVersion,
|
||||||
Network: network,
|
Network: network,
|
||||||
Services: 0,
|
Services: 0,
|
||||||
Timestamp: mstime.Now(),
|
Timestamp: mstime.Now(),
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
|
|
||||||
// TestVersion tests the MsgVersion API.
|
// TestVersion tests the MsgVersion API.
|
||||||
func TestVersion(t *testing.T) {
|
func TestVersion(t *testing.T) {
|
||||||
pver := uint32(4)
|
pver := ProtocolVersion
|
||||||
|
|
||||||
// Create version message data.
|
// Create version message data.
|
||||||
tcpAddrMe := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 16111}
|
tcpAddrMe := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 16111}
|
||||||
@@ -26,7 +26,7 @@ func TestVersion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we get the correct data back out.
|
// Ensure we get the correct data back out.
|
||||||
msg := NewMsgVersion(me, generatedID, "mainnet", nil, 4)
|
msg := NewMsgVersion(me, generatedID, "mainnet", nil)
|
||||||
if msg.ProtocolVersion != pver {
|
if msg.ProtocolVersion != pver {
|
||||||
t.Errorf("NewMsgVersion: wrong protocol version - got %v, want %v",
|
t.Errorf("NewMsgVersion: wrong protocol version - got %v, want %v",
|
||||||
msg.ProtocolVersion, pver)
|
msg.ProtocolVersion, pver)
|
||||||
|
|||||||
@@ -5,9 +5,8 @@
|
|||||||
package appmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/util/mstime"
|
"github.com/kaspanet/kaspad/util/mstime"
|
||||||
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NetAddress defines information about a peer on the network including the time
|
// NetAddress defines information about a peer on the network including the time
|
||||||
@@ -58,7 +57,3 @@ func NewNetAddressTimestamp(
|
|||||||
func NewNetAddress(addr *net.TCPAddr) *NetAddress {
|
func NewNetAddress(addr *net.TCPAddr) *NetAddress {
|
||||||
return NewNetAddressIPPort(addr.IP, uint16(addr.Port))
|
return NewNetAddressIPPort(addr.IP, uint16(addr.Port))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (na NetAddress) String() string {
|
|
||||||
return na.TCPAddress().String()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// MsgReady implements the Message interface and represents a kaspa
|
|
||||||
// Ready message. It is used to notify that the peer is ready to receive
|
|
||||||
// messages.
|
|
||||||
//
|
|
||||||
// This message has no payload.
|
|
||||||
type MsgReady struct {
|
|
||||||
baseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message. This is part
|
|
||||||
// of the Message interface implementation.
|
|
||||||
func (msg *MsgReady) Command() MessageCommand {
|
|
||||||
return CmdReady
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMsgReady returns a new kaspa Ready message that conforms to the
|
|
||||||
// Message interface.
|
|
||||||
func NewMsgReady() *MsgReady {
|
|
||||||
return &MsgReady{}
|
|
||||||
}
|
|
||||||
@@ -11,6 +11,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// ProtocolVersion is the latest protocol version this package supports.
|
||||||
|
ProtocolVersion uint32 = 1
|
||||||
|
|
||||||
// DefaultServices describes the default services that are supported by
|
// DefaultServices describes the default services that are supported by
|
||||||
// the server.
|
// the server.
|
||||||
DefaultServices = SFNodeNetwork | SFNodeBloom | SFNodeCF
|
DefaultServices = SFNodeNetwork | SFNodeBloom | SFNodeCF
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// GetBalanceByAddressRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetBalanceByAddressRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Address string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetBalanceByAddressRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdGetBalanceByAddressRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetBalanceByAddressRequest returns a instance of the message
|
|
||||||
func NewGetBalanceByAddressRequest(address string) *GetBalanceByAddressRequestMessage {
|
|
||||||
return &GetBalanceByAddressRequestMessage{
|
|
||||||
Address: address,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBalanceByAddressResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetBalanceByAddressResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Balance uint64
|
|
||||||
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetBalanceByAddressResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdGetBalanceByAddressResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetBalanceByAddressResponse returns an instance of the message
|
|
||||||
func NewGetBalanceByAddressResponse(Balance uint64) *GetBalanceByAddressResponseMessage {
|
|
||||||
return &GetBalanceByAddressResponseMessage{
|
|
||||||
Balance: Balance,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// GetBalancesByAddressesRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetBalancesByAddressesRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Addresses []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetBalancesByAddressesRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdGetBalancesByAddressesRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetBalancesByAddressesRequest returns a instance of the message
|
|
||||||
func NewGetBalancesByAddressesRequest(addresses []string) *GetBalancesByAddressesRequestMessage {
|
|
||||||
return &GetBalancesByAddressesRequestMessage{
|
|
||||||
Addresses: addresses,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// BalancesByAddressesEntry represents the balance of some address
|
|
||||||
type BalancesByAddressesEntry struct {
|
|
||||||
Address string
|
|
||||||
Balance uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetBalancesByAddressesResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetBalancesByAddressesResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Entries []*BalancesByAddressesEntry
|
|
||||||
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetBalancesByAddressesResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdGetBalancesByAddressesResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetBalancesByAddressesResponse returns an instance of the message
|
|
||||||
func NewGetBalancesByAddressesResponse(entries []*BalancesByAddressesEntry) *GetBalancesByAddressesResponseMessage {
|
|
||||||
return &GetBalancesByAddressesResponseMessage{
|
|
||||||
Entries: entries,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,8 +4,7 @@ package appmessage
|
|||||||
// its respective RPC message
|
// its respective RPC message
|
||||||
type SubmitBlockRequestMessage struct {
|
type SubmitBlockRequestMessage struct {
|
||||||
baseMessage
|
baseMessage
|
||||||
Block *RPCBlock
|
Block *RPCBlock
|
||||||
AllowNonDAABlocks bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
// Command returns the protocol command string for the message
|
||||||
@@ -14,10 +13,9 @@ func (msg *SubmitBlockRequestMessage) Command() MessageCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewSubmitBlockRequestMessage returns a instance of the message
|
// NewSubmitBlockRequestMessage returns a instance of the message
|
||||||
func NewSubmitBlockRequestMessage(block *RPCBlock, allowNonDAABlocks bool) *SubmitBlockRequestMessage {
|
func NewSubmitBlockRequestMessage(block *RPCBlock) *SubmitBlockRequestMessage {
|
||||||
return &SubmitBlockRequestMessage{
|
return &SubmitBlockRequestMessage{
|
||||||
Block: block,
|
Block: block,
|
||||||
AllowNonDAABlocks: allowNonDAABlocks,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,14 +90,11 @@ type RPCBlockLevelParents struct {
|
|||||||
|
|
||||||
// RPCBlockVerboseData holds verbose data about a block
|
// RPCBlockVerboseData holds verbose data about a block
|
||||||
type RPCBlockVerboseData struct {
|
type RPCBlockVerboseData struct {
|
||||||
Hash string
|
Hash string
|
||||||
Difficulty float64
|
Difficulty float64
|
||||||
SelectedParentHash string
|
SelectedParentHash string
|
||||||
TransactionIDs []string
|
TransactionIDs []string
|
||||||
IsHeaderOnly bool
|
IsHeaderOnly bool
|
||||||
BlueScore uint64
|
BlueScore uint64
|
||||||
ChildrenHashes []string
|
ChildrenHashes []string
|
||||||
MergeSetBluesHashes []string
|
|
||||||
MergeSetRedsHashes []string
|
|
||||||
IsChainBlock bool
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ func NewComponentManager(cfg *config.Config, db infrastructuredatabase.Database,
|
|||||||
|
|
||||||
var utxoIndex *utxoindex.UTXOIndex
|
var utxoIndex *utxoindex.UTXOIndex
|
||||||
if cfg.UTXOIndex {
|
if cfg.UTXOIndex {
|
||||||
utxoIndex, err = utxoindex.New(domain, db)
|
utxoIndex, err = utxoindex.New(domain.Consensus(), db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -152,7 +152,6 @@ func setupRPC(
|
|||||||
utxoIndex,
|
utxoIndex,
|
||||||
shutDownChan,
|
shutDownChan,
|
||||||
)
|
)
|
||||||
protocolManager.SetOnVirtualChange(rpcManager.NotifyVirtualChange)
|
|
||||||
protocolManager.SetOnBlockAddedToDAGHandler(rpcManager.NotifyBlockAddedToDAG)
|
protocolManager.SetOnBlockAddedToDAGHandler(rpcManager.NotifyBlockAddedToDAG)
|
||||||
protocolManager.SetOnPruningPointUTXOSetOverrideHandler(rpcManager.NotifyPruningPointUTXOSetOverride)
|
protocolManager.SetOnPruningPointUTXOSetOverrideHandler(rpcManager.NotifyPruningPointUTXOSetOverride)
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
peerpkg "github.com/kaspanet/kaspad/app/protocol/peer"
|
|
||||||
routerpkg "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@@ -14,14 +12,3 @@ const DefaultTimeout = 120 * time.Second
|
|||||||
|
|
||||||
// ErrPeerWithSameIDExists signifies that a peer with the same ID already exist.
|
// ErrPeerWithSameIDExists signifies that a peer with the same ID already exist.
|
||||||
var ErrPeerWithSameIDExists = errors.New("ready peer with the same ID already exists")
|
var ErrPeerWithSameIDExists = errors.New("ready peer with the same ID already exists")
|
||||||
|
|
||||||
type flowExecuteFunc func(peer *peerpkg.Peer)
|
|
||||||
|
|
||||||
// Flow is a a data structure that is used in order to associate a p2p flow to some route in a router.
|
|
||||||
type Flow struct {
|
|
||||||
Name string
|
|
||||||
ExecuteFunc flowExecuteFunc
|
|
||||||
}
|
|
||||||
|
|
||||||
// FlowInitializeFunc is a function that is used in order to initialize a flow
|
|
||||||
type FlowInitializeFunc func(route *routerpkg.Route, peer *peerpkg.Peer) error
|
|
||||||
|
|||||||
@@ -11,13 +11,14 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
"github.com/kaspanet/kaspad/app/appmessage"
|
||||||
|
"github.com/kaspanet/kaspad/app/protocol/flows/blockrelay"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OnNewBlock updates the mempool after a new block arrival, and
|
// OnNewBlock updates the mempool after a new block arrival, and
|
||||||
// relays newly unorphaned transactions and possibly rebroadcast
|
// relays newly unorphaned transactions and possibly rebroadcast
|
||||||
// manually added transactions when not in IBD.
|
// manually added transactions when not in IBD.
|
||||||
func (f *FlowContext) OnNewBlock(block *externalapi.DomainBlock,
|
func (f *FlowContext) OnNewBlock(block *externalapi.DomainBlock,
|
||||||
virtualChangeSet *externalapi.VirtualChangeSet) error {
|
blockInsertionResult *externalapi.BlockInsertionResult) error {
|
||||||
|
|
||||||
hash := consensushashing.BlockHash(block)
|
hash := consensushashing.BlockHash(block)
|
||||||
log.Debugf("OnNewBlock start for block %s", hash)
|
log.Debugf("OnNewBlock start for block %s", hash)
|
||||||
@@ -31,10 +32,10 @@ func (f *FlowContext) OnNewBlock(block *externalapi.DomainBlock,
|
|||||||
log.Debugf("OnNewBlock: block %s unorphaned %d blocks", hash, len(unorphaningResults))
|
log.Debugf("OnNewBlock: block %s unorphaned %d blocks", hash, len(unorphaningResults))
|
||||||
|
|
||||||
newBlocks := []*externalapi.DomainBlock{block}
|
newBlocks := []*externalapi.DomainBlock{block}
|
||||||
newVirtualChangeSets := []*externalapi.VirtualChangeSet{virtualChangeSet}
|
newBlockInsertionResults := []*externalapi.BlockInsertionResult{blockInsertionResult}
|
||||||
for _, unorphaningResult := range unorphaningResults {
|
for _, unorphaningResult := range unorphaningResults {
|
||||||
newBlocks = append(newBlocks, unorphaningResult.block)
|
newBlocks = append(newBlocks, unorphaningResult.block)
|
||||||
newVirtualChangeSets = append(newVirtualChangeSets, unorphaningResult.virtualChangeSet)
|
newBlockInsertionResults = append(newBlockInsertionResults, unorphaningResult.blockInsertionResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
allAcceptedTransactions := make([]*externalapi.DomainTransaction, 0)
|
allAcceptedTransactions := make([]*externalapi.DomainTransaction, 0)
|
||||||
@@ -48,8 +49,8 @@ func (f *FlowContext) OnNewBlock(block *externalapi.DomainBlock,
|
|||||||
|
|
||||||
if f.onBlockAddedToDAGHandler != nil {
|
if f.onBlockAddedToDAGHandler != nil {
|
||||||
log.Debugf("OnNewBlock: calling f.onBlockAddedToDAGHandler for block %s", hash)
|
log.Debugf("OnNewBlock: calling f.onBlockAddedToDAGHandler for block %s", hash)
|
||||||
virtualChangeSet = newVirtualChangeSets[i]
|
blockInsertionResult = newBlockInsertionResults[i]
|
||||||
err := f.onBlockAddedToDAGHandler(newBlock, virtualChangeSet)
|
err := f.onBlockAddedToDAGHandler(newBlock, blockInsertionResult)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -59,15 +60,6 @@ func (f *FlowContext) OnNewBlock(block *externalapi.DomainBlock,
|
|||||||
return f.broadcastTransactionsAfterBlockAdded(newBlocks, allAcceptedTransactions)
|
return f.broadcastTransactionsAfterBlockAdded(newBlocks, allAcceptedTransactions)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnVirtualChange calls the handler function whenever the virtual block changes.
|
|
||||||
func (f *FlowContext) OnVirtualChange(virtualChangeSet *externalapi.VirtualChangeSet) error {
|
|
||||||
if f.onVirtualChangeHandler != nil && virtualChangeSet != nil {
|
|
||||||
return f.onVirtualChangeHandler(virtualChangeSet)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnPruningPointUTXOSetOverride calls the handler function whenever the UTXO set
|
// OnPruningPointUTXOSetOverride calls the handler function whenever the UTXO set
|
||||||
// resets due to pruning point change via IBD.
|
// resets due to pruning point change via IBD.
|
||||||
func (f *FlowContext) OnPruningPointUTXOSetOverride() error {
|
func (f *FlowContext) OnPruningPointUTXOSetOverride() error {
|
||||||
@@ -108,7 +100,7 @@ func (f *FlowContext) broadcastTransactionsAfterBlockAdded(
|
|||||||
|
|
||||||
// SharedRequestedBlocks returns a *blockrelay.SharedRequestedBlocks for sharing
|
// SharedRequestedBlocks returns a *blockrelay.SharedRequestedBlocks for sharing
|
||||||
// data about requested blocks between different peers.
|
// data about requested blocks between different peers.
|
||||||
func (f *FlowContext) SharedRequestedBlocks() *SharedRequestedBlocks {
|
func (f *FlowContext) SharedRequestedBlocks() *blockrelay.SharedRequestedBlocks {
|
||||||
return f.sharedRequestedBlocks
|
return f.sharedRequestedBlocks
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,14 +110,14 @@ func (f *FlowContext) AddBlock(block *externalapi.DomainBlock) error {
|
|||||||
return protocolerrors.Errorf(false, "cannot add header only block")
|
return protocolerrors.Errorf(false, "cannot add header only block")
|
||||||
}
|
}
|
||||||
|
|
||||||
virtualChangeSet, err := f.Domain().Consensus().ValidateAndInsertBlock(block, true)
|
blockInsertionResult, err := f.Domain().Consensus().ValidateAndInsertBlock(block, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.As(err, &ruleerrors.RuleError{}) {
|
if errors.As(err, &ruleerrors.RuleError{}) {
|
||||||
log.Warnf("Validation failed for block %s: %s", consensushashing.BlockHash(block), err)
|
log.Warnf("Validation failed for block %s: %s", consensushashing.BlockHash(block), err)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = f.OnNewBlock(block, virtualChangeSet)
|
err = f.OnNewBlock(block, blockInsertionResult)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import (
|
|||||||
|
|
||||||
"github.com/kaspanet/kaspad/domain"
|
"github.com/kaspanet/kaspad/domain"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/app/protocol/flows/blockrelay"
|
||||||
|
"github.com/kaspanet/kaspad/app/protocol/flows/transactionrelay"
|
||||||
peerpkg "github.com/kaspanet/kaspad/app/protocol/peer"
|
peerpkg "github.com/kaspanet/kaspad/app/protocol/peer"
|
||||||
"github.com/kaspanet/kaspad/infrastructure/config"
|
"github.com/kaspanet/kaspad/infrastructure/config"
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/addressmanager"
|
"github.com/kaspanet/kaspad/infrastructure/network/addressmanager"
|
||||||
@@ -20,10 +22,7 @@ import (
|
|||||||
|
|
||||||
// OnBlockAddedToDAGHandler is a handler function that's triggered
|
// OnBlockAddedToDAGHandler is a handler function that's triggered
|
||||||
// when a block is added to the DAG
|
// when a block is added to the DAG
|
||||||
type OnBlockAddedToDAGHandler func(block *externalapi.DomainBlock, virtualChangeSet *externalapi.VirtualChangeSet) error
|
type OnBlockAddedToDAGHandler func(block *externalapi.DomainBlock, blockInsertionResult *externalapi.BlockInsertionResult) error
|
||||||
|
|
||||||
// OnVirtualChangeHandler is a handler function that's triggered when the virtual changes
|
|
||||||
type OnVirtualChangeHandler func(virtualChangeSet *externalapi.VirtualChangeSet) error
|
|
||||||
|
|
||||||
// OnPruningPointUTXOSetOverrideHandler is a handle function that's triggered whenever the UTXO set
|
// OnPruningPointUTXOSetOverrideHandler is a handle function that's triggered whenever the UTXO set
|
||||||
// resets due to pruning point change via IBD.
|
// resets due to pruning point change via IBD.
|
||||||
@@ -44,15 +43,14 @@ type FlowContext struct {
|
|||||||
|
|
||||||
timeStarted int64
|
timeStarted int64
|
||||||
|
|
||||||
onVirtualChangeHandler OnVirtualChangeHandler
|
|
||||||
onBlockAddedToDAGHandler OnBlockAddedToDAGHandler
|
onBlockAddedToDAGHandler OnBlockAddedToDAGHandler
|
||||||
onPruningPointUTXOSetOverrideHandler OnPruningPointUTXOSetOverrideHandler
|
onPruningPointUTXOSetOverrideHandler OnPruningPointUTXOSetOverrideHandler
|
||||||
onTransactionAddedToMempoolHandler OnTransactionAddedToMempoolHandler
|
onTransactionAddedToMempoolHandler OnTransactionAddedToMempoolHandler
|
||||||
|
|
||||||
lastRebroadcastTime time.Time
|
lastRebroadcastTime time.Time
|
||||||
sharedRequestedTransactions *SharedRequestedTransactions
|
sharedRequestedTransactions *transactionrelay.SharedRequestedTransactions
|
||||||
|
|
||||||
sharedRequestedBlocks *SharedRequestedBlocks
|
sharedRequestedBlocks *blockrelay.SharedRequestedBlocks
|
||||||
|
|
||||||
ibdPeer *peerpkg.Peer
|
ibdPeer *peerpkg.Peer
|
||||||
ibdPeerMutex sync.RWMutex
|
ibdPeerMutex sync.RWMutex
|
||||||
@@ -80,8 +78,8 @@ func New(cfg *config.Config, domain domain.Domain, addressManager *addressmanage
|
|||||||
domain: domain,
|
domain: domain,
|
||||||
addressManager: addressManager,
|
addressManager: addressManager,
|
||||||
connectionManager: connectionManager,
|
connectionManager: connectionManager,
|
||||||
sharedRequestedTransactions: NewSharedRequestedTransactions(),
|
sharedRequestedTransactions: transactionrelay.NewSharedRequestedTransactions(),
|
||||||
sharedRequestedBlocks: NewSharedRequestedBlocks(),
|
sharedRequestedBlocks: blockrelay.NewSharedRequestedBlocks(),
|
||||||
peers: make(map[id.ID]*peerpkg.Peer),
|
peers: make(map[id.ID]*peerpkg.Peer),
|
||||||
orphans: make(map[externalapi.DomainHash]*externalapi.DomainBlock),
|
orphans: make(map[externalapi.DomainHash]*externalapi.DomainBlock),
|
||||||
timeStarted: mstime.Now().UnixMilliseconds(),
|
timeStarted: mstime.Now().UnixMilliseconds(),
|
||||||
@@ -102,11 +100,6 @@ func (f *FlowContext) ShutdownChan() <-chan struct{} {
|
|||||||
return f.shutdownChan
|
return f.shutdownChan
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetOnVirtualChangeHandler sets the onVirtualChangeHandler handler
|
|
||||||
func (f *FlowContext) SetOnVirtualChangeHandler(onVirtualChangeHandler OnVirtualChangeHandler) {
|
|
||||||
f.onVirtualChangeHandler = onVirtualChangeHandler
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetOnBlockAddedToDAGHandler sets the onBlockAddedToDAG handler
|
// SetOnBlockAddedToDAGHandler sets the onBlockAddedToDAG handler
|
||||||
func (f *FlowContext) SetOnBlockAddedToDAGHandler(onBlockAddedToDAGHandler OnBlockAddedToDAGHandler) {
|
func (f *FlowContext) SetOnBlockAddedToDAGHandler(onBlockAddedToDAGHandler OnBlockAddedToDAGHandler) {
|
||||||
f.onBlockAddedToDAGHandler = onBlockAddedToDAGHandler
|
f.onBlockAddedToDAGHandler = onBlockAddedToDAGHandler
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ const maxOrphans = 600
|
|||||||
|
|
||||||
// UnorphaningResult is the result of unorphaning a block
|
// UnorphaningResult is the result of unorphaning a block
|
||||||
type UnorphaningResult struct {
|
type UnorphaningResult struct {
|
||||||
block *externalapi.DomainBlock
|
block *externalapi.DomainBlock
|
||||||
virtualChangeSet *externalapi.VirtualChangeSet
|
blockInsertionResult *externalapi.BlockInsertionResult
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddOrphan adds the block to the orphan set
|
// AddOrphan adds the block to the orphan set
|
||||||
@@ -90,14 +90,14 @@ func (f *FlowContext) UnorphanBlocks(rootBlock *externalapi.DomainBlock) ([]*Uno
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if canBeUnorphaned {
|
if canBeUnorphaned {
|
||||||
virtualChangeSet, unorphaningSucceeded, err := f.unorphanBlock(orphanHash)
|
blockInsertionResult, unorphaningSucceeded, err := f.unorphanBlock(orphanHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if unorphaningSucceeded {
|
if unorphaningSucceeded {
|
||||||
unorphaningResults = append(unorphaningResults, &UnorphaningResult{
|
unorphaningResults = append(unorphaningResults, &UnorphaningResult{
|
||||||
block: orphanBlock,
|
block: orphanBlock,
|
||||||
virtualChangeSet: virtualChangeSet,
|
blockInsertionResult: blockInsertionResult,
|
||||||
})
|
})
|
||||||
processQueue = f.addChildOrphansToProcessQueue(&orphanHash, processQueue)
|
processQueue = f.addChildOrphansToProcessQueue(&orphanHash, processQueue)
|
||||||
}
|
}
|
||||||
@@ -143,14 +143,14 @@ func (f *FlowContext) findChildOrphansOfBlock(blockHash *externalapi.DomainHash)
|
|||||||
return childOrphans
|
return childOrphans
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FlowContext) unorphanBlock(orphanHash externalapi.DomainHash) (*externalapi.VirtualChangeSet, bool, error) {
|
func (f *FlowContext) unorphanBlock(orphanHash externalapi.DomainHash) (*externalapi.BlockInsertionResult, bool, error) {
|
||||||
orphanBlock, ok := f.orphans[orphanHash]
|
orphanBlock, ok := f.orphans[orphanHash]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, false, errors.Errorf("attempted to unorphan a non-orphan block %s", orphanHash)
|
return nil, false, errors.Errorf("attempted to unorphan a non-orphan block %s", orphanHash)
|
||||||
}
|
}
|
||||||
delete(f.orphans, orphanHash)
|
delete(f.orphans, orphanHash)
|
||||||
|
|
||||||
virtualChangeSet, err := f.domain.Consensus().ValidateAndInsertBlock(orphanBlock, true)
|
blockInsertionResult, err := f.domain.Consensus().ValidateAndInsertBlock(orphanBlock, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.As(err, &ruleerrors.RuleError{}) {
|
if errors.As(err, &ruleerrors.RuleError{}) {
|
||||||
log.Warnf("Validation failed for orphan block %s: %s", orphanHash, err)
|
log.Warnf("Validation failed for orphan block %s: %s", orphanHash, err)
|
||||||
@@ -160,7 +160,7 @@ func (f *FlowContext) unorphanBlock(orphanHash externalapi.DomainHash) (*externa
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Unorphaned block %s", orphanHash)
|
log.Infof("Unorphaned block %s", orphanHash)
|
||||||
return virtualChangeSet, true, nil
|
return blockInsertionResult, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOrphanRoots returns the roots of the missing ancestors DAG of the given orphan
|
// GetOrphanRoots returns the roots of the missing ancestors DAG of the given orphan
|
||||||
|
|||||||
@@ -25,10 +25,6 @@ func (f *FlowContext) ShouldMine() (bool, error) {
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if virtualSelectedParent.Equal(f.Config().NetParams().GenesisHash) {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
virtualSelectedParentHeader, err := f.domain.Consensus().GetBlockHeader(virtualSelectedParent)
|
virtualSelectedParentHeader, err := f.domain.Consensus().GetBlockHeader(virtualSelectedParent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
"github.com/kaspanet/kaspad/app/appmessage"
|
||||||
|
"github.com/kaspanet/kaspad/app/protocol/flows/transactionrelay"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||||
)
|
)
|
||||||
@@ -29,7 +30,7 @@ func (f *FlowContext) shouldRebroadcastTransactions() bool {
|
|||||||
|
|
||||||
// SharedRequestedTransactions returns a *transactionrelay.SharedRequestedTransactions for sharing
|
// SharedRequestedTransactions returns a *transactionrelay.SharedRequestedTransactions for sharing
|
||||||
// data about requested transactions between different peers.
|
// data about requested transactions between different peers.
|
||||||
func (f *FlowContext) SharedRequestedTransactions() *SharedRequestedTransactions {
|
func (f *FlowContext) SharedRequestedTransactions() *transactionrelay.SharedRequestedTransactions {
|
||||||
return f.sharedRequestedTransactions
|
return f.sharedRequestedTransactions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,21 +13,15 @@ func (flow *handleRelayInvsFlow) sendGetBlockLocator(highHash *externalapi.Domai
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleRelayInvsFlow) receiveBlockLocator() (blockLocatorHashes []*externalapi.DomainHash, err error) {
|
func (flow *handleRelayInvsFlow) receiveBlockLocator() (blockLocatorHashes []*externalapi.DomainHash, err error) {
|
||||||
for {
|
message, err := flow.dequeueIncomingMessageAndSkipInvs(common.DefaultTimeout)
|
||||||
message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout)
|
if err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch message := message.(type) {
|
|
||||||
case *appmessage.MsgInvRelayBlock:
|
|
||||||
flow.invsQueue = append(flow.invsQueue, message)
|
|
||||||
case *appmessage.MsgBlockLocator:
|
|
||||||
return message.BlockLocatorHashes, nil
|
|
||||||
default:
|
|
||||||
return nil,
|
|
||||||
protocolerrors.Errorf(true, "received unexpected message type. "+
|
|
||||||
"expected: %s, got: %s", appmessage.CmdBlockLocator, message.Command())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
msgBlockLocator, ok := message.(*appmessage.MsgBlockLocator)
|
||||||
|
if !ok {
|
||||||
|
return nil,
|
||||||
|
protocolerrors.Errorf(true, "received unexpected message type. "+
|
||||||
|
"expected: %s, got: %s", appmessage.CmdBlockLocator, message.Command())
|
||||||
|
}
|
||||||
|
return msgBlockLocator.BlockLocatorHashes, nil
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package blockrelay
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kaspanet/kaspad/app/appmessage"
|
||||||
|
peerpkg "github.com/kaspanet/kaspad/app/protocol/peer"
|
||||||
|
"github.com/kaspanet/kaspad/domain"
|
||||||
|
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PruningPointAndItsAnticoneRequestsContext is the interface for the context needed for the HandlePruningPointAndItsAnticoneRequests flow.
|
||||||
|
type PruningPointAndItsAnticoneRequestsContext interface {
|
||||||
|
Domain() domain.Domain
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandlePruningPointAndItsAnticoneRequests listens to appmessage.MsgRequestPruningPointAndItsAnticone messages and sends
|
||||||
|
// the pruning point and its anticone to the requesting peer.
|
||||||
|
func HandlePruningPointAndItsAnticoneRequests(context PruningPointAndItsAnticoneRequestsContext, incomingRoute *router.Route,
|
||||||
|
outgoingRoute *router.Route, peer *peerpkg.Peer) error {
|
||||||
|
|
||||||
|
for {
|
||||||
|
_, err := incomingRoute.Dequeue()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("Got request for pruning point and its anticone from %s", peer)
|
||||||
|
|
||||||
|
pruningPointHeaders, err := context.Domain().Consensus().PruningPointHeaders()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
msgPruningPointHeaders := make([]*appmessage.MsgBlockHeader, len(pruningPointHeaders))
|
||||||
|
for i, header := range pruningPointHeaders {
|
||||||
|
msgPruningPointHeaders[i] = appmessage.DomainBlockHeaderToBlockHeader(header)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = outgoingRoute.Enqueue(appmessage.NewMsgPruningPoints(msgPruningPointHeaders))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
blocks, err := context.Domain().Consensus().PruningPointAndItsAnticoneWithTrustedData()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, block := range blocks {
|
||||||
|
err = outgoingRoute.Enqueue(appmessage.DomainBlockWithTrustedDataToBlockWithTrustedData(block))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = outgoingRoute.Enqueue(appmessage.NewMsgDoneBlocksWithTrustedData())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("Sent pruning point and its anticone to %s", peer)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@ package blockrelay
|
|||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
"github.com/kaspanet/kaspad/app/appmessage"
|
||||||
"github.com/kaspanet/kaspad/app/protocol/common"
|
"github.com/kaspanet/kaspad/app/protocol/common"
|
||||||
"github.com/kaspanet/kaspad/app/protocol/flowcontext"
|
|
||||||
peerpkg "github.com/kaspanet/kaspad/app/protocol/peer"
|
peerpkg "github.com/kaspanet/kaspad/app/protocol/peer"
|
||||||
"github.com/kaspanet/kaspad/app/protocol/protocolerrors"
|
"github.com/kaspanet/kaspad/app/protocol/protocolerrors"
|
||||||
"github.com/kaspanet/kaspad/domain"
|
"github.com/kaspanet/kaspad/domain"
|
||||||
@@ -24,15 +23,16 @@ var orphanResolutionRange uint32 = 5
|
|||||||
type RelayInvsContext interface {
|
type RelayInvsContext interface {
|
||||||
Domain() domain.Domain
|
Domain() domain.Domain
|
||||||
Config() *config.Config
|
Config() *config.Config
|
||||||
OnNewBlock(block *externalapi.DomainBlock, virtualChangeSet *externalapi.VirtualChangeSet) error
|
OnNewBlock(block *externalapi.DomainBlock, blockInsertionResult *externalapi.BlockInsertionResult) error
|
||||||
OnVirtualChange(virtualChangeSet *externalapi.VirtualChangeSet) error
|
|
||||||
OnPruningPointUTXOSetOverride() error
|
OnPruningPointUTXOSetOverride() error
|
||||||
SharedRequestedBlocks() *flowcontext.SharedRequestedBlocks
|
SharedRequestedBlocks() *SharedRequestedBlocks
|
||||||
Broadcast(message appmessage.Message) error
|
Broadcast(message appmessage.Message) error
|
||||||
AddOrphan(orphanBlock *externalapi.DomainBlock)
|
AddOrphan(orphanBlock *externalapi.DomainBlock)
|
||||||
GetOrphanRoots(orphanHash *externalapi.DomainHash) ([]*externalapi.DomainHash, bool, error)
|
GetOrphanRoots(orphanHash *externalapi.DomainHash) ([]*externalapi.DomainHash, bool, error)
|
||||||
IsOrphan(blockHash *externalapi.DomainHash) bool
|
IsOrphan(blockHash *externalapi.DomainHash) bool
|
||||||
IsIBDRunning() bool
|
IsIBDRunning() bool
|
||||||
|
TrySetIBDRunning(ibdPeer *peerpkg.Peer) bool
|
||||||
|
UnsetIBDRunning()
|
||||||
IsRecoverableError(err error) bool
|
IsRecoverableError(err error) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,10 +55,7 @@ func HandleRelayInvs(context RelayInvsContext, incomingRoute *router.Route, outg
|
|||||||
peer: peer,
|
peer: peer,
|
||||||
invsQueue: make([]*appmessage.MsgInvRelayBlock, 0),
|
invsQueue: make([]*appmessage.MsgInvRelayBlock, 0),
|
||||||
}
|
}
|
||||||
err := flow.start()
|
return flow.start()
|
||||||
// Currently, HandleRelayInvs flow is the only place where IBD is triggered, so the channel can be closed now
|
|
||||||
close(peer.IBDRequestChannel())
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleRelayInvsFlow) start() error {
|
func (flow *handleRelayInvsFlow) start() error {
|
||||||
@@ -84,18 +81,7 @@ func (flow *handleRelayInvsFlow) start() error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
isGenesisVirtualSelectedParent, err := flow.isGenesisVirtualSelectedParent()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if flow.IsOrphan(inv.Hash) {
|
if flow.IsOrphan(inv.Hash) {
|
||||||
if flow.Config().NetParams().DisallowDirectBlocksOnTopOfGenesis && !flow.Config().AllowSubmitBlockWhenNotSynced && isGenesisVirtualSelectedParent {
|
|
||||||
log.Infof("Cannot process orphan %s for a node with only the genesis block. The node needs to IBD "+
|
|
||||||
"to the recent pruning point before normal operation can resume.", inv.Hash)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("Block %s is a known orphan. Requesting its missing ancestors", inv.Hash)
|
log.Debugf("Block %s is a known orphan. Requesting its missing ancestors", inv.Hash)
|
||||||
err := flow.AddOrphanRootsToQueue(inv.Hash)
|
err := flow.AddOrphanRootsToQueue(inv.Hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -125,13 +111,8 @@ func (flow *handleRelayInvsFlow) start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if flow.Config().NetParams().DisallowDirectBlocksOnTopOfGenesis && !flow.Config().AllowSubmitBlockWhenNotSynced && !flow.Config().Devnet && flow.isChildOfGenesis(block) {
|
|
||||||
log.Infof("Cannot process %s because it's a direct child of genesis.", consensushashing.BlockHash(block))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("Processing block %s", inv.Hash)
|
log.Debugf("Processing block %s", inv.Hash)
|
||||||
missingParents, virtualChangeSet, err := flow.processBlock(block)
|
missingParents, blockInsertionResult, err := flow.processBlock(block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, ruleerrors.ErrPrunedBlock) {
|
if errors.Is(err, ruleerrors.ErrPrunedBlock) {
|
||||||
log.Infof("Ignoring pruned block %s", inv.Hash)
|
log.Infof("Ignoring pruned block %s", inv.Hash)
|
||||||
@@ -159,7 +140,7 @@ func (flow *handleRelayInvsFlow) start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Infof("Accepted block %s via relay", inv.Hash)
|
log.Infof("Accepted block %s via relay", inv.Hash)
|
||||||
err = flow.OnNewBlock(block, virtualChangeSet)
|
err = flow.OnNewBlock(block, blockInsertionResult)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -196,14 +177,14 @@ func (flow *handleRelayInvsFlow) readInv() (*appmessage.MsgInvRelayBlock, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleRelayInvsFlow) requestBlock(requestHash *externalapi.DomainHash) (*externalapi.DomainBlock, bool, error) {
|
func (flow *handleRelayInvsFlow) requestBlock(requestHash *externalapi.DomainHash) (*externalapi.DomainBlock, bool, error) {
|
||||||
exists := flow.SharedRequestedBlocks().AddIfNotExists(requestHash)
|
exists := flow.SharedRequestedBlocks().addIfNotExists(requestHash)
|
||||||
if exists {
|
if exists {
|
||||||
return nil, true, nil
|
return nil, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case the function returns earlier than expected, we want to make sure flow.SharedRequestedBlocks() is
|
// In case the function returns earlier than expected, we want to make sure flow.SharedRequestedBlocks() is
|
||||||
// clean from any pending blocks.
|
// clean from any pending blocks.
|
||||||
defer flow.SharedRequestedBlocks().Remove(requestHash)
|
defer flow.SharedRequestedBlocks().remove(requestHash)
|
||||||
|
|
||||||
getRelayBlocksMsg := appmessage.NewMsgRequestRelayBlocks([]*externalapi.DomainHash{requestHash})
|
getRelayBlocksMsg := appmessage.NewMsgRequestRelayBlocks([]*externalapi.DomainHash{requestHash})
|
||||||
err := flow.outgoingRoute.Enqueue(getRelayBlocksMsg)
|
err := flow.outgoingRoute.Enqueue(getRelayBlocksMsg)
|
||||||
@@ -246,9 +227,9 @@ func (flow *handleRelayInvsFlow) readMsgBlock() (msgBlock *appmessage.MsgBlock,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleRelayInvsFlow) processBlock(block *externalapi.DomainBlock) ([]*externalapi.DomainHash, *externalapi.VirtualChangeSet, error) {
|
func (flow *handleRelayInvsFlow) processBlock(block *externalapi.DomainBlock) ([]*externalapi.DomainHash, *externalapi.BlockInsertionResult, error) {
|
||||||
blockHash := consensushashing.BlockHash(block)
|
blockHash := consensushashing.BlockHash(block)
|
||||||
virtualChangeSet, err := flow.Domain().Consensus().ValidateAndInsertBlock(block, true)
|
blockInsertionResult, err := flow.Domain().Consensus().ValidateAndInsertBlock(block, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.As(err, &ruleerrors.RuleError{}) {
|
if !errors.As(err, &ruleerrors.RuleError{}) {
|
||||||
return nil, nil, errors.Wrapf(err, "failed to process block %s", blockHash)
|
return nil, nil, errors.Wrapf(err, "failed to process block %s", blockHash)
|
||||||
@@ -261,7 +242,7 @@ func (flow *handleRelayInvsFlow) processBlock(block *externalapi.DomainBlock) ([
|
|||||||
log.Warnf("Rejected block %s from %s: %s", blockHash, flow.peer, err)
|
log.Warnf("Rejected block %s from %s: %s", blockHash, flow.peer, err)
|
||||||
return nil, nil, protocolerrors.Wrapf(true, err, "got invalid block %s from relay", blockHash)
|
return nil, nil, protocolerrors.Wrapf(true, err, "got invalid block %s from relay", blockHash)
|
||||||
}
|
}
|
||||||
return nil, virtualChangeSet, nil
|
return nil, blockInsertionResult, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleRelayInvsFlow) relayBlock(block *externalapi.DomainBlock) error {
|
func (flow *handleRelayInvsFlow) relayBlock(block *externalapi.DomainBlock) error {
|
||||||
@@ -284,19 +265,6 @@ func (flow *handleRelayInvsFlow) processOrphan(block *externalapi.DomainBlock) e
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if isBlockInOrphanResolutionRange {
|
if isBlockInOrphanResolutionRange {
|
||||||
if flow.Config().NetParams().DisallowDirectBlocksOnTopOfGenesis && !flow.Config().AllowSubmitBlockWhenNotSynced {
|
|
||||||
isGenesisVirtualSelectedParent, err := flow.isGenesisVirtualSelectedParent()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if isGenesisVirtualSelectedParent {
|
|
||||||
log.Infof("Cannot process orphan %s for a node with only the genesis block. The node needs to IBD "+
|
|
||||||
"to the recent pruning point before normal operation can resume.", blockHash)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("Block %s is within orphan resolution range. "+
|
log.Debugf("Block %s is within orphan resolution range. "+
|
||||||
"Adding it to the orphan set", blockHash)
|
"Adding it to the orphan set", blockHash)
|
||||||
flow.AddOrphan(block)
|
flow.AddOrphan(block)
|
||||||
@@ -307,28 +275,7 @@ func (flow *handleRelayInvsFlow) processOrphan(block *externalapi.DomainBlock) e
|
|||||||
// Start IBD unless we already are in IBD
|
// Start IBD unless we already are in IBD
|
||||||
log.Debugf("Block %s is out of orphan resolution range. "+
|
log.Debugf("Block %s is out of orphan resolution range. "+
|
||||||
"Attempting to start IBD against it.", blockHash)
|
"Attempting to start IBD against it.", blockHash)
|
||||||
|
return flow.runIBDIfNotRunning(block)
|
||||||
// Send the block to IBD flow via the IBDRequestChannel.
|
|
||||||
// Note that this is a non-blocking send, since if IBD is already running, there is no need to trigger it
|
|
||||||
select {
|
|
||||||
case flow.peer.IBDRequestChannel() <- block:
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (flow *handleRelayInvsFlow) isGenesisVirtualSelectedParent() (bool, error) {
|
|
||||||
virtualSelectedParent, err := flow.Domain().Consensus().GetVirtualSelectedParent()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return virtualSelectedParent.Equal(flow.Config().NetParams().GenesisHash), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (flow *handleRelayInvsFlow) isChildOfGenesis(block *externalapi.DomainBlock) bool {
|
|
||||||
parents := block.Header.DirectParents()
|
|
||||||
return len(parents) == 1 && parents[0].Equal(flow.Config().NetParams().GenesisHash)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// isBlockInOrphanResolutionRange finds out whether the given blockHash should be
|
// isBlockInOrphanResolutionRange finds out whether the given blockHash should be
|
||||||
@@ -70,8 +70,7 @@ func (flow *handleRequestPruningPointUTXOSetFlow) waitForRequestPruningPointUTXO
|
|||||||
}
|
}
|
||||||
msgRequestPruningPointUTXOSet, ok := message.(*appmessage.MsgRequestPruningPointUTXOSet)
|
msgRequestPruningPointUTXOSet, ok := message.(*appmessage.MsgRequestPruningPointUTXOSet)
|
||||||
if !ok {
|
if !ok {
|
||||||
// TODO: Change to shouldBan: true once we fix the bug of getting redundant messages
|
return nil, protocolerrors.Errorf(true, "received unexpected message type. "+
|
||||||
return nil, protocolerrors.Errorf(false, "received unexpected message type. "+
|
|
||||||
"expected: %s, got: %s", appmessage.CmdRequestPruningPointUTXOSet, message.Command())
|
"expected: %s, got: %s", appmessage.CmdRequestPruningPointUTXOSet, message.Command())
|
||||||
}
|
}
|
||||||
return msgRequestPruningPointUTXOSet, nil
|
return msgRequestPruningPointUTXOSet, nil
|
||||||
@@ -124,8 +123,7 @@ func (flow *handleRequestPruningPointUTXOSetFlow) sendPruningPointUTXOSet(
|
|||||||
}
|
}
|
||||||
_, ok := message.(*appmessage.MsgRequestNextPruningPointUTXOSetChunk)
|
_, ok := message.(*appmessage.MsgRequestNextPruningPointUTXOSetChunk)
|
||||||
if !ok {
|
if !ok {
|
||||||
// TODO: Change to shouldBan: true once we fix the bug of getting redundant messages
|
return protocolerrors.Errorf(true, "received unexpected message type. "+
|
||||||
return protocolerrors.Errorf(false, "received unexpected message type. "+
|
|
||||||
"expected: %s, got: %s", appmessage.CmdRequestNextPruningPointUTXOSetChunk, message.Command())
|
"expected: %s, got: %s", appmessage.CmdRequestNextPruningPointUTXOSetChunk, message.Command())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,94 +1,22 @@
|
|||||||
package blockrelay
|
package blockrelay
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/infrastructure/logger"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
"github.com/kaspanet/kaspad/app/appmessage"
|
||||||
"github.com/kaspanet/kaspad/app/protocol/common"
|
"github.com/kaspanet/kaspad/app/protocol/common"
|
||||||
peerpkg "github.com/kaspanet/kaspad/app/protocol/peer"
|
|
||||||
"github.com/kaspanet/kaspad/app/protocol/protocolerrors"
|
"github.com/kaspanet/kaspad/app/protocol/protocolerrors"
|
||||||
"github.com/kaspanet/kaspad/domain"
|
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
|
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||||
"github.com/kaspanet/kaspad/infrastructure/config"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/logger"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
"github.com/kaspanet/kaspad/util/difficulty"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"math/big"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// IBDContext is the interface for the context needed for the HandleIBD flow.
|
func (flow *handleRelayInvsFlow) runIBDIfNotRunning(block *externalapi.DomainBlock) error {
|
||||||
type IBDContext interface {
|
|
||||||
Domain() domain.Domain
|
|
||||||
Config() *config.Config
|
|
||||||
OnNewBlock(block *externalapi.DomainBlock, virtualChangeSet *externalapi.VirtualChangeSet) error
|
|
||||||
OnVirtualChange(virtualChangeSet *externalapi.VirtualChangeSet) error
|
|
||||||
OnPruningPointUTXOSetOverride() error
|
|
||||||
IsIBDRunning() bool
|
|
||||||
TrySetIBDRunning(ibdPeer *peerpkg.Peer) bool
|
|
||||||
UnsetIBDRunning()
|
|
||||||
IsRecoverableError(err error) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type handleIBDFlow struct {
|
|
||||||
IBDContext
|
|
||||||
incomingRoute, outgoingRoute *router.Route
|
|
||||||
peer *peerpkg.Peer
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleIBD handles IBD
|
|
||||||
func HandleIBD(context IBDContext, incomingRoute *router.Route, outgoingRoute *router.Route,
|
|
||||||
peer *peerpkg.Peer) error {
|
|
||||||
|
|
||||||
flow := &handleIBDFlow{
|
|
||||||
IBDContext: context,
|
|
||||||
incomingRoute: incomingRoute,
|
|
||||||
outgoingRoute: outgoingRoute,
|
|
||||||
peer: peer,
|
|
||||||
}
|
|
||||||
return flow.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (flow *handleIBDFlow) start() error {
|
|
||||||
for {
|
|
||||||
// Wait for IBD requests triggered by other flows
|
|
||||||
block, ok := <-flow.peer.IBDRequestChannel()
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err := flow.runIBDIfNotRunning(block)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (flow *handleIBDFlow) runIBDIfNotRunning(block *externalapi.DomainBlock) error {
|
|
||||||
highHash := consensushashing.BlockHash(block)
|
|
||||||
|
|
||||||
// Temp code to avoid IBD from lagging nodes publishing their side-chain
|
|
||||||
virtualSelectedParent, err := flow.Domain().Consensus().GetVirtualSelectedParent()
|
|
||||||
if err == nil {
|
|
||||||
virtualSelectedParentHeader, err := flow.Domain().Consensus().GetBlockHeader(virtualSelectedParent)
|
|
||||||
if err == nil {
|
|
||||||
if virtualSelectedParentHeader.DAAScore() > block.Header.DAAScore()+2641 {
|
|
||||||
virtualDifficulty := difficulty.CalcWork(virtualSelectedParentHeader.Bits())
|
|
||||||
var virtualSub, difficultyMul big.Int
|
|
||||||
if difficultyMul.Mul(virtualDifficulty, big.NewInt(180)).
|
|
||||||
Cmp(virtualSub.Sub(virtualSelectedParentHeader.BlueWork(), block.Header.BlueWork())) < 0 {
|
|
||||||
log.Criticalf("Avoiding IBD triggered by relay %s because it is coming from " +
|
|
||||||
"a deep (%d DAA score depth) side-chain which has much lower blue work (%d, %d)",
|
|
||||||
highHash,
|
|
||||||
virtualSelectedParentHeader.DAAScore()-block.Header.DAAScore(),
|
|
||||||
virtualSelectedParentHeader.BlueWork(), block.Header.BlueWork())
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wasIBDNotRunning := flow.TrySetIBDRunning(flow.peer)
|
wasIBDNotRunning := flow.TrySetIBDRunning(flow.peer)
|
||||||
if !wasIBDNotRunning {
|
if !wasIBDNotRunning {
|
||||||
log.Debugf("IBD is already running")
|
log.Debugf("IBD is already running")
|
||||||
@@ -101,14 +29,15 @@ func (flow *handleIBDFlow) runIBDIfNotRunning(block *externalapi.DomainBlock) er
|
|||||||
flow.logIBDFinished(isFinishedSuccessfully)
|
flow.logIBDFinished(isFinishedSuccessfully)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
log.Criticalf("IBD started with peer %s and highHash %s", flow.peer, highHash)
|
highHash := consensushashing.BlockHash(block)
|
||||||
log.Criticalf("Syncing blocks up to %s", highHash)
|
log.Debugf("IBD started with peer %s and highHash %s", flow.peer, highHash)
|
||||||
log.Criticalf("Trying to find highest shared chain block with peer %s with high hash %s", flow.peer, highHash)
|
log.Debugf("Syncing blocks up to %s", highHash)
|
||||||
|
log.Debugf("Trying to find highest shared chain block with peer %s with high hash %s", flow.peer, highHash)
|
||||||
highestSharedBlockHash, highestSharedBlockFound, err := flow.findHighestSharedBlockHash(highHash)
|
highestSharedBlockHash, highestSharedBlockFound, err := flow.findHighestSharedBlockHash(highHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Criticalf("Found highest shared chain block %s with peer %s", highestSharedBlockHash, flow.peer)
|
log.Debugf("Found highest shared chain block %s with peer %s", highestSharedBlockHash, flow.peer)
|
||||||
|
|
||||||
shouldDownloadHeadersProof, shouldSync, err := flow.shouldSyncAndShouldDownloadHeadersProof(block, highestSharedBlockFound)
|
shouldDownloadHeadersProof, shouldSync, err := flow.shouldSyncAndShouldDownloadHeadersProof(block, highestSharedBlockFound)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -121,25 +50,12 @@ func (flow *handleIBDFlow) runIBDIfNotRunning(block *externalapi.DomainBlock) er
|
|||||||
|
|
||||||
if shouldDownloadHeadersProof {
|
if shouldDownloadHeadersProof {
|
||||||
log.Infof("Starting IBD with headers proof")
|
log.Infof("Starting IBD with headers proof")
|
||||||
err := flow.ibdWithHeadersProof(highHash, block.Header.DAAScore())
|
err := flow.ibdWithHeadersProof(highHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if flow.Config().NetParams().DisallowDirectBlocksOnTopOfGenesis && !flow.Config().AllowSubmitBlockWhenNotSynced {
|
err = flow.syncPruningPointFutureHeaders(flow.Domain().Consensus(), highestSharedBlockHash, highHash)
|
||||||
isGenesisVirtualSelectedParent, err := flow.isGenesisVirtualSelectedParent()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if isGenesisVirtualSelectedParent {
|
|
||||||
log.Infof("Cannot IBD to %s because it won't change the pruning point. The node needs to IBD "+
|
|
||||||
"to the recent pruning point before normal operation can resume.", highHash)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = flow.syncPruningPointFutureHeaders(flow.Domain().Consensus(), highestSharedBlockHash, highHash, block.Header.DAAScore())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -155,16 +71,7 @@ func (flow *handleIBDFlow) runIBDIfNotRunning(block *externalapi.DomainBlock) er
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) isGenesisVirtualSelectedParent() (bool, error) {
|
func (flow *handleRelayInvsFlow) logIBDFinished(isFinishedSuccessfully bool) {
|
||||||
virtualSelectedParent, err := flow.Domain().Consensus().GetVirtualSelectedParent()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return virtualSelectedParent.Equal(flow.Config().NetParams().GenesisHash), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (flow *handleIBDFlow) logIBDFinished(isFinishedSuccessfully bool) {
|
|
||||||
successString := "successfully"
|
successString := "successfully"
|
||||||
if !isFinishedSuccessfully {
|
if !isFinishedSuccessfully {
|
||||||
successString = "(interrupted)"
|
successString = "(interrupted)"
|
||||||
@@ -175,7 +82,7 @@ func (flow *handleIBDFlow) logIBDFinished(isFinishedSuccessfully bool) {
|
|||||||
// findHighestSharedBlock attempts to find the highest shared block between the peer
|
// findHighestSharedBlock attempts to find the highest shared block between the peer
|
||||||
// and this node. This method may fail because the peer and us have conflicting pruning
|
// and this node. This method may fail because the peer and us have conflicting pruning
|
||||||
// points. In that case we return (nil, false, nil) so that we may stop IBD gracefully.
|
// points. In that case we return (nil, false, nil) so that we may stop IBD gracefully.
|
||||||
func (flow *handleIBDFlow) findHighestSharedBlockHash(
|
func (flow *handleRelayInvsFlow) findHighestSharedBlockHash(
|
||||||
targetHash *externalapi.DomainHash) (*externalapi.DomainHash, bool, error) {
|
targetHash *externalapi.DomainHash) (*externalapi.DomainHash, bool, error) {
|
||||||
|
|
||||||
log.Debugf("Sending a blockLocator to %s between pruning point and headers selected tip", flow.peer)
|
log.Debugf("Sending a blockLocator to %s between pruning point and headers selected tip", flow.peer)
|
||||||
@@ -218,7 +125,7 @@ func (flow *handleIBDFlow) findHighestSharedBlockHash(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) nextBlockLocator(lowHash, highHash *externalapi.DomainHash) (externalapi.BlockLocator, error) {
|
func (flow *handleRelayInvsFlow) nextBlockLocator(lowHash, highHash *externalapi.DomainHash) (externalapi.BlockLocator, error) {
|
||||||
log.Debugf("Sending a blockLocator to %s between %s and %s", flow.peer, lowHash, highHash)
|
log.Debugf("Sending a blockLocator to %s between %s and %s", flow.peer, lowHash, highHash)
|
||||||
blockLocator, err := flow.Domain().Consensus().CreateHeadersSelectedChainBlockLocator(lowHash, highHash)
|
blockLocator, err := flow.Domain().Consensus().CreateHeadersSelectedChainBlockLocator(lowHash, highHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -236,7 +143,7 @@ func (flow *handleIBDFlow) nextBlockLocator(lowHash, highHash *externalapi.Domai
|
|||||||
return blockLocator, nil
|
return blockLocator, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) findHighestHashIndex(
|
func (flow *handleRelayInvsFlow) findHighestHashIndex(
|
||||||
highestHash *externalapi.DomainHash, blockLocator externalapi.BlockLocator) (int, error) {
|
highestHash *externalapi.DomainHash, blockLocator externalapi.BlockLocator) (int, error) {
|
||||||
|
|
||||||
highestHashIndex := 0
|
highestHashIndex := 0
|
||||||
@@ -261,7 +168,7 @@ func (flow *handleIBDFlow) findHighestHashIndex(
|
|||||||
// fetchHighestHash attempts to fetch the highest hash the peer knows amongst the given
|
// fetchHighestHash attempts to fetch the highest hash the peer knows amongst the given
|
||||||
// blockLocator. This method may fail because the peer and us have conflicting pruning
|
// blockLocator. This method may fail because the peer and us have conflicting pruning
|
||||||
// points. In that case we return (nil, false, nil) so that we may stop IBD gracefully.
|
// points. In that case we return (nil, false, nil) so that we may stop IBD gracefully.
|
||||||
func (flow *handleIBDFlow) fetchHighestHash(
|
func (flow *handleRelayInvsFlow) fetchHighestHash(
|
||||||
targetHash *externalapi.DomainHash, blockLocator externalapi.BlockLocator) (*externalapi.DomainHash, bool, error) {
|
targetHash *externalapi.DomainHash, blockLocator externalapi.BlockLocator) (*externalapi.DomainHash, bool, error) {
|
||||||
|
|
||||||
ibdBlockLocatorMessage := appmessage.NewMsgIBDBlockLocator(targetHash, blockLocator)
|
ibdBlockLocatorMessage := appmessage.NewMsgIBDBlockLocator(targetHash, blockLocator)
|
||||||
@@ -269,7 +176,7 @@ func (flow *handleIBDFlow) fetchHighestHash(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout)
|
message, err := flow.dequeueIncomingMessageAndSkipInvs(common.DefaultTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
@@ -289,8 +196,8 @@ func (flow *handleIBDFlow) fetchHighestHash(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) syncPruningPointFutureHeaders(consensus externalapi.Consensus, highestSharedBlockHash *externalapi.DomainHash,
|
func (flow *handleRelayInvsFlow) syncPruningPointFutureHeaders(consensus externalapi.Consensus, highestSharedBlockHash *externalapi.DomainHash,
|
||||||
highHash *externalapi.DomainHash, highBlockDAAScore uint64) error {
|
highHash *externalapi.DomainHash) error {
|
||||||
|
|
||||||
log.Infof("Downloading headers from %s", flow.peer)
|
log.Infof("Downloading headers from %s", flow.peer)
|
||||||
|
|
||||||
@@ -299,12 +206,6 @@ func (flow *handleIBDFlow) syncPruningPointFutureHeaders(consensus externalapi.C
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
highestSharedBlockHeader, err := consensus.GetBlockHeader(highestSharedBlockHash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
progressReporter := newIBDProgressReporter(highestSharedBlockHeader.DAAScore(), highBlockDAAScore, "block headers")
|
|
||||||
|
|
||||||
// Keep a short queue of BlockHeadersMessages so that there's
|
// Keep a short queue of BlockHeadersMessages so that there's
|
||||||
// never a moment when the node is not validating and inserting
|
// never a moment when the node is not validating and inserting
|
||||||
// headers
|
// headers
|
||||||
@@ -348,29 +249,26 @@ func (flow *handleIBDFlow) syncPruningPointFutureHeaders(consensus externalapi.C
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for _, header := range ibdBlocksMessage.BlockHeaders {
|
for _, header := range ibdBlocksMessage.BlockHeaders {
|
||||||
_, err := flow.processHeader(consensus, header)
|
err = flow.processHeader(consensus, header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lastReceivedHeader := ibdBlocksMessage.BlockHeaders[len(ibdBlocksMessage.BlockHeaders)-1]
|
|
||||||
progressReporter.reportProgress(len(ibdBlocksMessage.BlockHeaders), lastReceivedHeader.DAAScore)
|
|
||||||
case err := <-errChan:
|
case err := <-errChan:
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) sendRequestHeaders(highestSharedBlockHash *externalapi.DomainHash,
|
func (flow *handleRelayInvsFlow) sendRequestHeaders(highestSharedBlockHash *externalapi.DomainHash,
|
||||||
peerSelectedTipHash *externalapi.DomainHash) error {
|
peerSelectedTipHash *externalapi.DomainHash) error {
|
||||||
|
|
||||||
msgGetBlockInvs := appmessage.NewMsgRequstHeaders(highestSharedBlockHash, peerSelectedTipHash)
|
msgGetBlockInvs := appmessage.NewMsgRequstHeaders(highestSharedBlockHash, peerSelectedTipHash)
|
||||||
return flow.outgoingRoute.Enqueue(msgGetBlockInvs)
|
return flow.outgoingRoute.Enqueue(msgGetBlockInvs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) receiveHeaders() (msgIBDBlock *appmessage.BlockHeadersMessage, doneHeaders bool, err error) {
|
func (flow *handleRelayInvsFlow) receiveHeaders() (msgIBDBlock *appmessage.BlockHeadersMessage, doneHeaders bool, err error) {
|
||||||
message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout)
|
message, err := flow.dequeueIncomingMessageAndSkipInvs(common.DefaultTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
@@ -389,7 +287,7 @@ func (flow *handleIBDFlow) receiveHeaders() (msgIBDBlock *appmessage.BlockHeader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) processHeader(consensus externalapi.Consensus, msgBlockHeader *appmessage.MsgBlockHeader) (bool, error) {
|
func (flow *handleRelayInvsFlow) processHeader(consensus externalapi.Consensus, msgBlockHeader *appmessage.MsgBlockHeader) error {
|
||||||
header := appmessage.BlockHeaderToDomainBlockHeader(msgBlockHeader)
|
header := appmessage.BlockHeaderToDomainBlockHeader(msgBlockHeader)
|
||||||
block := &externalapi.DomainBlock{
|
block := &externalapi.DomainBlock{
|
||||||
Header: header,
|
Header: header,
|
||||||
@@ -399,29 +297,30 @@ func (flow *handleIBDFlow) processHeader(consensus externalapi.Consensus, msgBlo
|
|||||||
blockHash := consensushashing.BlockHash(block)
|
blockHash := consensushashing.BlockHash(block)
|
||||||
blockInfo, err := consensus.GetBlockInfo(blockHash)
|
blockInfo, err := consensus.GetBlockInfo(blockHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return err
|
||||||
}
|
}
|
||||||
if blockInfo.Exists {
|
if blockInfo.Exists {
|
||||||
log.Debugf("Block header %s is already in the DAG. Skipping...", blockHash)
|
log.Debugf("Block header %s is already in the DAG. Skipping...", blockHash)
|
||||||
return false, nil
|
return nil
|
||||||
}
|
}
|
||||||
_, err = consensus.ValidateAndInsertBlock(block, false)
|
_, err = consensus.ValidateAndInsertBlock(block, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.As(err, &ruleerrors.RuleError{}) {
|
if !errors.As(err, &ruleerrors.RuleError{}) {
|
||||||
return false, errors.Wrapf(err, "failed to process header %s during IBD", blockHash)
|
return errors.Wrapf(err, "failed to process header %s during IBD", blockHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
if errors.Is(err, ruleerrors.ErrDuplicateBlock) {
|
if errors.Is(err, ruleerrors.ErrDuplicateBlock) {
|
||||||
log.Debugf("Skipping block header %s as it is a duplicate", blockHash)
|
log.Debugf("Skipping block header %s as it is a duplicate", blockHash)
|
||||||
} else {
|
} else {
|
||||||
log.Infof("Rejected block header %s from %s during IBD: %s", blockHash, flow.peer, err)
|
log.Infof("Rejected block header %s from %s during IBD: %s", blockHash, flow.peer, err)
|
||||||
return false, protocolerrors.Wrapf(true, err, "got invalid block header %s during IBD", blockHash)
|
return protocolerrors.Wrapf(true, err, "got invalid block header %s during IBD", blockHash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true, nil
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) validatePruningPointFutureHeaderTimestamps() error {
|
func (flow *handleRelayInvsFlow) validatePruningPointFutureHeaderTimestamps() error {
|
||||||
headerSelectedTipHash, err := flow.Domain().StagingConsensus().GetHeadersSelectedTip()
|
headerSelectedTipHash, err := flow.Domain().StagingConsensus().GetHeadersSelectedTip()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -455,7 +354,7 @@ func (flow *handleIBDFlow) validatePruningPointFutureHeaderTimestamps() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) receiveAndInsertPruningPointUTXOSet(
|
func (flow *handleRelayInvsFlow) receiveAndInsertPruningPointUTXOSet(
|
||||||
consensus externalapi.Consensus, pruningPointHash *externalapi.DomainHash) (bool, error) {
|
consensus externalapi.Consensus, pruningPointHash *externalapi.DomainHash) (bool, error) {
|
||||||
|
|
||||||
onEnd := logger.LogAndMeasureExecutionTime(log, "receiveAndInsertPruningPointUTXOSet")
|
onEnd := logger.LogAndMeasureExecutionTime(log, "receiveAndInsertPruningPointUTXOSet")
|
||||||
@@ -464,7 +363,7 @@ func (flow *handleIBDFlow) receiveAndInsertPruningPointUTXOSet(
|
|||||||
receivedChunkCount := 0
|
receivedChunkCount := 0
|
||||||
receivedUTXOCount := 0
|
receivedUTXOCount := 0
|
||||||
for {
|
for {
|
||||||
message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout)
|
message, err := flow.dequeueIncomingMessageAndSkipInvs(common.DefaultTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@@ -510,7 +409,7 @@ func (flow *handleIBDFlow) receiveAndInsertPruningPointUTXOSet(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) syncMissingBlockBodies(highHash *externalapi.DomainHash) error {
|
func (flow *handleRelayInvsFlow) syncMissingBlockBodies(highHash *externalapi.DomainHash) error {
|
||||||
hashes, err := flow.Domain().Consensus().GetMissingBlockBodyHashes(highHash)
|
hashes, err := flow.Domain().Consensus().GetMissingBlockBodyHashes(highHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -523,17 +422,6 @@ func (flow *handleIBDFlow) syncMissingBlockBodies(highHash *externalapi.DomainHa
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
lowBlockHeader, err := flow.Domain().Consensus().GetBlockHeader(hashes[0])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
highBlockHeader, err := flow.Domain().Consensus().GetBlockHeader(hashes[len(hashes)-1])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
progressReporter := newIBDProgressReporter(lowBlockHeader.DAAScore(), highBlockHeader.DAAScore(), "blocks")
|
|
||||||
highestProcessedDAAScore := lowBlockHeader.DAAScore()
|
|
||||||
|
|
||||||
for offset := 0; offset < len(hashes); offset += ibdBatchSize {
|
for offset := 0; offset < len(hashes); offset += ibdBatchSize {
|
||||||
var hashesToRequest []*externalapi.DomainHash
|
var hashesToRequest []*externalapi.DomainHash
|
||||||
if offset+ibdBatchSize < len(hashes) {
|
if offset+ibdBatchSize < len(hashes) {
|
||||||
@@ -548,7 +436,7 @@ func (flow *handleIBDFlow) syncMissingBlockBodies(highHash *externalapi.DomainHa
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, expectedHash := range hashesToRequest {
|
for _, expectedHash := range hashesToRequest {
|
||||||
message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout)
|
message, err := flow.dequeueIncomingMessageAndSkipInvs(common.DefaultTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -570,7 +458,7 @@ func (flow *handleIBDFlow) syncMissingBlockBodies(highHash *externalapi.DomainHa
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
virtualChangeSet, err := flow.Domain().Consensus().ValidateAndInsertBlock(block, false)
|
blockInsertionResult, err := flow.Domain().Consensus().ValidateAndInsertBlock(block, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, ruleerrors.ErrDuplicateBlock) {
|
if errors.Is(err, ruleerrors.ErrDuplicateBlock) {
|
||||||
log.Debugf("Skipping IBD Block %s as it has already been added to the DAG", blockHash)
|
log.Debugf("Skipping IBD Block %s as it has already been added to the DAG", blockHash)
|
||||||
@@ -578,62 +466,27 @@ func (flow *handleIBDFlow) syncMissingBlockBodies(highHash *externalapi.DomainHa
|
|||||||
}
|
}
|
||||||
return protocolerrors.ConvertToBanningProtocolErrorIfRuleError(err, "invalid block %s", blockHash)
|
return protocolerrors.ConvertToBanningProtocolErrorIfRuleError(err, "invalid block %s", blockHash)
|
||||||
}
|
}
|
||||||
err = flow.OnNewBlock(block, virtualChangeSet)
|
err = flow.OnNewBlock(block, blockInsertionResult)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
highestProcessedDAAScore = block.Header.DAAScore()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
progressReporter.reportProgress(len(hashesToRequest), highestProcessedDAAScore)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return flow.resolveVirtual(highestProcessedDAAScore)
|
return flow.Domain().Consensus().ResolveVirtual()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) banIfBlockIsHeaderOnly(block *externalapi.DomainBlock) error {
|
// dequeueIncomingMessageAndSkipInvs is a convenience method to be used during
|
||||||
if len(block.Transactions) == 0 {
|
// IBD. Inv messages are expected to arrive at any given moment, but should be
|
||||||
return protocolerrors.Errorf(true, "sent header of %s block where expected block with body",
|
// ignored while we're in IBD
|
||||||
consensushashing.BlockHash(block))
|
func (flow *handleRelayInvsFlow) dequeueIncomingMessageAndSkipInvs(timeout time.Duration) (appmessage.Message, error) {
|
||||||
}
|
for {
|
||||||
|
message, err := flow.incomingRoute.DequeueWithTimeout(timeout)
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (flow *handleIBDFlow) resolveVirtual(estimatedVirtualDAAScoreTarget uint64) error {
|
|
||||||
virtualDAAScoreStart, err := flow.Domain().Consensus().GetVirtualDAAScore()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; ; i++ {
|
|
||||||
if i%10 == 0 {
|
|
||||||
virtualDAAScore, err := flow.Domain().Consensus().GetVirtualDAAScore()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var percents int
|
|
||||||
if estimatedVirtualDAAScoreTarget-virtualDAAScoreStart <= 0 {
|
|
||||||
percents = 100
|
|
||||||
} else {
|
|
||||||
percents = int(float64(virtualDAAScore-virtualDAAScoreStart) / float64(estimatedVirtualDAAScoreTarget-virtualDAAScoreStart) * 100)
|
|
||||||
}
|
|
||||||
log.Infof("Resolving virtual. Estimated progress: %d%%", percents)
|
|
||||||
}
|
|
||||||
virtualChangeSet, isCompletelyResolved, err := flow.Domain().Consensus().ResolveVirtual()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if _, ok := message.(*appmessage.MsgInvRelayBlock); !ok {
|
||||||
err = flow.OnVirtualChange(virtualChangeSet)
|
return message, nil
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if isCompletelyResolved {
|
|
||||||
log.Infof("Resolved virtual")
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,16 +9,15 @@ import (
|
|||||||
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
|
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (flow *handleIBDFlow) ibdWithHeadersProof(highHash *externalapi.DomainHash, highBlockDAAScore uint64) error {
|
func (flow *handleRelayInvsFlow) ibdWithHeadersProof(highHash *externalapi.DomainHash) error {
|
||||||
err := flow.Domain().InitStagingConsensus()
|
err := flow.Domain().InitStagingConsensus()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = flow.downloadHeadersAndPruningUTXOSet(highHash, highBlockDAAScore)
|
err = flow.downloadHeadersAndPruningUTXOSet(highHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !flow.IsRecoverableError(err) {
|
if !flow.IsRecoverableError(err) {
|
||||||
return err
|
return err
|
||||||
@@ -37,15 +36,10 @@ func (flow *handleIBDFlow) ibdWithHeadersProof(highHash *externalapi.DomainHash,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = flow.OnPruningPointUTXOSetOverride()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) shouldSyncAndShouldDownloadHeadersProof(highBlock *externalapi.DomainBlock,
|
func (flow *handleRelayInvsFlow) shouldSyncAndShouldDownloadHeadersProof(highBlock *externalapi.DomainBlock,
|
||||||
highestSharedBlockFound bool) (shouldDownload, shouldSync bool, err error) {
|
highestSharedBlockFound bool) (shouldDownload, shouldSync bool, err error) {
|
||||||
|
|
||||||
if !highestSharedBlockFound {
|
if !highestSharedBlockFound {
|
||||||
@@ -64,7 +58,7 @@ func (flow *handleIBDFlow) shouldSyncAndShouldDownloadHeadersProof(highBlock *ex
|
|||||||
return false, true, nil
|
return false, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) checkIfHighHashHasMoreBlueWorkThanSelectedTipAndPruningDepthMoreBlueScore(highBlock *externalapi.DomainBlock) (bool, error) {
|
func (flow *handleRelayInvsFlow) checkIfHighHashHasMoreBlueWorkThanSelectedTipAndPruningDepthMoreBlueScore(highBlock *externalapi.DomainBlock) (bool, error) {
|
||||||
headersSelectedTip, err := flow.Domain().Consensus().GetHeadersSelectedTip()
|
headersSelectedTip, err := flow.Domain().Consensus().GetHeadersSelectedTip()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
@@ -82,13 +76,13 @@ func (flow *handleIBDFlow) checkIfHighHashHasMoreBlueWorkThanSelectedTipAndPruni
|
|||||||
return highBlock.Header.BlueWork().Cmp(headersSelectedTipInfo.BlueWork) > 0, nil
|
return highBlock.Header.BlueWork().Cmp(headersSelectedTipInfo.BlueWork) > 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) syncAndValidatePruningPointProof() (*externalapi.DomainHash, error) {
|
func (flow *handleRelayInvsFlow) syncAndValidatePruningPointProof() (*externalapi.DomainHash, error) {
|
||||||
log.Infof("Downloading the pruning point proof from %s", flow.peer)
|
log.Infof("Downloading the pruning point proof from %s", flow.peer)
|
||||||
err := flow.outgoingRoute.Enqueue(appmessage.NewMsgRequestPruningPointProof())
|
err := flow.outgoingRoute.Enqueue(appmessage.NewMsgRequestPruningPointProof())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
message, err := flow.incomingRoute.DequeueWithTimeout(10 * time.Minute)
|
message, err := flow.dequeueIncomingMessageAndSkipInvs(common.DefaultTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -114,7 +108,7 @@ func (flow *handleIBDFlow) syncAndValidatePruningPointProof() (*externalapi.Doma
|
|||||||
return consensushashing.HeaderHash(pruningPointProof.Headers[0][len(pruningPointProof.Headers[0])-1]), nil
|
return consensushashing.HeaderHash(pruningPointProof.Headers[0][len(pruningPointProof.Headers[0])-1]), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) downloadHeadersAndPruningUTXOSet(highHash *externalapi.DomainHash, highBlockDAAScore uint64) error {
|
func (flow *handleRelayInvsFlow) downloadHeadersAndPruningUTXOSet(highHash *externalapi.DomainHash) error {
|
||||||
proofPruningPoint, err := flow.syncAndValidatePruningPointProof()
|
proofPruningPoint, err := flow.syncAndValidatePruningPointProof()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -131,12 +125,12 @@ func (flow *handleIBDFlow) downloadHeadersAndPruningUTXOSet(highHash *externalap
|
|||||||
return protocolerrors.Errorf(true, "the genesis pruning point violates finality")
|
return protocolerrors.Errorf(true, "the genesis pruning point violates finality")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = flow.syncPruningPointFutureHeaders(flow.Domain().StagingConsensus(), proofPruningPoint, highHash, highBlockDAAScore)
|
err = flow.syncPruningPointFutureHeaders(flow.Domain().StagingConsensus(), proofPruningPoint, highHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Headers downloaded from peer %s", flow.peer)
|
log.Debugf("Headers downloaded from peer %s", flow.peer)
|
||||||
|
|
||||||
highHashInfo, err := flow.Domain().StagingConsensus().GetBlockInfo(highHash)
|
highHashInfo, err := flow.Domain().StagingConsensus().GetBlockInfo(highHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -165,7 +159,7 @@ func (flow *handleIBDFlow) downloadHeadersAndPruningUTXOSet(highHash *externalap
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) syncPruningPointsAndPruningPointAnticone(proofPruningPoint *externalapi.DomainHash) error {
|
func (flow *handleRelayInvsFlow) syncPruningPointsAndPruningPointAnticone(proofPruningPoint *externalapi.DomainHash) error {
|
||||||
log.Infof("Downloading the past pruning points and the pruning point anticone from %s", flow.peer)
|
log.Infof("Downloading the past pruning points and the pruning point anticone from %s", flow.peer)
|
||||||
err := flow.outgoingRoute.Enqueue(appmessage.NewMsgRequestPruningPointAndItsAnticone())
|
err := flow.outgoingRoute.Enqueue(appmessage.NewMsgRequestPruningPointAndItsAnticone())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -177,17 +171,6 @@ func (flow *handleIBDFlow) syncPruningPointsAndPruningPointAnticone(proofPruning
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
msgTrustedData, ok := message.(*appmessage.MsgTrustedData)
|
|
||||||
if !ok {
|
|
||||||
return protocolerrors.Errorf(true, "received unexpected message type. "+
|
|
||||||
"expected: %s, got: %s", appmessage.CmdTrustedData, message.Command())
|
|
||||||
}
|
|
||||||
|
|
||||||
pruningPointWithMetaData, done, err := flow.receiveBlockWithTrustedData()
|
pruningPointWithMetaData, done, err := flow.receiveBlockWithTrustedData()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -201,7 +184,7 @@ func (flow *handleIBDFlow) syncPruningPointsAndPruningPointAnticone(proofPruning
|
|||||||
return protocolerrors.Errorf(true, "first block with trusted data is not the pruning point")
|
return protocolerrors.Errorf(true, "first block with trusted data is not the pruning point")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = flow.processBlockWithTrustedData(flow.Domain().StagingConsensus(), pruningPointWithMetaData, msgTrustedData)
|
err = flow.processBlockWithTrustedData(flow.Domain().StagingConsensus(), pruningPointWithMetaData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -216,7 +199,7 @@ func (flow *handleIBDFlow) syncPruningPointsAndPruningPointAnticone(proofPruning
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
err = flow.processBlockWithTrustedData(flow.Domain().StagingConsensus(), blockWithTrustedData, msgTrustedData)
|
err = flow.processBlockWithTrustedData(flow.Domain().StagingConsensus(), blockWithTrustedData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -226,35 +209,21 @@ func (flow *handleIBDFlow) syncPruningPointsAndPruningPointAnticone(proofPruning
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) processBlockWithTrustedData(
|
func (flow *handleRelayInvsFlow) processBlockWithTrustedData(
|
||||||
consensus externalapi.Consensus, block *appmessage.MsgBlockWithTrustedDataV4, data *appmessage.MsgTrustedData) error {
|
consensus externalapi.Consensus, block *appmessage.MsgBlockWithTrustedData) error {
|
||||||
|
|
||||||
blockWithTrustedData := &externalapi.BlockWithTrustedData{
|
_, err := consensus.ValidateAndInsertBlockWithTrustedData(appmessage.BlockWithTrustedDataToDomainBlockWithTrustedData(block), false)
|
||||||
Block: appmessage.MsgBlockToDomainBlock(block.Block),
|
|
||||||
DAAWindow: make([]*externalapi.TrustedDataDataDAAHeader, 0, len(block.DAAWindowIndices)),
|
|
||||||
GHOSTDAGData: make([]*externalapi.BlockGHOSTDAGDataHashPair, 0, len(block.GHOSTDAGDataIndices)),
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, index := range block.DAAWindowIndices {
|
|
||||||
blockWithTrustedData.DAAWindow = append(blockWithTrustedData.DAAWindow, appmessage.TrustedDataDataDAABlockV4ToTrustedDataDataDAAHeader(data.DAAWindow[index]))
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, index := range block.GHOSTDAGDataIndices {
|
|
||||||
blockWithTrustedData.GHOSTDAGData = append(blockWithTrustedData.GHOSTDAGData, appmessage.GHOSTDAGHashPairToDomainGHOSTDAGHashPair(data.GHOSTDAGData[index]))
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := consensus.ValidateAndInsertBlockWithTrustedData(blockWithTrustedData, false)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) receiveBlockWithTrustedData() (*appmessage.MsgBlockWithTrustedDataV4, bool, error) {
|
func (flow *handleRelayInvsFlow) receiveBlockWithTrustedData() (*appmessage.MsgBlockWithTrustedData, bool, error) {
|
||||||
message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout)
|
message, err := flow.dequeueIncomingMessageAndSkipInvs(common.DefaultTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch downCastedMessage := message.(type) {
|
switch downCastedMessage := message.(type) {
|
||||||
case *appmessage.MsgBlockWithTrustedDataV4:
|
case *appmessage.MsgBlockWithTrustedData:
|
||||||
return downCastedMessage, false, nil
|
return downCastedMessage, false, nil
|
||||||
case *appmessage.MsgDoneBlocksWithTrustedData:
|
case *appmessage.MsgDoneBlocksWithTrustedData:
|
||||||
return nil, true, nil
|
return nil, true, nil
|
||||||
@@ -268,8 +237,8 @@ func (flow *handleIBDFlow) receiveBlockWithTrustedData() (*appmessage.MsgBlockWi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) receivePruningPoints() (*appmessage.MsgPruningPoints, error) {
|
func (flow *handleRelayInvsFlow) receivePruningPoints() (*appmessage.MsgPruningPoints, error) {
|
||||||
message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout)
|
message, err := flow.dequeueIncomingMessageAndSkipInvs(common.DefaultTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -284,7 +253,7 @@ func (flow *handleIBDFlow) receivePruningPoints() (*appmessage.MsgPruningPoints,
|
|||||||
return msgPruningPoints, nil
|
return msgPruningPoints, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) validateAndInsertPruningPoints(proofPruningPoint *externalapi.DomainHash) error {
|
func (flow *handleRelayInvsFlow) validateAndInsertPruningPoints(proofPruningPoint *externalapi.DomainHash) error {
|
||||||
currentPruningPoint, err := flow.Domain().Consensus().PruningPoint()
|
currentPruningPoint, err := flow.Domain().Consensus().PruningPoint()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -328,7 +297,7 @@ func (flow *handleIBDFlow) validateAndInsertPruningPoints(proofPruningPoint *ext
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) syncPruningPointUTXOSet(consensus externalapi.Consensus,
|
func (flow *handleRelayInvsFlow) syncPruningPointUTXOSet(consensus externalapi.Consensus,
|
||||||
pruningPoint *externalapi.DomainHash) (bool, error) {
|
pruningPoint *externalapi.DomainHash) (bool, error) {
|
||||||
|
|
||||||
log.Infof("Checking if the suggested pruning point %s is compatible to the node DAG", pruningPoint)
|
log.Infof("Checking if the suggested pruning point %s is compatible to the node DAG", pruningPoint)
|
||||||
@@ -356,7 +325,7 @@ func (flow *handleIBDFlow) syncPruningPointUTXOSet(consensus externalapi.Consens
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flow *handleIBDFlow) fetchMissingUTXOSet(consensus externalapi.Consensus, pruningPointHash *externalapi.DomainHash) (succeed bool, err error) {
|
func (flow *handleRelayInvsFlow) fetchMissingUTXOSet(consensus externalapi.Consensus, pruningPointHash *externalapi.DomainHash) (succeed bool, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
err := flow.Domain().StagingConsensus().ClearImportedPruningPointData()
|
err := flow.Domain().StagingConsensus().ClearImportedPruningPointData()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -386,5 +355,10 @@ func (flow *handleIBDFlow) fetchMissingUTXOSet(consensus externalapi.Consensus,
|
|||||||
return false, protocolerrors.ConvertToBanningProtocolErrorIfRuleError(err, "error with pruning point UTXO set")
|
return false, protocolerrors.ConvertToBanningProtocolErrorIfRuleError(err, "error with pruning point UTXO set")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = flow.OnPruningPointUTXOSetOverride()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package flowcontext
|
package blockrelay
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
@@ -13,15 +13,13 @@ type SharedRequestedBlocks struct {
|
|||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove removes a block from the set.
|
func (s *SharedRequestedBlocks) remove(hash *externalapi.DomainHash) {
|
||||||
func (s *SharedRequestedBlocks) Remove(hash *externalapi.DomainHash) {
|
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
delete(s.blocks, *hash)
|
delete(s.blocks, *hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveSet removes a set of blocks from the set.
|
func (s *SharedRequestedBlocks) removeSet(blockHashes map[externalapi.DomainHash]struct{}) {
|
||||||
func (s *SharedRequestedBlocks) RemoveSet(blockHashes map[externalapi.DomainHash]struct{}) {
|
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
for hash := range blockHashes {
|
for hash := range blockHashes {
|
||||||
@@ -29,8 +27,7 @@ func (s *SharedRequestedBlocks) RemoveSet(blockHashes map[externalapi.DomainHash
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddIfNotExists adds a block to the set if it doesn't exist yet.
|
func (s *SharedRequestedBlocks) addIfNotExists(hash *externalapi.DomainHash) (exists bool) {
|
||||||
func (s *SharedRequestedBlocks) AddIfNotExists(hash *externalapi.DomainHash) (exists bool) {
|
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
_, ok := s.blocks[*hash]
|
_, ok := s.blocks[*hash]
|
||||||
@@ -28,7 +28,7 @@ type HandleHandshakeContext interface {
|
|||||||
HandleError(err error, flowName string, isStopping *uint32, errChan chan<- error)
|
HandleError(err error, flowName string, isStopping *uint32, errChan chan<- error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleHandshake sets up the new_handshake protocol - It sends a version message and waits for an incoming
|
// HandleHandshake sets up the handshake protocol - It sends a version message and waits for an incoming
|
||||||
// version message, as well as a verack for the sent version
|
// version message, as well as a verack for the sent version
|
||||||
func HandleHandshake(context HandleHandshakeContext, netConnection *netadapter.NetConnection,
|
func HandleHandshake(context HandleHandshakeContext, netConnection *netadapter.NetConnection,
|
||||||
receiveVersionRoute *routerpkg.Route, sendVersionRoute *routerpkg.Route, outgoingRoute *routerpkg.Route,
|
receiveVersionRoute *routerpkg.Route, sendVersionRoute *routerpkg.Route, outgoingRoute *routerpkg.Route,
|
||||||
@@ -98,7 +98,7 @@ func HandleHandshake(context HandleHandshakeContext, netConnection *netadapter.N
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handshake is different from other flows, since in it should forward router.ErrRouteClosed to errChan
|
// Handshake is different from other flows, since in it should forward router.ErrRouteClosed to errChan
|
||||||
// Therefore we implement a separate handleError for new_handshake
|
// Therefore we implement a separate handleError for handshake
|
||||||
func handleError(err error, flowName string, isStopping *uint32, errChan chan error) {
|
func handleError(err error, flowName string, isStopping *uint32, errChan chan error) {
|
||||||
if errors.Is(err, routerpkg.ErrRouteClosed) {
|
if errors.Is(err, routerpkg.ErrRouteClosed) {
|
||||||
if atomic.AddUint32(isStopping, 1) == 1 {
|
if atomic.AddUint32(isStopping, 1) == 1 {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"github.com/kaspanet/kaspad/app/protocol/protocolerrors"
|
"github.com/kaspanet/kaspad/app/protocol/protocolerrors"
|
||||||
"github.com/kaspanet/kaspad/infrastructure/logger"
|
"github.com/kaspanet/kaspad/infrastructure/logger"
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -18,9 +17,7 @@ var (
|
|||||||
|
|
||||||
// minAcceptableProtocolVersion is the lowest protocol version that a
|
// minAcceptableProtocolVersion is the lowest protocol version that a
|
||||||
// connected peer may support.
|
// connected peer may support.
|
||||||
minAcceptableProtocolVersion = uint32(4)
|
minAcceptableProtocolVersion = appmessage.ProtocolVersion
|
||||||
|
|
||||||
maxAcceptableProtocolVersion = uint32(4)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type receiveVersionFlow struct {
|
type receiveVersionFlow struct {
|
||||||
@@ -100,12 +97,7 @@ func (flow *receiveVersionFlow) start() (*appmessage.NetAddress, error) {
|
|||||||
return nil, protocolerrors.New(false, "incompatible subnetworks")
|
return nil, protocolerrors.New(false, "incompatible subnetworks")
|
||||||
}
|
}
|
||||||
|
|
||||||
if flow.Config().ProtocolVersion > maxAcceptableProtocolVersion {
|
flow.peer.UpdateFieldsFromMsgVersion(msgVersion)
|
||||||
return nil, errors.Errorf("%d is a non existing protocol version", flow.Config().ProtocolVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
maxProtocolVersion := flow.Config().ProtocolVersion
|
|
||||||
flow.peer.UpdateFieldsFromMsgVersion(msgVersion, maxProtocolVersion)
|
|
||||||
err = flow.outgoingRoute.Enqueue(appmessage.NewMsgVerAck())
|
err = flow.outgoingRoute.Enqueue(appmessage.NewMsgVerAck())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"github.com/kaspanet/kaspad/infrastructure/logger"
|
"github.com/kaspanet/kaspad/infrastructure/logger"
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
||||||
"github.com/kaspanet/kaspad/version"
|
"github.com/kaspanet/kaspad/version"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -57,18 +56,15 @@ func (flow *sendVersionFlow) start() error {
|
|||||||
// Version message.
|
// Version message.
|
||||||
localAddress := flow.AddressManager().BestLocalAddress(flow.peer.Connection().NetAddress())
|
localAddress := flow.AddressManager().BestLocalAddress(flow.peer.Connection().NetAddress())
|
||||||
subnetworkID := flow.Config().SubnetworkID
|
subnetworkID := flow.Config().SubnetworkID
|
||||||
if flow.Config().ProtocolVersion < minAcceptableProtocolVersion {
|
|
||||||
return errors.Errorf("configured protocol version %d is obsolete", flow.Config().ProtocolVersion)
|
|
||||||
}
|
|
||||||
msg := appmessage.NewMsgVersion(localAddress, flow.NetAdapter().ID(),
|
msg := appmessage.NewMsgVersion(localAddress, flow.NetAdapter().ID(),
|
||||||
flow.Config().ActiveNetParams.Name, subnetworkID, flow.Config().ProtocolVersion)
|
flow.Config().ActiveNetParams.Name, subnetworkID)
|
||||||
msg.AddUserAgent(userAgentName, userAgentVersion, flow.Config().UserAgentComments...)
|
msg.AddUserAgent(userAgentName, userAgentVersion, flow.Config().UserAgentComments...)
|
||||||
|
|
||||||
// Advertise the services flag
|
// Advertise the services flag
|
||||||
msg.Services = defaultServices
|
msg.Services = defaultServices
|
||||||
|
|
||||||
// Advertise our max supported protocol version.
|
// Advertise our max supported protocol version.
|
||||||
msg.ProtocolVersion = flow.Config().ProtocolVersion
|
msg.ProtocolVersion = appmessage.ProtocolVersion
|
||||||
|
|
||||||
// Advertise if inv messages for transactions are desired.
|
// Advertise if inv messages for transactions are desired.
|
||||||
msg.DisableRelayTx = flow.Config().BlocksOnly
|
msg.DisableRelayTx = flow.Config().BlocksOnly
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
package ready
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/logger"
|
|
||||||
"github.com/kaspanet/kaspad/util/panics"
|
|
||||||
)
|
|
||||||
|
|
||||||
var log = logger.RegisterSubSystem("PROT")
|
|
||||||
var spawn = panics.GoroutineWrapperFunc(log)
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
package ready
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/app/protocol/common"
|
|
||||||
"sync/atomic"
|
|
||||||
|
|
||||||
peerpkg "github.com/kaspanet/kaspad/app/protocol/peer"
|
|
||||||
"github.com/kaspanet/kaspad/app/protocol/protocolerrors"
|
|
||||||
routerpkg "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleReady notify the other peer that peer is ready for messages, and wait for the other peer
|
|
||||||
// to send a ready message before start running the flows.
|
|
||||||
func HandleReady(incomingRoute *routerpkg.Route, outgoingRoute *routerpkg.Route,
|
|
||||||
peer *peerpkg.Peer,
|
|
||||||
) error {
|
|
||||||
|
|
||||||
log.Debugf("Sending ready message to %s", peer)
|
|
||||||
|
|
||||||
isStopping := uint32(0)
|
|
||||||
err := outgoingRoute.Enqueue(appmessage.NewMsgReady())
|
|
||||||
if err != nil {
|
|
||||||
return handleError(err, "HandleReady", &isStopping)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = incomingRoute.DequeueWithTimeout(common.DefaultTimeout)
|
|
||||||
if err != nil {
|
|
||||||
return handleError(err, "HandleReady", &isStopping)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("Got ready message from %s", peer)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ready is different from other flows, since in it should forward router.ErrRouteClosed to errChan
|
|
||||||
// Therefore we implement a separate handleError for 'ready'
|
|
||||||
func handleError(err error, flowName string, isStopping *uint32) error {
|
|
||||||
if errors.Is(err, routerpkg.ErrRouteClosed) {
|
|
||||||
if atomic.AddUint32(isStopping, 1) == 1 {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if protocolErr := (protocolerrors.ProtocolError{}); errors.As(err, &protocolErr) {
|
|
||||||
log.Errorf("Ready protocol error from %s: %s", flowName, err)
|
|
||||||
if atomic.AddUint32(isStopping, 1) == 1 {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
package testing
|
package testing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/app/protocol/flows/v4/addressexchange"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
"github.com/kaspanet/kaspad/app/appmessage"
|
||||||
|
"github.com/kaspanet/kaspad/app/protocol/flows/addressexchange"
|
||||||
peerpkg "github.com/kaspanet/kaspad/app/protocol/peer"
|
peerpkg "github.com/kaspanet/kaspad/app/protocol/peer"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus"
|
"github.com/kaspanet/kaspad/domain/consensus"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
|
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
|
||||||
@@ -3,7 +3,6 @@ package transactionrelay
|
|||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
"github.com/kaspanet/kaspad/app/appmessage"
|
||||||
"github.com/kaspanet/kaspad/app/protocol/common"
|
"github.com/kaspanet/kaspad/app/protocol/common"
|
||||||
"github.com/kaspanet/kaspad/app/protocol/flowcontext"
|
|
||||||
"github.com/kaspanet/kaspad/app/protocol/protocolerrors"
|
"github.com/kaspanet/kaspad/app/protocol/protocolerrors"
|
||||||
"github.com/kaspanet/kaspad/domain"
|
"github.com/kaspanet/kaspad/domain"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
@@ -19,10 +18,9 @@ import (
|
|||||||
type TransactionsRelayContext interface {
|
type TransactionsRelayContext interface {
|
||||||
NetAdapter() *netadapter.NetAdapter
|
NetAdapter() *netadapter.NetAdapter
|
||||||
Domain() domain.Domain
|
Domain() domain.Domain
|
||||||
SharedRequestedTransactions() *flowcontext.SharedRequestedTransactions
|
SharedRequestedTransactions() *SharedRequestedTransactions
|
||||||
OnTransactionAddedToMempool()
|
OnTransactionAddedToMempool()
|
||||||
EnqueueTransactionIDsForPropagation(transactionIDs []*externalapi.DomainTransactionID) error
|
EnqueueTransactionIDsForPropagation(transactionIDs []*externalapi.DomainTransactionID) error
|
||||||
IsIBDRunning() bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type handleRelayedTransactionsFlow struct {
|
type handleRelayedTransactionsFlow struct {
|
||||||
@@ -50,10 +48,6 @@ func (flow *handleRelayedTransactionsFlow) start() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if flow.IsIBDRunning() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
requestedIDs, err := flow.requestInvTransactions(inv)
|
requestedIDs, err := flow.requestInvTransactions(inv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -74,7 +68,7 @@ func (flow *handleRelayedTransactionsFlow) requestInvTransactions(
|
|||||||
if flow.isKnownTransaction(txID) {
|
if flow.isKnownTransaction(txID) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
exists := flow.SharedRequestedTransactions().AddIfNotExists(txID)
|
exists := flow.SharedRequestedTransactions().addIfNotExists(txID)
|
||||||
if exists {
|
if exists {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -88,7 +82,7 @@ func (flow *handleRelayedTransactionsFlow) requestInvTransactions(
|
|||||||
msgGetTransactions := appmessage.NewMsgRequestTransactions(idsToRequest)
|
msgGetTransactions := appmessage.NewMsgRequestTransactions(idsToRequest)
|
||||||
err = flow.outgoingRoute.Enqueue(msgGetTransactions)
|
err = flow.outgoingRoute.Enqueue(msgGetTransactions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
flow.SharedRequestedTransactions().RemoveMany(idsToRequest)
|
flow.SharedRequestedTransactions().removeMany(idsToRequest)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return idsToRequest, nil
|
return idsToRequest, nil
|
||||||
@@ -157,7 +151,7 @@ func (flow *handleRelayedTransactionsFlow) readMsgTxOrNotFound() (
|
|||||||
func (flow *handleRelayedTransactionsFlow) receiveTransactions(requestedTransactions []*externalapi.DomainTransactionID) error {
|
func (flow *handleRelayedTransactionsFlow) receiveTransactions(requestedTransactions []*externalapi.DomainTransactionID) error {
|
||||||
// In case the function returns earlier than expected, we want to make sure sharedRequestedTransactions is
|
// In case the function returns earlier than expected, we want to make sure sharedRequestedTransactions is
|
||||||
// clean from any pending transactions.
|
// clean from any pending transactions.
|
||||||
defer flow.SharedRequestedTransactions().RemoveMany(requestedTransactions)
|
defer flow.SharedRequestedTransactions().removeMany(requestedTransactions)
|
||||||
for _, expectedID := range requestedTransactions {
|
for _, expectedID := range requestedTransactions {
|
||||||
msgTx, msgTxNotFound, err := flow.readMsgTxOrNotFound()
|
msgTx, msgTxNotFound, err := flow.readMsgTxOrNotFound()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -2,11 +2,10 @@ package transactionrelay_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/kaspanet/kaspad/app/protocol/flowcontext"
|
|
||||||
"github.com/kaspanet/kaspad/app/protocol/flows/v4/transactionrelay"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/app/protocol/flows/transactionrelay"
|
||||||
"github.com/kaspanet/kaspad/app/protocol/protocolerrors"
|
"github.com/kaspanet/kaspad/app/protocol/protocolerrors"
|
||||||
"github.com/kaspanet/kaspad/domain"
|
"github.com/kaspanet/kaspad/domain"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus"
|
"github.com/kaspanet/kaspad/domain/consensus"
|
||||||
@@ -25,7 +24,7 @@ import (
|
|||||||
type mocTransactionsRelayContext struct {
|
type mocTransactionsRelayContext struct {
|
||||||
netAdapter *netadapter.NetAdapter
|
netAdapter *netadapter.NetAdapter
|
||||||
domain domain.Domain
|
domain domain.Domain
|
||||||
sharedRequestedTransactions *flowcontext.SharedRequestedTransactions
|
sharedRequestedTransactions *transactionrelay.SharedRequestedTransactions
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mocTransactionsRelayContext) NetAdapter() *netadapter.NetAdapter {
|
func (m *mocTransactionsRelayContext) NetAdapter() *netadapter.NetAdapter {
|
||||||
@@ -36,7 +35,7 @@ func (m *mocTransactionsRelayContext) Domain() domain.Domain {
|
|||||||
return m.domain
|
return m.domain
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mocTransactionsRelayContext) SharedRequestedTransactions() *flowcontext.SharedRequestedTransactions {
|
func (m *mocTransactionsRelayContext) SharedRequestedTransactions() *transactionrelay.SharedRequestedTransactions {
|
||||||
return m.sharedRequestedTransactions
|
return m.sharedRequestedTransactions
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,10 +46,6 @@ func (m *mocTransactionsRelayContext) EnqueueTransactionIDsForPropagation(transa
|
|||||||
func (m *mocTransactionsRelayContext) OnTransactionAddedToMempool() {
|
func (m *mocTransactionsRelayContext) OnTransactionAddedToMempool() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mocTransactionsRelayContext) IsIBDRunning() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestHandleRelayedTransactionsNotFound tests the flow of HandleRelayedTransactions when the peer doesn't
|
// TestHandleRelayedTransactionsNotFound tests the flow of HandleRelayedTransactions when the peer doesn't
|
||||||
// have the requested transactions in the mempool.
|
// have the requested transactions in the mempool.
|
||||||
func TestHandleRelayedTransactionsNotFound(t *testing.T) {
|
func TestHandleRelayedTransactionsNotFound(t *testing.T) {
|
||||||
@@ -65,7 +60,7 @@ func TestHandleRelayedTransactionsNotFound(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer teardown(false)
|
defer teardown(false)
|
||||||
|
|
||||||
sharedRequestedTransactions := flowcontext.NewSharedRequestedTransactions()
|
sharedRequestedTransactions := transactionrelay.NewSharedRequestedTransactions()
|
||||||
adapter, err := netadapter.NewNetAdapter(config.DefaultConfig())
|
adapter, err := netadapter.NewNetAdapter(config.DefaultConfig())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create a NetAdapter: %v", err)
|
t.Fatalf("Failed to create a NetAdapter: %v", err)
|
||||||
@@ -158,7 +153,7 @@ func TestOnClosedIncomingRoute(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer teardown(false)
|
defer teardown(false)
|
||||||
|
|
||||||
sharedRequestedTransactions := flowcontext.NewSharedRequestedTransactions()
|
sharedRequestedTransactions := transactionrelay.NewSharedRequestedTransactions()
|
||||||
adapter, err := netadapter.NewNetAdapter(config.DefaultConfig())
|
adapter, err := netadapter.NewNetAdapter(config.DefaultConfig())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to creat a NetAdapter : %v", err)
|
t.Fatalf("Failed to creat a NetAdapter : %v", err)
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
package transactionrelay_test
|
package transactionrelay_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/app/protocol/flowcontext"
|
|
||||||
"github.com/kaspanet/kaspad/app/protocol/flows/v4/transactionrelay"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
"github.com/kaspanet/kaspad/app/appmessage"
|
||||||
|
"github.com/kaspanet/kaspad/app/protocol/flows/transactionrelay"
|
||||||
"github.com/kaspanet/kaspad/domain"
|
"github.com/kaspanet/kaspad/domain"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus"
|
"github.com/kaspanet/kaspad/domain/consensus"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
@@ -32,7 +31,7 @@ func TestHandleRequestedTransactionsNotFound(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer teardown(false)
|
defer teardown(false)
|
||||||
|
|
||||||
sharedRequestedTransactions := flowcontext.NewSharedRequestedTransactions()
|
sharedRequestedTransactions := transactionrelay.NewSharedRequestedTransactions()
|
||||||
adapter, err := netadapter.NewNetAdapter(config.DefaultConfig())
|
adapter, err := netadapter.NewNetAdapter(config.DefaultConfig())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create a NetAdapter: %v", err)
|
t.Fatalf("Failed to create a NetAdapter: %v", err)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package flowcontext
|
package transactionrelay
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
@@ -13,15 +13,13 @@ type SharedRequestedTransactions struct {
|
|||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove removes a transaction from the set.
|
func (s *SharedRequestedTransactions) remove(txID *externalapi.DomainTransactionID) {
|
||||||
func (s *SharedRequestedTransactions) Remove(txID *externalapi.DomainTransactionID) {
|
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
delete(s.transactions, *txID)
|
delete(s.transactions, *txID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveMany removes a set of transactions from the set.
|
func (s *SharedRequestedTransactions) removeMany(txIDs []*externalapi.DomainTransactionID) {
|
||||||
func (s *SharedRequestedTransactions) RemoveMany(txIDs []*externalapi.DomainTransactionID) {
|
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
for _, txID := range txIDs {
|
for _, txID := range txIDs {
|
||||||
@@ -29,8 +27,7 @@ func (s *SharedRequestedTransactions) RemoveMany(txIDs []*externalapi.DomainTran
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddIfNotExists adds a transaction to the set if it doesn't exist yet.
|
func (s *SharedRequestedTransactions) addIfNotExists(txID *externalapi.DomainTransactionID) (exists bool) {
|
||||||
func (s *SharedRequestedTransactions) AddIfNotExists(txID *externalapi.DomainTransactionID) (exists bool) {
|
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
_, ok := s.transactions[*txID]
|
_, ok := s.transactions[*txID]
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
package blockrelay
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
peerpkg "github.com/kaspanet/kaspad/app/protocol/peer"
|
|
||||||
"github.com/kaspanet/kaspad/app/protocol/protocolerrors"
|
|
||||||
"github.com/kaspanet/kaspad/domain"
|
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/config"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
"sync/atomic"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PruningPointAndItsAnticoneRequestsContext is the interface for the context needed for the HandlePruningPointAndItsAnticoneRequests flow.
|
|
||||||
type PruningPointAndItsAnticoneRequestsContext interface {
|
|
||||||
Domain() domain.Domain
|
|
||||||
Config() *config.Config
|
|
||||||
}
|
|
||||||
|
|
||||||
var isBusy uint32
|
|
||||||
|
|
||||||
// HandlePruningPointAndItsAnticoneRequests listens to appmessage.MsgRequestPruningPointAndItsAnticone messages and sends
|
|
||||||
// the pruning point and its anticone to the requesting peer.
|
|
||||||
func HandlePruningPointAndItsAnticoneRequests(context PruningPointAndItsAnticoneRequestsContext, incomingRoute *router.Route,
|
|
||||||
outgoingRoute *router.Route, peer *peerpkg.Peer) error {
|
|
||||||
|
|
||||||
for {
|
|
||||||
err := func() error {
|
|
||||||
_, err := incomingRoute.Dequeue()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !atomic.CompareAndSwapUint32(&isBusy, 0, 1) {
|
|
||||||
return protocolerrors.Errorf(false, "node is busy with other pruning point anticone requests")
|
|
||||||
}
|
|
||||||
defer atomic.StoreUint32(&isBusy, 0)
|
|
||||||
|
|
||||||
log.Debugf("Got request for pruning point and its anticone from %s", peer)
|
|
||||||
|
|
||||||
pruningPointHeaders, err := context.Domain().Consensus().PruningPointHeaders()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
msgPruningPointHeaders := make([]*appmessage.MsgBlockHeader, len(pruningPointHeaders))
|
|
||||||
for i, header := range pruningPointHeaders {
|
|
||||||
msgPruningPointHeaders[i] = appmessage.DomainBlockHeaderToBlockHeader(header)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = outgoingRoute.Enqueue(appmessage.NewMsgPruningPoints(msgPruningPointHeaders))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
pointAndItsAnticone, err := context.Domain().Consensus().PruningPointAndItsAnticone()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
windowSize := context.Config().NetParams().DifficultyAdjustmentWindowSize
|
|
||||||
daaWindowBlocks := make([]*externalapi.TrustedDataDataDAAHeader, 0, windowSize)
|
|
||||||
daaWindowHashesToIndex := make(map[externalapi.DomainHash]int, windowSize)
|
|
||||||
trustedDataDAABlockIndexes := make(map[externalapi.DomainHash][]uint64)
|
|
||||||
|
|
||||||
ghostdagData := make([]*externalapi.BlockGHOSTDAGDataHashPair, 0)
|
|
||||||
ghostdagDataHashToIndex := make(map[externalapi.DomainHash]int)
|
|
||||||
trustedDataGHOSTDAGDataIndexes := make(map[externalapi.DomainHash][]uint64)
|
|
||||||
for _, blockHash := range pointAndItsAnticone {
|
|
||||||
blockDAAWindowHashes, err := context.Domain().Consensus().BlockDAAWindowHashes(blockHash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
trustedDataDAABlockIndexes[*blockHash] = make([]uint64, 0, windowSize)
|
|
||||||
for i, daaBlockHash := range blockDAAWindowHashes {
|
|
||||||
index, exists := daaWindowHashesToIndex[*daaBlockHash]
|
|
||||||
if !exists {
|
|
||||||
trustedDataDataDAAHeader, err := context.Domain().Consensus().TrustedDataDataDAAHeader(blockHash, daaBlockHash, uint64(i))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
daaWindowBlocks = append(daaWindowBlocks, trustedDataDataDAAHeader)
|
|
||||||
index = len(daaWindowBlocks) - 1
|
|
||||||
daaWindowHashesToIndex[*daaBlockHash] = index
|
|
||||||
}
|
|
||||||
|
|
||||||
trustedDataDAABlockIndexes[*blockHash] = append(trustedDataDAABlockIndexes[*blockHash], uint64(index))
|
|
||||||
}
|
|
||||||
|
|
||||||
ghostdagDataBlockHashes, err := context.Domain().Consensus().TrustedBlockAssociatedGHOSTDAGDataBlockHashes(blockHash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
trustedDataGHOSTDAGDataIndexes[*blockHash] = make([]uint64, 0, context.Config().NetParams().K)
|
|
||||||
for _, ghostdagDataBlockHash := range ghostdagDataBlockHashes {
|
|
||||||
index, exists := ghostdagDataHashToIndex[*ghostdagDataBlockHash]
|
|
||||||
if !exists {
|
|
||||||
data, err := context.Domain().Consensus().TrustedGHOSTDAGData(ghostdagDataBlockHash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
ghostdagData = append(ghostdagData, &externalapi.BlockGHOSTDAGDataHashPair{
|
|
||||||
Hash: ghostdagDataBlockHash,
|
|
||||||
GHOSTDAGData: data,
|
|
||||||
})
|
|
||||||
index = len(ghostdagData) - 1
|
|
||||||
ghostdagDataHashToIndex[*ghostdagDataBlockHash] = index
|
|
||||||
}
|
|
||||||
|
|
||||||
trustedDataGHOSTDAGDataIndexes[*blockHash] = append(trustedDataGHOSTDAGDataIndexes[*blockHash], uint64(index))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = outgoingRoute.Enqueue(appmessage.DomainTrustedDataToTrustedData(daaWindowBlocks, ghostdagData))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, blockHash := range pointAndItsAnticone {
|
|
||||||
block, err := context.Domain().Consensus().GetBlock(blockHash)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = outgoingRoute.Enqueue(appmessage.DomainBlockWithTrustedDataToBlockWithTrustedDataV4(block, trustedDataDAABlockIndexes[*blockHash], trustedDataGHOSTDAGDataIndexes[*blockHash]))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = outgoingRoute.Enqueue(appmessage.NewMsgDoneBlocksWithTrustedData())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("Sent pruning point and its anticone to %s", peer)
|
|
||||||
return nil
|
|
||||||
}()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
package blockrelay
|
|
||||||
|
|
||||||
type ibdProgressReporter struct {
|
|
||||||
lowDAAScore uint64
|
|
||||||
highDAAScore uint64
|
|
||||||
objectName string
|
|
||||||
totalDAAScoreDifference uint64
|
|
||||||
lastReportedProgressPercent int
|
|
||||||
processed int
|
|
||||||
}
|
|
||||||
|
|
||||||
func newIBDProgressReporter(lowDAAScore uint64, highDAAScore uint64, objectName string) *ibdProgressReporter {
|
|
||||||
return &ibdProgressReporter{
|
|
||||||
lowDAAScore: lowDAAScore,
|
|
||||||
highDAAScore: highDAAScore,
|
|
||||||
objectName: objectName,
|
|
||||||
totalDAAScoreDifference: highDAAScore - lowDAAScore,
|
|
||||||
lastReportedProgressPercent: 0,
|
|
||||||
processed: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ipr *ibdProgressReporter) reportProgress(processedDelta int, highestProcessedDAAScore uint64) {
|
|
||||||
ipr.processed += processedDelta
|
|
||||||
|
|
||||||
relativeDAAScore := highestProcessedDAAScore - ipr.lowDAAScore
|
|
||||||
progressPercent := int((float64(relativeDAAScore) / float64(ipr.totalDAAScoreDifference)) * 100)
|
|
||||||
if progressPercent > ipr.lastReportedProgressPercent {
|
|
||||||
log.Infof("IBD: Processed %d %s (%d%%)", ipr.processed, ipr.objectName, progressPercent)
|
|
||||||
ipr.lastReportedProgressPercent = progressPercent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,194 +0,0 @@
|
|||||||
package v4
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/app/protocol/common"
|
|
||||||
"github.com/kaspanet/kaspad/app/protocol/flowcontext"
|
|
||||||
"github.com/kaspanet/kaspad/app/protocol/flows/v4/addressexchange"
|
|
||||||
"github.com/kaspanet/kaspad/app/protocol/flows/v4/blockrelay"
|
|
||||||
"github.com/kaspanet/kaspad/app/protocol/flows/v4/ping"
|
|
||||||
"github.com/kaspanet/kaspad/app/protocol/flows/v4/rejects"
|
|
||||||
"github.com/kaspanet/kaspad/app/protocol/flows/v4/transactionrelay"
|
|
||||||
peerpkg "github.com/kaspanet/kaspad/app/protocol/peer"
|
|
||||||
routerpkg "github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
)
|
|
||||||
|
|
||||||
type protocolManager interface {
|
|
||||||
RegisterFlow(name string, router *routerpkg.Router, messageTypes []appmessage.MessageCommand, isStopping *uint32,
|
|
||||||
errChan chan error, initializeFunc common.FlowInitializeFunc) *common.Flow
|
|
||||||
RegisterOneTimeFlow(name string, router *routerpkg.Router, messageTypes []appmessage.MessageCommand,
|
|
||||||
isStopping *uint32, stopChan chan error, initializeFunc common.FlowInitializeFunc) *common.Flow
|
|
||||||
RegisterFlowWithCapacity(name string, capacity int, router *routerpkg.Router,
|
|
||||||
messageTypes []appmessage.MessageCommand, isStopping *uint32,
|
|
||||||
errChan chan error, initializeFunc common.FlowInitializeFunc) *common.Flow
|
|
||||||
Context() *flowcontext.FlowContext
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register is used in order to register all the protocol flows to the given router.
|
|
||||||
func Register(m protocolManager, router *routerpkg.Router, errChan chan error, isStopping *uint32) (flows []*common.Flow) {
|
|
||||||
flows = registerAddressFlows(m, router, isStopping, errChan)
|
|
||||||
flows = append(flows, registerBlockRelayFlows(m, router, isStopping, errChan)...)
|
|
||||||
flows = append(flows, registerPingFlows(m, router, isStopping, errChan)...)
|
|
||||||
flows = append(flows, registerTransactionRelayFlow(m, router, isStopping, errChan)...)
|
|
||||||
flows = append(flows, registerRejectsFlow(m, router, isStopping, errChan)...)
|
|
||||||
|
|
||||||
return flows
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerAddressFlows(m protocolManager, router *routerpkg.Router, isStopping *uint32, errChan chan error) []*common.Flow {
|
|
||||||
outgoingRoute := router.OutgoingRoute()
|
|
||||||
|
|
||||||
return []*common.Flow{
|
|
||||||
m.RegisterFlow("SendAddresses", router, []appmessage.MessageCommand{appmessage.CmdRequestAddresses}, isStopping, errChan,
|
|
||||||
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
|
||||||
return addressexchange.SendAddresses(m.Context(), incomingRoute, outgoingRoute)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
m.RegisterOneTimeFlow("ReceiveAddresses", router, []appmessage.MessageCommand{appmessage.CmdAddresses}, isStopping, errChan,
|
|
||||||
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
|
||||||
return addressexchange.ReceiveAddresses(m.Context(), incomingRoute, outgoingRoute, peer)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerBlockRelayFlows(m protocolManager, router *routerpkg.Router, isStopping *uint32, errChan chan error) []*common.Flow {
|
|
||||||
outgoingRoute := router.OutgoingRoute()
|
|
||||||
|
|
||||||
return []*common.Flow{
|
|
||||||
m.RegisterOneTimeFlow("SendVirtualSelectedParentInv", router, []appmessage.MessageCommand{},
|
|
||||||
isStopping, errChan, func(route *routerpkg.Route, peer *peerpkg.Peer) error {
|
|
||||||
return blockrelay.SendVirtualSelectedParentInv(m.Context(), outgoingRoute, peer)
|
|
||||||
}),
|
|
||||||
|
|
||||||
m.RegisterFlow("HandleRelayInvs", router, []appmessage.MessageCommand{
|
|
||||||
appmessage.CmdInvRelayBlock, appmessage.CmdBlock, appmessage.CmdBlockLocator,
|
|
||||||
},
|
|
||||||
isStopping, errChan, func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
|
||||||
return blockrelay.HandleRelayInvs(m.Context(), incomingRoute,
|
|
||||||
outgoingRoute, peer)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
m.RegisterFlow("HandleIBD", router, []appmessage.MessageCommand{
|
|
||||||
appmessage.CmdDoneHeaders, appmessage.CmdUnexpectedPruningPoint, appmessage.CmdPruningPointUTXOSetChunk,
|
|
||||||
appmessage.CmdBlockHeaders, appmessage.CmdIBDBlockLocatorHighestHash, appmessage.CmdBlockWithTrustedDataV4,
|
|
||||||
appmessage.CmdDoneBlocksWithTrustedData, appmessage.CmdIBDBlockLocatorHighestHashNotFound,
|
|
||||||
appmessage.CmdDonePruningPointUTXOSetChunks, appmessage.CmdIBDBlock, appmessage.CmdPruningPoints,
|
|
||||||
appmessage.CmdPruningPointProof,
|
|
||||||
appmessage.CmdTrustedData,
|
|
||||||
},
|
|
||||||
isStopping, errChan, func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
|
||||||
return blockrelay.HandleIBD(m.Context(), incomingRoute,
|
|
||||||
outgoingRoute, peer)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
m.RegisterFlow("HandleRelayBlockRequests", router, []appmessage.MessageCommand{appmessage.CmdRequestRelayBlocks}, isStopping, errChan,
|
|
||||||
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
|
||||||
return blockrelay.HandleRelayBlockRequests(m.Context(), incomingRoute, outgoingRoute, peer)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
m.RegisterFlow("HandleRequestBlockLocator", router,
|
|
||||||
[]appmessage.MessageCommand{appmessage.CmdRequestBlockLocator}, isStopping, errChan,
|
|
||||||
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
|
||||||
return blockrelay.HandleRequestBlockLocator(m.Context(), incomingRoute, outgoingRoute)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
m.RegisterFlow("HandleRequestHeaders", router,
|
|
||||||
[]appmessage.MessageCommand{appmessage.CmdRequestHeaders, appmessage.CmdRequestNextHeaders}, isStopping, errChan,
|
|
||||||
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
|
||||||
return blockrelay.HandleRequestHeaders(m.Context(), incomingRoute, outgoingRoute, peer)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
m.RegisterFlow("HandleIBDBlockRequests", router,
|
|
||||||
[]appmessage.MessageCommand{appmessage.CmdRequestIBDBlocks}, isStopping, errChan,
|
|
||||||
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
|
||||||
return blockrelay.HandleIBDBlockRequests(m.Context(), incomingRoute, outgoingRoute)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
m.RegisterFlow("HandleRequestPruningPointUTXOSet", router,
|
|
||||||
[]appmessage.MessageCommand{appmessage.CmdRequestPruningPointUTXOSet,
|
|
||||||
appmessage.CmdRequestNextPruningPointUTXOSetChunk}, isStopping, errChan,
|
|
||||||
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
|
||||||
return blockrelay.HandleRequestPruningPointUTXOSet(m.Context(), incomingRoute, outgoingRoute)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
m.RegisterFlow("HandlePruningPointAndItsAnticoneRequests", router,
|
|
||||||
[]appmessage.MessageCommand{appmessage.CmdRequestPruningPointAndItsAnticone}, isStopping, errChan,
|
|
||||||
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
|
||||||
return blockrelay.HandlePruningPointAndItsAnticoneRequests(m.Context(), incomingRoute, outgoingRoute, peer)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
m.RegisterFlow("HandleIBDBlockLocator", router,
|
|
||||||
[]appmessage.MessageCommand{appmessage.CmdIBDBlockLocator}, isStopping, errChan,
|
|
||||||
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
|
||||||
return blockrelay.HandleIBDBlockLocator(m.Context(), incomingRoute, outgoingRoute, peer)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
m.RegisterFlow("HandlePruningPointProofRequests", router,
|
|
||||||
[]appmessage.MessageCommand{appmessage.CmdRequestPruningPointProof}, isStopping, errChan,
|
|
||||||
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
|
||||||
return blockrelay.HandlePruningPointProofRequests(m.Context(), incomingRoute, outgoingRoute, peer)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerPingFlows(m protocolManager, router *routerpkg.Router, isStopping *uint32, errChan chan error) []*common.Flow {
|
|
||||||
outgoingRoute := router.OutgoingRoute()
|
|
||||||
|
|
||||||
return []*common.Flow{
|
|
||||||
m.RegisterFlow("ReceivePings", router, []appmessage.MessageCommand{appmessage.CmdPing}, isStopping, errChan,
|
|
||||||
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
|
||||||
return ping.ReceivePings(m.Context(), incomingRoute, outgoingRoute)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
m.RegisterFlow("SendPings", router, []appmessage.MessageCommand{appmessage.CmdPong}, isStopping, errChan,
|
|
||||||
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
|
||||||
return ping.SendPings(m.Context(), incomingRoute, outgoingRoute, peer)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerTransactionRelayFlow(m protocolManager, router *routerpkg.Router, isStopping *uint32, errChan chan error) []*common.Flow {
|
|
||||||
outgoingRoute := router.OutgoingRoute()
|
|
||||||
|
|
||||||
return []*common.Flow{
|
|
||||||
m.RegisterFlowWithCapacity("HandleRelayedTransactions", 10_000, router,
|
|
||||||
[]appmessage.MessageCommand{appmessage.CmdInvTransaction, appmessage.CmdTx, appmessage.CmdTransactionNotFound}, isStopping, errChan,
|
|
||||||
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
|
||||||
return transactionrelay.HandleRelayedTransactions(m.Context(), incomingRoute, outgoingRoute)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
m.RegisterFlow("HandleRequestTransactions", router,
|
|
||||||
[]appmessage.MessageCommand{appmessage.CmdRequestTransactions}, isStopping, errChan,
|
|
||||||
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
|
||||||
return transactionrelay.HandleRequestedTransactions(m.Context(), incomingRoute, outgoingRoute)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerRejectsFlow(m protocolManager, router *routerpkg.Router, isStopping *uint32, errChan chan error) []*common.Flow {
|
|
||||||
outgoingRoute := router.OutgoingRoute()
|
|
||||||
|
|
||||||
return []*common.Flow{
|
|
||||||
m.RegisterFlow("HandleRejects", router,
|
|
||||||
[]appmessage.MessageCommand{appmessage.CmdReject}, isStopping, errChan,
|
|
||||||
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
|
||||||
return rejects.HandleRejects(m.Context(), incomingRoute, outgoingRoute)
|
|
||||||
},
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,6 @@ package protocol
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/kaspanet/kaspad/app/protocol/common"
|
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
@@ -72,16 +71,11 @@ func (m *Manager) AddBlock(block *externalapi.DomainBlock) error {
|
|||||||
return m.context.AddBlock(block)
|
return m.context.AddBlock(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Context returns the manager's flow context
|
func (m *Manager) runFlows(flows []*flow, peer *peerpkg.Peer, errChan <-chan error, flowsWaitGroup *sync.WaitGroup) error {
|
||||||
func (m *Manager) Context() *flowcontext.FlowContext {
|
|
||||||
return m.context
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Manager) runFlows(flows []*common.Flow, peer *peerpkg.Peer, errChan <-chan error, flowsWaitGroup *sync.WaitGroup) error {
|
|
||||||
flowsWaitGroup.Add(len(flows))
|
flowsWaitGroup.Add(len(flows))
|
||||||
for _, flow := range flows {
|
for _, flow := range flows {
|
||||||
executeFunc := flow.ExecuteFunc // extract to new variable so that it's not overwritten
|
executeFunc := flow.executeFunc // extract to new variable so that it's not overwritten
|
||||||
spawn(fmt.Sprintf("flow-%s", flow.Name), func() {
|
spawn(fmt.Sprintf("flow-%s", flow.name), func() {
|
||||||
executeFunc(peer)
|
executeFunc(peer)
|
||||||
flowsWaitGroup.Done()
|
flowsWaitGroup.Done()
|
||||||
})
|
})
|
||||||
@@ -90,11 +84,6 @@ func (m *Manager) runFlows(flows []*common.Flow, peer *peerpkg.Peer, errChan <-c
|
|||||||
return <-errChan
|
return <-errChan
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetOnVirtualChange sets the onVirtualChangeHandler handler
|
|
||||||
func (m *Manager) SetOnVirtualChange(onVirtualChangeHandler flowcontext.OnVirtualChangeHandler) {
|
|
||||||
m.context.SetOnVirtualChangeHandler(onVirtualChangeHandler)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetOnBlockAddedToDAGHandler sets the onBlockAddedToDAG handler
|
// SetOnBlockAddedToDAGHandler sets the onBlockAddedToDAG handler
|
||||||
func (m *Manager) SetOnBlockAddedToDAGHandler(onBlockAddedToDAGHandler flowcontext.OnBlockAddedToDAGHandler) {
|
func (m *Manager) SetOnBlockAddedToDAGHandler(onBlockAddedToDAGHandler flowcontext.OnBlockAddedToDAGHandler) {
|
||||||
m.context.SetOnBlockAddedToDAGHandler(onBlockAddedToDAGHandler)
|
m.context.SetOnBlockAddedToDAGHandler(onBlockAddedToDAGHandler)
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ import (
|
|||||||
"github.com/kaspanet/kaspad/util/mstime"
|
"github.com/kaspanet/kaspad/util/mstime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// maxProtocolVersion version is the maximum supported protocol
|
||||||
|
// version this kaspad node supports
|
||||||
|
const maxProtocolVersion = 1
|
||||||
|
|
||||||
// Peer holds data about a peer.
|
// Peer holds data about a peer.
|
||||||
type Peer struct {
|
type Peer struct {
|
||||||
connection *netadapter.NetConnection
|
connection *netadapter.NetConnection
|
||||||
@@ -31,8 +35,6 @@ type Peer struct {
|
|||||||
lastPingNonce uint64 // The nonce of the last ping we sent
|
lastPingNonce uint64 // The nonce of the last ping we sent
|
||||||
lastPingTime time.Time // Time we sent last ping
|
lastPingTime time.Time // Time we sent last ping
|
||||||
lastPingDuration time.Duration // Time for last ping to return
|
lastPingDuration time.Duration // Time for last ping to return
|
||||||
|
|
||||||
ibdRequestChannel chan *externalapi.DomainBlock // A channel used to communicate IBD requests between flows
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new Peer
|
// New returns a new Peer
|
||||||
@@ -40,7 +42,6 @@ func New(connection *netadapter.NetConnection) *Peer {
|
|||||||
return &Peer{
|
return &Peer{
|
||||||
connection: connection,
|
connection: connection,
|
||||||
connectionStarted: time.Now(),
|
connectionStarted: time.Now(),
|
||||||
ibdRequestChannel: make(chan *externalapi.DomainBlock),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,11 +76,6 @@ func (p *Peer) AdvertisedProtocolVersion() uint32 {
|
|||||||
return p.advertisedProtocolVerion
|
return p.advertisedProtocolVerion
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProtocolVersion returns the protocol version which is used when communicating with the peer.
|
|
||||||
func (p *Peer) ProtocolVersion() uint32 {
|
|
||||||
return p.protocolVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
// TimeConnected returns the time since the connection to this been has been started.
|
// TimeConnected returns the time since the connection to this been has been started.
|
||||||
func (p *Peer) TimeConnected() time.Duration {
|
func (p *Peer) TimeConnected() time.Duration {
|
||||||
return time.Since(p.connectionStarted)
|
return time.Since(p.connectionStarted)
|
||||||
@@ -91,7 +87,7 @@ func (p *Peer) IsOutbound() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateFieldsFromMsgVersion updates the peer with the data from the version message.
|
// UpdateFieldsFromMsgVersion updates the peer with the data from the version message.
|
||||||
func (p *Peer) UpdateFieldsFromMsgVersion(msg *appmessage.MsgVersion, maxProtocolVersion uint32) {
|
func (p *Peer) UpdateFieldsFromMsgVersion(msg *appmessage.MsgVersion) {
|
||||||
// Negotiate the protocol version.
|
// Negotiate the protocol version.
|
||||||
p.advertisedProtocolVerion = msg.ProtocolVersion
|
p.advertisedProtocolVerion = msg.ProtocolVersion
|
||||||
p.protocolVersion = mathUtil.MinUint32(maxProtocolVersion, p.advertisedProtocolVerion)
|
p.protocolVersion = mathUtil.MinUint32(maxProtocolVersion, p.advertisedProtocolVerion)
|
||||||
@@ -146,8 +142,3 @@ func (p *Peer) LastPingDuration() time.Duration {
|
|||||||
|
|
||||||
return p.lastPingDuration
|
return p.lastPingDuration
|
||||||
}
|
}
|
||||||
|
|
||||||
// IBDRequestChannel returns the channel used in order to communicate an IBD request between peer flows
|
|
||||||
func (p *Peer) IBDRequestChannel() chan *externalapi.DomainBlock {
|
|
||||||
return p.ibdRequestChannel
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
package protocol
|
package protocol
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/app/protocol/common"
|
|
||||||
"github.com/kaspanet/kaspad/app/protocol/flows/ready"
|
|
||||||
v4 "github.com/kaspanet/kaspad/app/protocol/flows/v4"
|
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
"github.com/kaspanet/kaspad/app/appmessage"
|
||||||
|
"github.com/kaspanet/kaspad/app/protocol/flows/addressexchange"
|
||||||
|
"github.com/kaspanet/kaspad/app/protocol/flows/blockrelay"
|
||||||
"github.com/kaspanet/kaspad/app/protocol/flows/handshake"
|
"github.com/kaspanet/kaspad/app/protocol/flows/handshake"
|
||||||
|
"github.com/kaspanet/kaspad/app/protocol/flows/ping"
|
||||||
|
"github.com/kaspanet/kaspad/app/protocol/flows/rejects"
|
||||||
|
"github.com/kaspanet/kaspad/app/protocol/flows/transactionrelay"
|
||||||
peerpkg "github.com/kaspanet/kaspad/app/protocol/peer"
|
peerpkg "github.com/kaspanet/kaspad/app/protocol/peer"
|
||||||
"github.com/kaspanet/kaspad/app/protocol/protocolerrors"
|
"github.com/kaspanet/kaspad/app/protocol/protocolerrors"
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/addressmanager"
|
"github.com/kaspanet/kaspad/infrastructure/network/addressmanager"
|
||||||
@@ -18,6 +20,14 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type flowInitializeFunc func(route *routerpkg.Route, peer *peerpkg.Peer) error
|
||||||
|
type flowExecuteFunc func(peer *peerpkg.Peer)
|
||||||
|
|
||||||
|
type flow struct {
|
||||||
|
name string
|
||||||
|
executeFunc flowExecuteFunc
|
||||||
|
}
|
||||||
|
|
||||||
func (m *Manager) routerInitializer(router *routerpkg.Router, netConnection *netadapter.NetConnection) {
|
func (m *Manager) routerInitializer(router *routerpkg.Router, netConnection *netadapter.NetConnection) {
|
||||||
// isStopping flag is raised the moment that the connection associated with this router is disconnected
|
// isStopping flag is raised the moment that the connection associated with this router is disconnected
|
||||||
// errChan is used by the flow goroutines to return to runFlows when an error occurs.
|
// errChan is used by the flow goroutines to return to runFlows when an error occurs.
|
||||||
@@ -25,7 +35,8 @@ func (m *Manager) routerInitializer(router *routerpkg.Router, netConnection *net
|
|||||||
isStopping := uint32(0)
|
isStopping := uint32(0)
|
||||||
errChan := make(chan error)
|
errChan := make(chan error)
|
||||||
|
|
||||||
receiveVersionRoute, sendVersionRoute, receiveReadyRoute := registerHandshakeRoutes(router)
|
flows := m.registerFlows(router, errChan, &isStopping)
|
||||||
|
receiveVersionRoute, sendVersionRoute := registerHandshakeRoutes(router)
|
||||||
|
|
||||||
// After flows were registered - spawn a new thread that will wait for connection to finish initializing
|
// After flows were registered - spawn a new thread that will wait for connection to finish initializing
|
||||||
// and start receiving messages
|
// and start receiving messages
|
||||||
@@ -73,21 +84,6 @@ func (m *Manager) routerInitializer(router *routerpkg.Router, netConnection *net
|
|||||||
}
|
}
|
||||||
defer m.context.RemoveFromPeers(peer)
|
defer m.context.RemoveFromPeers(peer)
|
||||||
|
|
||||||
var flows []*common.Flow
|
|
||||||
log.Infof("Registering p2p flows for peer %s for protocol version %d", peer, peer.ProtocolVersion())
|
|
||||||
switch peer.ProtocolVersion() {
|
|
||||||
case 4:
|
|
||||||
flows = v4.Register(m, router, errChan, &isStopping)
|
|
||||||
default:
|
|
||||||
panic(errors.Errorf("no way to handle protocol version %d", peer.ProtocolVersion()))
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ready.HandleReady(receiveReadyRoute, router.OutgoingRoute(), peer)
|
|
||||||
if err != nil {
|
|
||||||
m.handleError(err, netConnection, router.OutgoingRoute())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
removeHandshakeRoutes(router)
|
removeHandshakeRoutes(router)
|
||||||
|
|
||||||
flowsWaitGroup := &sync.WaitGroup{}
|
flowsWaitGroup := &sync.WaitGroup{}
|
||||||
@@ -106,7 +102,7 @@ func (m *Manager) routerInitializer(router *routerpkg.Router, netConnection *net
|
|||||||
|
|
||||||
func (m *Manager) handleError(err error, netConnection *netadapter.NetConnection, outgoingRoute *routerpkg.Route) {
|
func (m *Manager) handleError(err error, netConnection *netadapter.NetConnection, outgoingRoute *routerpkg.Route) {
|
||||||
if protocolErr := (protocolerrors.ProtocolError{}); errors.As(err, &protocolErr) {
|
if protocolErr := (protocolerrors.ProtocolError{}); errors.As(err, &protocolErr) {
|
||||||
if m.context.Config().EnableBanning && protocolErr.ShouldBan {
|
if !m.context.Config().DisableBanning && protocolErr.ShouldBan {
|
||||||
log.Warnf("Banning %s (reason: %s)", netConnection, protocolErr.Cause)
|
log.Warnf("Banning %s (reason: %s)", netConnection, protocolErr.Cause)
|
||||||
|
|
||||||
err := m.context.ConnectionManager().Ban(netConnection)
|
err := m.context.ConnectionManager().Ban(netConnection)
|
||||||
@@ -134,9 +130,167 @@ func (m *Manager) handleError(err error, netConnection *netadapter.NetConnection
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterFlow registers a flow to the given router.
|
func (m *Manager) registerFlows(router *routerpkg.Router, errChan chan error, isStopping *uint32) (flows []*flow) {
|
||||||
func (m *Manager) RegisterFlow(name string, router *routerpkg.Router, messageTypes []appmessage.MessageCommand, isStopping *uint32,
|
flows = m.registerAddressFlows(router, isStopping, errChan)
|
||||||
errChan chan error, initializeFunc common.FlowInitializeFunc) *common.Flow {
|
flows = append(flows, m.registerBlockRelayFlows(router, isStopping, errChan)...)
|
||||||
|
flows = append(flows, m.registerPingFlows(router, isStopping, errChan)...)
|
||||||
|
flows = append(flows, m.registerTransactionRelayFlow(router, isStopping, errChan)...)
|
||||||
|
flows = append(flows, m.registerRejectsFlow(router, isStopping, errChan)...)
|
||||||
|
|
||||||
|
return flows
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) registerAddressFlows(router *routerpkg.Router, isStopping *uint32, errChan chan error) []*flow {
|
||||||
|
outgoingRoute := router.OutgoingRoute()
|
||||||
|
|
||||||
|
return []*flow{
|
||||||
|
m.registerFlow("SendAddresses", router, []appmessage.MessageCommand{appmessage.CmdRequestAddresses}, isStopping, errChan,
|
||||||
|
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
||||||
|
return addressexchange.SendAddresses(m.context, incomingRoute, outgoingRoute)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
m.registerOneTimeFlow("ReceiveAddresses", router, []appmessage.MessageCommand{appmessage.CmdAddresses}, isStopping, errChan,
|
||||||
|
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
||||||
|
return addressexchange.ReceiveAddresses(m.context, incomingRoute, outgoingRoute, peer)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) registerBlockRelayFlows(router *routerpkg.Router, isStopping *uint32, errChan chan error) []*flow {
|
||||||
|
outgoingRoute := router.OutgoingRoute()
|
||||||
|
|
||||||
|
return []*flow{
|
||||||
|
m.registerOneTimeFlow("SendVirtualSelectedParentInv", router, []appmessage.MessageCommand{},
|
||||||
|
isStopping, errChan, func(route *routerpkg.Route, peer *peerpkg.Peer) error {
|
||||||
|
return blockrelay.SendVirtualSelectedParentInv(m.context, outgoingRoute, peer)
|
||||||
|
}),
|
||||||
|
|
||||||
|
m.registerFlow("HandleRelayInvs", router, []appmessage.MessageCommand{
|
||||||
|
appmessage.CmdInvRelayBlock, appmessage.CmdBlock, appmessage.CmdBlockLocator,
|
||||||
|
appmessage.CmdDoneHeaders, appmessage.CmdUnexpectedPruningPoint, appmessage.CmdPruningPointUTXOSetChunk,
|
||||||
|
appmessage.CmdBlockHeaders, appmessage.CmdIBDBlockLocatorHighestHash, appmessage.CmdBlockWithTrustedData,
|
||||||
|
appmessage.CmdDoneBlocksWithTrustedData, appmessage.CmdIBDBlockLocatorHighestHashNotFound,
|
||||||
|
appmessage.CmdDonePruningPointUTXOSetChunks, appmessage.CmdIBDBlock, appmessage.CmdPruningPoints,
|
||||||
|
appmessage.CmdPruningPointProof,
|
||||||
|
},
|
||||||
|
isStopping, errChan, func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
||||||
|
return blockrelay.HandleRelayInvs(m.context, incomingRoute,
|
||||||
|
outgoingRoute, peer)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
m.registerFlow("HandleRelayBlockRequests", router, []appmessage.MessageCommand{appmessage.CmdRequestRelayBlocks}, isStopping, errChan,
|
||||||
|
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
||||||
|
return blockrelay.HandleRelayBlockRequests(m.context, incomingRoute, outgoingRoute, peer)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
m.registerFlow("HandleRequestBlockLocator", router,
|
||||||
|
[]appmessage.MessageCommand{appmessage.CmdRequestBlockLocator}, isStopping, errChan,
|
||||||
|
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
||||||
|
return blockrelay.HandleRequestBlockLocator(m.context, incomingRoute, outgoingRoute)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
m.registerFlow("HandleRequestHeaders", router,
|
||||||
|
[]appmessage.MessageCommand{appmessage.CmdRequestHeaders, appmessage.CmdRequestNextHeaders}, isStopping, errChan,
|
||||||
|
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
||||||
|
return blockrelay.HandleRequestHeaders(m.context, incomingRoute, outgoingRoute, peer)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
m.registerFlow("HandleIBDBlockRequests", router,
|
||||||
|
[]appmessage.MessageCommand{appmessage.CmdRequestIBDBlocks}, isStopping, errChan,
|
||||||
|
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
||||||
|
return blockrelay.HandleIBDBlockRequests(m.context, incomingRoute, outgoingRoute)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
m.registerFlow("HandleRequestPruningPointUTXOSet", router,
|
||||||
|
[]appmessage.MessageCommand{appmessage.CmdRequestPruningPointUTXOSet,
|
||||||
|
appmessage.CmdRequestNextPruningPointUTXOSetChunk}, isStopping, errChan,
|
||||||
|
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
||||||
|
return blockrelay.HandleRequestPruningPointUTXOSet(m.context, incomingRoute, outgoingRoute)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
m.registerFlow("HandlePruningPointAndItsAnticoneRequests", router,
|
||||||
|
[]appmessage.MessageCommand{appmessage.CmdRequestPruningPointAndItsAnticone}, isStopping, errChan,
|
||||||
|
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
||||||
|
return blockrelay.HandlePruningPointAndItsAnticoneRequests(m.context, incomingRoute, outgoingRoute, peer)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
m.registerFlow("HandleIBDBlockLocator", router,
|
||||||
|
[]appmessage.MessageCommand{appmessage.CmdIBDBlockLocator}, isStopping, errChan,
|
||||||
|
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
||||||
|
return blockrelay.HandleIBDBlockLocator(m.context, incomingRoute, outgoingRoute, peer)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
m.registerFlow("HandlePruningPointProofRequests", router,
|
||||||
|
[]appmessage.MessageCommand{appmessage.CmdRequestPruningPointProof}, isStopping, errChan,
|
||||||
|
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
||||||
|
return blockrelay.HandlePruningPointProofRequests(m.context, incomingRoute, outgoingRoute, peer)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) registerPingFlows(router *routerpkg.Router, isStopping *uint32, errChan chan error) []*flow {
|
||||||
|
outgoingRoute := router.OutgoingRoute()
|
||||||
|
|
||||||
|
return []*flow{
|
||||||
|
m.registerFlow("ReceivePings", router, []appmessage.MessageCommand{appmessage.CmdPing}, isStopping, errChan,
|
||||||
|
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
||||||
|
return ping.ReceivePings(m.context, incomingRoute, outgoingRoute)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
m.registerFlow("SendPings", router, []appmessage.MessageCommand{appmessage.CmdPong}, isStopping, errChan,
|
||||||
|
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
||||||
|
return ping.SendPings(m.context, incomingRoute, outgoingRoute, peer)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) registerTransactionRelayFlow(router *routerpkg.Router, isStopping *uint32, errChan chan error) []*flow {
|
||||||
|
outgoingRoute := router.OutgoingRoute()
|
||||||
|
|
||||||
|
return []*flow{
|
||||||
|
m.registerFlowWithCapacity("HandleRelayedTransactions", 10_000, router,
|
||||||
|
[]appmessage.MessageCommand{appmessage.CmdInvTransaction, appmessage.CmdTx, appmessage.CmdTransactionNotFound}, isStopping, errChan,
|
||||||
|
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
||||||
|
return transactionrelay.HandleRelayedTransactions(m.context, incomingRoute, outgoingRoute)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
m.registerFlow("HandleRequestTransactions", router,
|
||||||
|
[]appmessage.MessageCommand{appmessage.CmdRequestTransactions}, isStopping, errChan,
|
||||||
|
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
||||||
|
return transactionrelay.HandleRequestedTransactions(m.context, incomingRoute, outgoingRoute)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) registerRejectsFlow(router *routerpkg.Router, isStopping *uint32, errChan chan error) []*flow {
|
||||||
|
outgoingRoute := router.OutgoingRoute()
|
||||||
|
|
||||||
|
return []*flow{
|
||||||
|
m.registerFlow("HandleRejects", router,
|
||||||
|
[]appmessage.MessageCommand{appmessage.CmdReject}, isStopping, errChan,
|
||||||
|
func(incomingRoute *routerpkg.Route, peer *peerpkg.Peer) error {
|
||||||
|
return rejects.HandleRejects(m.context, incomingRoute, outgoingRoute)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Manager) registerFlow(name string, router *routerpkg.Router, messageTypes []appmessage.MessageCommand, isStopping *uint32,
|
||||||
|
errChan chan error, initializeFunc flowInitializeFunc) *flow {
|
||||||
|
|
||||||
route, err := router.AddIncomingRoute(name, messageTypes)
|
route, err := router.AddIncomingRoute(name, messageTypes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -146,10 +300,9 @@ func (m *Manager) RegisterFlow(name string, router *routerpkg.Router, messageTyp
|
|||||||
return m.registerFlowForRoute(route, name, isStopping, errChan, initializeFunc)
|
return m.registerFlowForRoute(route, name, isStopping, errChan, initializeFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterFlowWithCapacity registers a flow to the given router with a custom capacity.
|
func (m *Manager) registerFlowWithCapacity(name string, capacity int, router *routerpkg.Router,
|
||||||
func (m *Manager) RegisterFlowWithCapacity(name string, capacity int, router *routerpkg.Router,
|
|
||||||
messageTypes []appmessage.MessageCommand, isStopping *uint32,
|
messageTypes []appmessage.MessageCommand, isStopping *uint32,
|
||||||
errChan chan error, initializeFunc common.FlowInitializeFunc) *common.Flow {
|
errChan chan error, initializeFunc flowInitializeFunc) *flow {
|
||||||
|
|
||||||
route, err := router.AddIncomingRouteWithCapacity(name, capacity, messageTypes)
|
route, err := router.AddIncomingRouteWithCapacity(name, capacity, messageTypes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -160,11 +313,11 @@ func (m *Manager) RegisterFlowWithCapacity(name string, capacity int, router *ro
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) registerFlowForRoute(route *routerpkg.Route, name string, isStopping *uint32,
|
func (m *Manager) registerFlowForRoute(route *routerpkg.Route, name string, isStopping *uint32,
|
||||||
errChan chan error, initializeFunc common.FlowInitializeFunc) *common.Flow {
|
errChan chan error, initializeFunc flowInitializeFunc) *flow {
|
||||||
|
|
||||||
return &common.Flow{
|
return &flow{
|
||||||
Name: name,
|
name: name,
|
||||||
ExecuteFunc: func(peer *peerpkg.Peer) {
|
executeFunc: func(peer *peerpkg.Peer) {
|
||||||
err := initializeFunc(route, peer)
|
err := initializeFunc(route, peer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
m.context.HandleError(err, name, isStopping, errChan)
|
m.context.HandleError(err, name, isStopping, errChan)
|
||||||
@@ -174,18 +327,17 @@ func (m *Manager) registerFlowForRoute(route *routerpkg.Route, name string, isSt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterOneTimeFlow registers a one-time flow (that exits once some operations are done) to the given router.
|
func (m *Manager) registerOneTimeFlow(name string, router *routerpkg.Router, messageTypes []appmessage.MessageCommand,
|
||||||
func (m *Manager) RegisterOneTimeFlow(name string, router *routerpkg.Router, messageTypes []appmessage.MessageCommand,
|
isStopping *uint32, stopChan chan error, initializeFunc flowInitializeFunc) *flow {
|
||||||
isStopping *uint32, stopChan chan error, initializeFunc common.FlowInitializeFunc) *common.Flow {
|
|
||||||
|
|
||||||
route, err := router.AddIncomingRoute(name, messageTypes)
|
route, err := router.AddIncomingRoute(name, messageTypes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &common.Flow{
|
return &flow{
|
||||||
Name: name,
|
name: name,
|
||||||
ExecuteFunc: func(peer *peerpkg.Peer) {
|
executeFunc: func(peer *peerpkg.Peer) {
|
||||||
defer func() {
|
defer func() {
|
||||||
err := router.RemoveRoute(messageTypes)
|
err := router.RemoveRoute(messageTypes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -203,7 +355,7 @@ func (m *Manager) RegisterOneTimeFlow(name string, router *routerpkg.Router, mes
|
|||||||
}
|
}
|
||||||
|
|
||||||
func registerHandshakeRoutes(router *routerpkg.Router) (
|
func registerHandshakeRoutes(router *routerpkg.Router) (
|
||||||
receiveVersionRoute, sendVersionRoute, receiveReadyRoute *routerpkg.Route) {
|
receiveVersionRoute *routerpkg.Route, sendVersionRoute *routerpkg.Route) {
|
||||||
receiveVersionRoute, err := router.AddIncomingRoute("recieveVersion - incoming", []appmessage.MessageCommand{appmessage.CmdVersion})
|
receiveVersionRoute, err := router.AddIncomingRoute("recieveVersion - incoming", []appmessage.MessageCommand{appmessage.CmdVersion})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@@ -214,16 +366,11 @@ func registerHandshakeRoutes(router *routerpkg.Router) (
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
receiveReadyRoute, err = router.AddIncomingRoute("recieveReady - incoming", []appmessage.MessageCommand{appmessage.CmdReady})
|
return receiveVersionRoute, sendVersionRoute
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return receiveVersionRoute, sendVersionRoute, receiveReadyRoute
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeHandshakeRoutes(router *routerpkg.Router) {
|
func removeHandshakeRoutes(router *routerpkg.Router) {
|
||||||
err := router.RemoveRoute([]appmessage.MessageCommand{appmessage.CmdVersion, appmessage.CmdVerAck, appmessage.CmdReady})
|
err := router.RemoveRoute([]appmessage.MessageCommand{appmessage.CmdVersion, appmessage.CmdVerAck})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,31 +48,12 @@ func NewManager(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NotifyBlockAddedToDAG notifies the manager that a block has been added to the DAG
|
// NotifyBlockAddedToDAG notifies the manager that a block has been added to the DAG
|
||||||
func (m *Manager) NotifyBlockAddedToDAG(block *externalapi.DomainBlock, virtualChangeSet *externalapi.VirtualChangeSet) error {
|
func (m *Manager) NotifyBlockAddedToDAG(block *externalapi.DomainBlock, blockInsertionResult *externalapi.BlockInsertionResult) error {
|
||||||
onEnd := logger.LogAndMeasureExecutionTime(log, "RPCManager.NotifyBlockAddedToDAG")
|
|
||||||
defer onEnd()
|
|
||||||
|
|
||||||
err := m.NotifyVirtualChange(virtualChangeSet)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
rpcBlock := appmessage.DomainBlockToRPCBlock(block)
|
|
||||||
err = m.context.PopulateBlockWithVerboseData(rpcBlock, block.Header, block, false)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
blockAddedNotification := appmessage.NewBlockAddedNotificationMessage(rpcBlock)
|
|
||||||
return m.context.NotificationManager.NotifyBlockAdded(blockAddedNotification)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifyVirtualChange notifies the manager that the virtual block has been changed.
|
|
||||||
func (m *Manager) NotifyVirtualChange(virtualChangeSet *externalapi.VirtualChangeSet) error {
|
|
||||||
onEnd := logger.LogAndMeasureExecutionTime(log, "RPCManager.NotifyBlockAddedToDAG")
|
onEnd := logger.LogAndMeasureExecutionTime(log, "RPCManager.NotifyBlockAddedToDAG")
|
||||||
defer onEnd()
|
defer onEnd()
|
||||||
|
|
||||||
if m.context.Config.UTXOIndex {
|
if m.context.Config.UTXOIndex {
|
||||||
err := m.notifyUTXOsChanged(virtualChangeSet)
|
err := m.notifyUTXOsChanged(blockInsertionResult)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -88,12 +69,18 @@ func (m *Manager) NotifyVirtualChange(virtualChangeSet *externalapi.VirtualChang
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = m.notifyVirtualSelectedParentChainChanged(virtualChangeSet)
|
err = m.notifyVirtualSelectedParentChainChanged(blockInsertionResult)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
rpcBlock := appmessage.DomainBlockToRPCBlock(block)
|
||||||
|
err = m.context.PopulateBlockWithVerboseData(rpcBlock, block.Header, block, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
blockAddedNotification := appmessage.NewBlockAddedNotificationMessage(rpcBlock)
|
||||||
|
return m.context.NotificationManager.NotifyBlockAdded(blockAddedNotification)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotifyPruningPointUTXOSetOverride notifies the manager whenever the UTXO index
|
// NotifyPruningPointUTXOSetOverride notifies the manager whenever the UTXO index
|
||||||
@@ -130,11 +117,11 @@ func (m *Manager) NotifyFinalityConflictResolved(finalityBlockHash string) error
|
|||||||
return m.context.NotificationManager.NotifyFinalityConflictResolved(notification)
|
return m.context.NotificationManager.NotifyFinalityConflictResolved(notification)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) notifyUTXOsChanged(virtualChangeSet *externalapi.VirtualChangeSet) error {
|
func (m *Manager) notifyUTXOsChanged(blockInsertionResult *externalapi.BlockInsertionResult) error {
|
||||||
onEnd := logger.LogAndMeasureExecutionTime(log, "RPCManager.NotifyUTXOsChanged")
|
onEnd := logger.LogAndMeasureExecutionTime(log, "RPCManager.NotifyUTXOsChanged")
|
||||||
defer onEnd()
|
defer onEnd()
|
||||||
|
|
||||||
utxoIndexChanges, err := m.context.UTXOIndex.Update(virtualChangeSet)
|
utxoIndexChanges, err := m.context.UTXOIndex.Update(blockInsertionResult)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -184,12 +171,12 @@ func (m *Manager) notifyVirtualDaaScoreChanged() error {
|
|||||||
return m.context.NotificationManager.NotifyVirtualDaaScoreChanged(notification)
|
return m.context.NotificationManager.NotifyVirtualDaaScoreChanged(notification)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Manager) notifyVirtualSelectedParentChainChanged(virtualChangeSet *externalapi.VirtualChangeSet) error {
|
func (m *Manager) notifyVirtualSelectedParentChainChanged(blockInsertionResult *externalapi.BlockInsertionResult) error {
|
||||||
onEnd := logger.LogAndMeasureExecutionTime(log, "RPCManager.NotifyVirtualSelectedParentChainChanged")
|
onEnd := logger.LogAndMeasureExecutionTime(log, "RPCManager.NotifyVirtualSelectedParentChainChanged")
|
||||||
defer onEnd()
|
defer onEnd()
|
||||||
|
|
||||||
notification, err := m.context.ConvertVirtualSelectedParentChainChangesToChainChangedNotificationMessage(
|
notification, err := m.context.ConvertVirtualSelectedParentChainChangesToChainChangedNotificationMessage(
|
||||||
virtualChangeSet.VirtualSelectedParentChainChanges)
|
blockInsertionResult.VirtualSelectedParentChainChanges)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ var handlers = map[appmessage.MessageCommand]handler{
|
|||||||
appmessage.CmdGetVirtualSelectedParentChainFromBlockRequestMessage: rpchandlers.HandleGetVirtualSelectedParentChainFromBlock,
|
appmessage.CmdGetVirtualSelectedParentChainFromBlockRequestMessage: rpchandlers.HandleGetVirtualSelectedParentChainFromBlock,
|
||||||
appmessage.CmdGetBlocksRequestMessage: rpchandlers.HandleGetBlocks,
|
appmessage.CmdGetBlocksRequestMessage: rpchandlers.HandleGetBlocks,
|
||||||
appmessage.CmdGetBlockCountRequestMessage: rpchandlers.HandleGetBlockCount,
|
appmessage.CmdGetBlockCountRequestMessage: rpchandlers.HandleGetBlockCount,
|
||||||
appmessage.CmdGetBalanceByAddressRequestMessage: rpchandlers.HandleGetBalanceByAddress,
|
|
||||||
appmessage.CmdGetBlockDAGInfoRequestMessage: rpchandlers.HandleGetBlockDAGInfo,
|
appmessage.CmdGetBlockDAGInfoRequestMessage: rpchandlers.HandleGetBlockDAGInfo,
|
||||||
appmessage.CmdResolveFinalityConflictRequestMessage: rpchandlers.HandleResolveFinalityConflict,
|
appmessage.CmdResolveFinalityConflictRequestMessage: rpchandlers.HandleResolveFinalityConflict,
|
||||||
appmessage.CmdNotifyFinalityConflictsRequestMessage: rpchandlers.HandleNotifyFinalityConflicts,
|
appmessage.CmdNotifyFinalityConflictsRequestMessage: rpchandlers.HandleNotifyFinalityConflicts,
|
||||||
@@ -38,7 +37,6 @@ var handlers = map[appmessage.MessageCommand]handler{
|
|||||||
appmessage.CmdNotifyUTXOsChangedRequestMessage: rpchandlers.HandleNotifyUTXOsChanged,
|
appmessage.CmdNotifyUTXOsChangedRequestMessage: rpchandlers.HandleNotifyUTXOsChanged,
|
||||||
appmessage.CmdStopNotifyingUTXOsChangedRequestMessage: rpchandlers.HandleStopNotifyingUTXOsChanged,
|
appmessage.CmdStopNotifyingUTXOsChangedRequestMessage: rpchandlers.HandleStopNotifyingUTXOsChanged,
|
||||||
appmessage.CmdGetUTXOsByAddressesRequestMessage: rpchandlers.HandleGetUTXOsByAddresses,
|
appmessage.CmdGetUTXOsByAddressesRequestMessage: rpchandlers.HandleGetUTXOsByAddresses,
|
||||||
appmessage.CmdGetBalancesByAddressesRequestMessage: rpchandlers.HandleGetBalancesByAddresses,
|
|
||||||
appmessage.CmdGetVirtualSelectedParentBlueScoreRequestMessage: rpchandlers.HandleGetVirtualSelectedParentBlueScore,
|
appmessage.CmdGetVirtualSelectedParentBlueScoreRequestMessage: rpchandlers.HandleGetVirtualSelectedParentBlueScore,
|
||||||
appmessage.CmdNotifyVirtualSelectedParentBlueScoreChangedRequestMessage: rpchandlers.HandleNotifyVirtualSelectedParentBlueScoreChanged,
|
appmessage.CmdNotifyVirtualSelectedParentBlueScoreChangedRequestMessage: rpchandlers.HandleNotifyVirtualSelectedParentBlueScoreChanged,
|
||||||
appmessage.CmdBanRequestMessage: rpchandlers.HandleBan,
|
appmessage.CmdBanRequestMessage: rpchandlers.HandleBan,
|
||||||
|
|||||||
@@ -56,29 +56,21 @@ func (ctx *Context) PopulateBlockWithVerboseData(block *appmessage.RPCBlock, dom
|
|||||||
"invalid block")
|
"invalid block")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, childrenHashes, err := ctx.Domain.Consensus().GetBlockRelations(blockHash)
|
_, selectedParentHash, childrenHashes, err := ctx.Domain.Consensus().GetBlockRelations(blockHash)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
isChainBlock, err := ctx.Domain.Consensus().IsChainBlock(blockHash)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
block.VerboseData = &appmessage.RPCBlockVerboseData{
|
block.VerboseData = &appmessage.RPCBlockVerboseData{
|
||||||
Hash: blockHash.String(),
|
Hash: blockHash.String(),
|
||||||
Difficulty: ctx.GetDifficultyRatio(domainBlockHeader.Bits(), ctx.Config.ActiveNetParams),
|
Difficulty: ctx.GetDifficultyRatio(domainBlockHeader.Bits(), ctx.Config.ActiveNetParams),
|
||||||
ChildrenHashes: hashes.ToStrings(childrenHashes),
|
ChildrenHashes: hashes.ToStrings(childrenHashes),
|
||||||
IsHeaderOnly: blockInfo.BlockStatus == externalapi.StatusHeaderOnly,
|
IsHeaderOnly: blockInfo.BlockStatus == externalapi.StatusHeaderOnly,
|
||||||
BlueScore: blockInfo.BlueScore,
|
BlueScore: blockInfo.BlueScore,
|
||||||
MergeSetBluesHashes: hashes.ToStrings(blockInfo.MergeSetBlues),
|
|
||||||
MergeSetRedsHashes: hashes.ToStrings(blockInfo.MergeSetReds),
|
|
||||||
IsChainBlock: isChainBlock,
|
|
||||||
}
|
}
|
||||||
// selectedParentHash will be nil in the genesis block
|
// selectedParentHash will be nil in the genesis block
|
||||||
if blockInfo.SelectedParent != nil {
|
if selectedParentHash != nil {
|
||||||
block.VerboseData.SelectedParentHash = blockInfo.SelectedParent.String()
|
block.VerboseData.SelectedParentHash = selectedParentHash.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
if blockInfo.BlockStatus == externalapi.StatusHeaderOnly {
|
if blockInfo.BlockStatus == externalapi.StatusHeaderOnly {
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
package rpchandlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
|
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
"github.com/kaspanet/kaspad/util"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleGetBalanceByAddress handles the respectively named RPC command
|
|
||||||
func HandleGetBalanceByAddress(context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) {
|
|
||||||
if !context.Config.UTXOIndex {
|
|
||||||
errorMessage := &appmessage.GetUTXOsByAddressesResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Method unavailable when kaspad is run without --utxoindex")
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
getBalanceByAddressRequest := request.(*appmessage.GetBalanceByAddressRequestMessage)
|
|
||||||
|
|
||||||
balance, err := getBalanceByAddress(context, getBalanceByAddressRequest.Address)
|
|
||||||
if err != nil {
|
|
||||||
rpcError := &appmessage.RPCError{}
|
|
||||||
if !errors.As(err, rpcError) {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
errorMessage := &appmessage.GetUTXOsByAddressesResponseMessage{}
|
|
||||||
errorMessage.Error = rpcError
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
response := appmessage.NewGetBalanceByAddressResponse(balance)
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getBalanceByAddress(context *rpccontext.Context, addressString string) (uint64, error) {
|
|
||||||
address, err := util.DecodeAddress(addressString, context.Config.ActiveNetParams.Prefix)
|
|
||||||
if err != nil {
|
|
||||||
return 0, appmessage.RPCErrorf("Couldn't decode address '%s': %s", addressString, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptPublicKey, err := txscript.PayToAddrScript(address)
|
|
||||||
if err != nil {
|
|
||||||
return 0, appmessage.RPCErrorf("Could not create a scriptPublicKey for address '%s': %s", addressString, err)
|
|
||||||
}
|
|
||||||
utxoOutpointEntryPairs, err := context.UTXOIndex.UTXOs(scriptPublicKey)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
balance := uint64(0)
|
|
||||||
for _, utxoOutpointEntryPair := range utxoOutpointEntryPairs {
|
|
||||||
balance += utxoOutpointEntryPair.Amount()
|
|
||||||
}
|
|
||||||
return balance, nil
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
package rpchandlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
|
||||||
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
|
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleGetBalancesByAddresses handles the respectively named RPC command
|
|
||||||
func HandleGetBalancesByAddresses(context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) {
|
|
||||||
if !context.Config.UTXOIndex {
|
|
||||||
errorMessage := &appmessage.GetBalancesByAddressesResponseMessage{}
|
|
||||||
errorMessage.Error = appmessage.RPCErrorf("Method unavailable when kaspad is run without --utxoindex")
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
getBalancesByAddressesRequest := request.(*appmessage.GetBalancesByAddressesRequestMessage)
|
|
||||||
|
|
||||||
allEntries := make([]*appmessage.BalancesByAddressesEntry, len(getBalancesByAddressesRequest.Addresses))
|
|
||||||
for i, address := range getBalancesByAddressesRequest.Addresses {
|
|
||||||
balance, err := getBalanceByAddress(context, address)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
rpcError := &appmessage.RPCError{}
|
|
||||||
if !errors.As(err, rpcError) {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
errorMessage := &appmessage.GetUTXOsByAddressesResponseMessage{}
|
|
||||||
errorMessage.Error = rpcError
|
|
||||||
return errorMessage, nil
|
|
||||||
}
|
|
||||||
allEntries[i] = &appmessage.BalancesByAddressesEntry{
|
|
||||||
Address: address,
|
|
||||||
Balance: balance,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
response := appmessage.NewGetBalancesByAddressesResponse(allEntries)
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
@@ -14,14 +14,9 @@ import (
|
|||||||
func HandleSubmitBlock(context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) {
|
func HandleSubmitBlock(context *rpccontext.Context, _ *router.Router, request appmessage.Message) (appmessage.Message, error) {
|
||||||
submitBlockRequest := request.(*appmessage.SubmitBlockRequestMessage)
|
submitBlockRequest := request.(*appmessage.SubmitBlockRequestMessage)
|
||||||
|
|
||||||
isSynced, err := context.ProtocolManager.ShouldMine()
|
if context.ProtocolManager.IsIBDRunning() {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !context.Config.AllowSubmitBlockWhenNotSynced && !isSynced {
|
|
||||||
return &appmessage.SubmitBlockResponseMessage{
|
return &appmessage.SubmitBlockResponseMessage{
|
||||||
Error: appmessage.RPCErrorf("Block not submitted - node is not synced"),
|
Error: appmessage.RPCErrorf("Block not submitted - IBD is running"),
|
||||||
RejectReason: appmessage.RejectReasonIsInIBD,
|
RejectReason: appmessage.RejectReasonIsInIBD,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@@ -34,23 +29,6 @@ func HandleSubmitBlock(context *rpccontext.Context, _ *router.Router, request ap
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !submitBlockRequest.AllowNonDAABlocks {
|
|
||||||
virtualDAAScore, err := context.Domain.Consensus().GetVirtualDAAScore()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// A simple heuristic check which signals that the mined block is out of date
|
|
||||||
// and should not be accepted unless user explicitly requests
|
|
||||||
daaWindowSize := uint64(context.Config.NetParams().DifficultyAdjustmentWindowSize)
|
|
||||||
if virtualDAAScore > daaWindowSize && domainBlock.Header.DAAScore() < virtualDAAScore-daaWindowSize {
|
|
||||||
return &appmessage.SubmitBlockResponseMessage{
|
|
||||||
Error: appmessage.RPCErrorf("Block rejected. Reason: block DAA score %d is too far "+
|
|
||||||
"behind virtual's DAA score %d", domainBlock.Header.DAAScore(), virtualDAAScore),
|
|
||||||
RejectReason: appmessage.RejectReasonBlockInvalid,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = context.ProtocolManager.AddBlock(domainBlock)
|
err = context.ProtocolManager.AddBlock(domainBlock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
isProtocolOrRuleError := errors.As(err, &ruleerrors.RuleError{}) || errors.As(err, &protocolerrors.ProtocolError{})
|
isProtocolOrRuleError := errors.As(err, &ruleerrors.RuleError{}) || errors.As(err, &protocolerrors.ProtocolError{})
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ golint -set_exit_status ./...
|
|||||||
|
|
||||||
staticcheck -checks SA4006,SA4008,SA4009,SA4010,SA5003,SA1004,SA1014,SA1021,SA1023,SA1024,SA1025,SA1026,SA1027,SA1028,SA2000,SA2001,SA2003,SA4000,SA4001,SA4003,SA4004,SA4011,SA4012,SA4013,SA4014,SA4015,SA4016,SA4017,SA4018,SA4019,SA4020,SA4021,SA4022,SA4023,SA5000,SA5002,SA5004,SA5005,SA5007,SA5008,SA5009,SA5010,SA5011,SA5012,SA6001,SA6002,SA9001,SA9002,SA9003,SA9004,SA9005,SA9006,ST1019 ./...
|
staticcheck -checks SA4006,SA4008,SA4009,SA4010,SA5003,SA1004,SA1014,SA1021,SA1023,SA1024,SA1025,SA1026,SA1027,SA1028,SA2000,SA2001,SA2003,SA4000,SA4001,SA4003,SA4004,SA4011,SA4012,SA4013,SA4014,SA4015,SA4016,SA4017,SA4018,SA4019,SA4020,SA4021,SA4022,SA4023,SA5000,SA5002,SA5004,SA5005,SA5007,SA5008,SA5009,SA5010,SA5011,SA5012,SA6001,SA6002,SA9001,SA9002,SA9003,SA9004,SA9005,SA9006,ST1019 ./...
|
||||||
|
|
||||||
|
go vet -composites=false $FLAGS ./...
|
||||||
|
|
||||||
go build $FLAGS -o kaspad .
|
go build $FLAGS -o kaspad .
|
||||||
|
|
||||||
if [ -n "${NO_PARALLEL}" ]
|
if [ -n "${NO_PARALLEL}" ]
|
||||||
|
|||||||
@@ -1,57 +1,3 @@
|
|||||||
Kaspad v0.11.11 - 2022-01-27
|
|
||||||
===========================
|
|
||||||
* Fix for rare consensus bug regarding DAA window order. The bug only affected IBD from scratch and only today (#1934)
|
|
||||||
|
|
||||||
Kaspad v0.11.10 - 2022-01-27
|
|
||||||
===========================
|
|
||||||
* Add monitoring of heap and save heap profile if size is over some limit (#1932)
|
|
||||||
* Extract IBD management from invs relay flow to a new separated flow (#1930)
|
|
||||||
* Add --transaction-file options to the `sign` and `broadcast` wallet subcommands (#1927)
|
|
||||||
* Filter redundant blocks from daa window on IBD (#1925)
|
|
||||||
* Implement a P2P upgrade mechanism (#1921)
|
|
||||||
|
|
||||||
Kaspad v0.11.9 - 2021-12-30
|
|
||||||
===========================
|
|
||||||
Breaking changes:
|
|
||||||
* Implement the new monetary policy. Breaking change effective only in ~4 months (#1892)
|
|
||||||
|
|
||||||
Bug fixes:
|
|
||||||
* Fix two pruning proof IBD crash bugs (#1913)
|
|
||||||
* Fix UTXO index bug showing wrong wallet balance (#1891)
|
|
||||||
|
|
||||||
Non-breaking changes:
|
|
||||||
* Address search: cleanup repetitively-offline addresses and use randomization weighted by connection failures (#1899, #1916)
|
|
||||||
* New DNS seeders and removal of offline one (#1901, #1910, #1918)
|
|
||||||
* Add request balance by address to kaspactl (#1885)
|
|
||||||
* Wallet: show balance by addresses (#1904)
|
|
||||||
* Reject outdated non-DAA blocks submitted via RPC (#1914)
|
|
||||||
* Add a profile option to kaspawallet daemon (#1854)
|
|
||||||
|
|
||||||
Kaspad v0.11.8 - 2021-12-13
|
|
||||||
===========================
|
|
||||||
Bug fixes:
|
|
||||||
* Update reindex root for each block level (#1881)
|
|
||||||
|
|
||||||
Non-breaking changes:
|
|
||||||
* Update readme (#1848)
|
|
||||||
* Lower devnet's initial difficulty (#1869)
|
|
||||||
|
|
||||||
Kaspad v0.11.7 - 2021-12-11
|
|
||||||
===========================
|
|
||||||
Breaking changes:
|
|
||||||
* kaspawallet: show-address →new-address + show-addresses (#1870)
|
|
||||||
|
|
||||||
Bug fixes:
|
|
||||||
* Fix numThreads using getAEAD instead of decryptMnemonic (#1859)
|
|
||||||
* Apply ResolveVirtual diffs to the UTXO index (#1868)
|
|
||||||
|
|
||||||
Non-breaking changes:
|
|
||||||
* Ignore header mass in devnet and testnet (#1879)
|
|
||||||
* Remove unused args from CalcSubsidy (#1877)
|
|
||||||
* ExpectedHeaderPruningPoint fix (#1876)
|
|
||||||
* Changes to libkaspawallet to support Kaspaper (#1878)
|
|
||||||
* Get rid of genesis's UTXO dump (#1867)
|
|
||||||
|
|
||||||
Kaspad v0.11.2 - 2021-11-11
|
Kaspad v0.11.2 - 2021-11-11
|
||||||
===========================
|
===========================
|
||||||
Bug fixes:
|
Bug fixes:
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"google.golang.org/protobuf/encoding/protojson"
|
"google.golang.org/protobuf/encoding/protojson"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
@@ -150,24 +149,12 @@ func stringToValue(parameterDesc *parameterDescription, valueStr string) (reflec
|
|||||||
|
|
||||||
value = pointer.Interface()
|
value = pointer.Interface()
|
||||||
|
|
||||||
case reflect.Slice:
|
|
||||||
sliceType := parameterDesc.typeof.Elem()
|
|
||||||
if sliceType.Kind() != reflect.String {
|
|
||||||
return reflect.Value{},
|
|
||||||
errors.Errorf("Unsupported slice type '%s' for parameter '%s'",
|
|
||||||
sliceType,
|
|
||||||
parameterDesc.name)
|
|
||||||
}
|
|
||||||
if valueStr == "" {
|
|
||||||
value = []string{}
|
|
||||||
} else {
|
|
||||||
value = strings.Split(valueStr, ",")
|
|
||||||
}
|
|
||||||
// Int and uint are not supported because their size is platform-dependant
|
// Int and uint are not supported because their size is platform-dependant
|
||||||
case reflect.Int,
|
case reflect.Int,
|
||||||
reflect.Uint,
|
reflect.Uint,
|
||||||
// Other types are not supported simply because they are not used in any command right now
|
// Other types are not supported simply because they are not used in any command right now
|
||||||
// but support can be added if and when needed
|
// but support can be added if and when needed
|
||||||
|
reflect.Slice,
|
||||||
reflect.Func,
|
reflect.Func,
|
||||||
reflect.Interface,
|
reflect.Interface,
|
||||||
reflect.Map,
|
reflect.Map,
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ var commandTypes = []reflect.Type{
|
|||||||
reflect.TypeOf(protowire.KaspadMessage_SubmitTransactionRequest{}),
|
reflect.TypeOf(protowire.KaspadMessage_SubmitTransactionRequest{}),
|
||||||
|
|
||||||
reflect.TypeOf(protowire.KaspadMessage_GetUtxosByAddressesRequest{}),
|
reflect.TypeOf(protowire.KaspadMessage_GetUtxosByAddressesRequest{}),
|
||||||
reflect.TypeOf(protowire.KaspadMessage_GetBalanceByAddressRequest{}),
|
|
||||||
|
|
||||||
reflect.TypeOf(protowire.KaspadMessage_BanRequest{}),
|
reflect.TypeOf(protowire.KaspadMessage_BanRequest{}),
|
||||||
reflect.TypeOf(protowire.KaspadMessage_UnbanRequest{}),
|
reflect.TypeOf(protowire.KaspadMessage_UnbanRequest{}),
|
||||||
|
|||||||
@@ -12,12 +12,11 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type configFlags struct {
|
type configFlags struct {
|
||||||
RPCServer string `short:"s" long:"rpcserver" description:"RPC server to connect to"`
|
RPCServer string `short:"s" long:"rpcserver" description:"RPC server to connect to"`
|
||||||
Timeout uint64 `short:"t" long:"timeout" description:"Timeout for the request (in seconds)"`
|
Timeout uint64 `short:"t" long:"timeout" description:"Timeout for the request (in seconds)"`
|
||||||
RequestJSON string `short:"j" long:"json" description:"The request in JSON format"`
|
RequestJSON string `short:"j" long:"json" description:"The request in JSON format"`
|
||||||
ListCommands bool `short:"l" long:"list-commands" description:"List all commands and exit"`
|
ListCommands bool `short:"l" long:"list-commands" description:"List all commands and exit"`
|
||||||
AllowConnectionToDifferentVersions bool `short:"a" long:"allow-connection-to-different-versions" description:"Allow connections to versions different than kaspactl's version'"`
|
CommandAndParameters []string
|
||||||
CommandAndParameters []string
|
|
||||||
config.NetworkFlags
|
config.NetworkFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,18 +34,16 @@ func main() {
|
|||||||
}
|
}
|
||||||
defer client.Disconnect()
|
defer client.Disconnect()
|
||||||
|
|
||||||
if !cfg.AllowConnectionToDifferentVersions {
|
kaspadMessage, err := client.Post(&protowire.KaspadMessage{Payload: &protowire.KaspadMessage_GetInfoRequest{GetInfoRequest: &protowire.GetInfoRequestMessage{}}})
|
||||||
kaspadMessage, err := client.Post(&protowire.KaspadMessage{Payload: &protowire.KaspadMessage_GetInfoRequest{GetInfoRequest: &protowire.GetInfoRequestMessage{}}})
|
if err != nil {
|
||||||
if err != nil {
|
printErrorAndExit(fmt.Sprintf("Cannot post GetInfo message: %s", err))
|
||||||
printErrorAndExit(fmt.Sprintf("Cannot post GetInfo message: %s", err))
|
}
|
||||||
}
|
|
||||||
|
|
||||||
localVersion := version.Version()
|
localVersion := version.Version()
|
||||||
remoteVersion := kaspadMessage.GetGetInfoResponse().ServerVersion
|
remoteVersion := kaspadMessage.GetGetInfoResponse().ServerVersion
|
||||||
|
|
||||||
if localVersion != remoteVersion {
|
if localVersion != remoteVersion {
|
||||||
printErrorAndExit(fmt.Sprintf("Server version mismatch, expect: %s, got: %s", localVersion, remoteVersion))
|
printErrorAndExit(fmt.Sprintf("Server version mismatch, expect: %s, got: %s", localVersion, remoteVersion))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
responseChan := make(chan string)
|
responseChan := make(chan string)
|
||||||
|
|||||||
@@ -8,14 +8,6 @@ import (
|
|||||||
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
func formatKas(amount uint64) string {
|
|
||||||
res := " "
|
|
||||||
if amount > 0 {
|
|
||||||
res = fmt.Sprintf("%19.8f", float64(amount)/constants.SompiPerKaspa)
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
func balance(conf *balanceConfig) error {
|
func balance(conf *balanceConfig) error {
|
||||||
daemonClient, tearDown, err := client.Connect(conf.DaemonAddress)
|
daemonClient, tearDown, err := client.Connect(conf.DaemonAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -30,21 +22,10 @@ func balance(conf *balanceConfig) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
pendingSuffix := ""
|
fmt.Printf("Balance:\t\tKAS %f\n", float64(response.Available)/constants.SompiPerKaspa)
|
||||||
if response.Pending > 0 {
|
if response.Pending > 0 {
|
||||||
pendingSuffix = " (pending)"
|
fmt.Printf("Pending balance:\tKAS %f\n", float64(response.Pending)/constants.SompiPerKaspa)
|
||||||
}
|
}
|
||||||
if conf.Verbose {
|
|
||||||
pendingSuffix = ""
|
|
||||||
println("Address Available Pending")
|
|
||||||
println("-----------------------------------------------------------------------------------------------------------")
|
|
||||||
for _, addressBalance := range response.AddressBalances {
|
|
||||||
fmt.Printf("%s %s %s\n", addressBalance.Address, formatKas(addressBalance.Available), formatKas(addressBalance.Pending))
|
|
||||||
}
|
|
||||||
println("-----------------------------------------------------------------------------------------------------------")
|
|
||||||
print(" ")
|
|
||||||
}
|
|
||||||
fmt.Printf("Total balance, KAS %s %s%s\n", formatKas(response.Available), formatKas(response.Pending), pendingSuffix)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/client"
|
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/client"
|
||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
|
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"io/ioutil"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func broadcast(conf *broadcastConfig) error {
|
func broadcast(conf *broadcastConfig) error {
|
||||||
@@ -21,23 +18,7 @@ func broadcast(conf *broadcastConfig) error {
|
|||||||
ctx, cancel := context.WithTimeout(context.Background(), daemonTimeout)
|
ctx, cancel := context.WithTimeout(context.Background(), daemonTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if conf.Transaction == "" && conf.TransactionFile == "" {
|
transaction, err := hex.DecodeString(conf.Transaction)
|
||||||
return errors.Errorf("Either --transaction or --transaction-file is required")
|
|
||||||
}
|
|
||||||
if conf.Transaction != "" && conf.TransactionFile != "" {
|
|
||||||
return errors.Errorf("Both --transaction and --transaction-file cannot be passed at the same time")
|
|
||||||
}
|
|
||||||
|
|
||||||
transactionHex := conf.Transaction
|
|
||||||
if conf.TransactionFile != "" {
|
|
||||||
transactionHexBytes, err := ioutil.ReadFile(conf.TransactionFile)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "Could not read hex from %s", conf.TransactionFile)
|
|
||||||
}
|
|
||||||
transactionHex = strings.TrimSpace(string(transactionHexBytes))
|
|
||||||
}
|
|
||||||
|
|
||||||
transaction, err := hex.DecodeString(transactionHex)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,7 @@ const (
|
|||||||
createUnsignedTransactionSubCmd = "create-unsigned-transaction"
|
createUnsignedTransactionSubCmd = "create-unsigned-transaction"
|
||||||
signSubCmd = "sign"
|
signSubCmd = "sign"
|
||||||
broadcastSubCmd = "broadcast"
|
broadcastSubCmd = "broadcast"
|
||||||
parseSubCmd = "parse"
|
showAddressSubCmd = "show-address"
|
||||||
showAddressesSubCmd = "show-addresses"
|
|
||||||
newAddressSubCmd = "new-address"
|
|
||||||
dumpUnencryptedDataSubCmd = "dump-unencrypted-data"
|
dumpUnencryptedDataSubCmd = "dump-unencrypted-data"
|
||||||
startDaemonSubCmd = "start-daemon"
|
startDaemonSubCmd = "start-daemon"
|
||||||
)
|
)
|
||||||
@@ -45,7 +43,6 @@ type createConfig struct {
|
|||||||
|
|
||||||
type balanceConfig struct {
|
type balanceConfig struct {
|
||||||
DaemonAddress string `long:"daemonaddress" short:"d" description:"Wallet daemon server to connect to (default: localhost:8082)"`
|
DaemonAddress string `long:"daemonaddress" short:"d" description:"Wallet daemon server to connect to (default: localhost:8082)"`
|
||||||
Verbose bool `long:"verbose" short:"v" description:"Verbose: show addresses with balance"`
|
|
||||||
config.NetworkFlags
|
config.NetworkFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,33 +63,19 @@ type createUnsignedTransactionConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type signConfig struct {
|
type signConfig struct {
|
||||||
KeysFile string `long:"keys-file" short:"f" description:"Keys file location (default: ~/.kaspawallet/keys.json (*nix), %USERPROFILE%\\AppData\\Local\\Kaspawallet\\key.json (Windows))"`
|
KeysFile string `long:"keys-file" short:"f" description:"Keys file location (default: ~/.kaspawallet/keys.json (*nix), %USERPROFILE%\\AppData\\Local\\Kaspawallet\\key.json (Windows))"`
|
||||||
Password string `long:"password" short:"p" description:"Wallet password"`
|
Password string `long:"password" short:"p" description:"Wallet password"`
|
||||||
Transaction string `long:"transaction" short:"t" description:"The unsigned transaction to sign on (encoded in hex)"`
|
Transaction string `long:"transaction" short:"t" description:"The unsigned transaction to sign on (encoded in hex)" required:"true"`
|
||||||
TransactionFile string `long:"transaction-file" short:"F" description:"The file containing the unsigned transaction to sign on (encoded in hex)"`
|
|
||||||
config.NetworkFlags
|
config.NetworkFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
type broadcastConfig struct {
|
type broadcastConfig struct {
|
||||||
DaemonAddress string `long:"daemonaddress" short:"d" description:"Wallet daemon server to connect to (default: localhost:8082)"`
|
|
||||||
Transaction string `long:"transaction" short:"t" description:"The signed transaction to broadcast (encoded in hex)"`
|
|
||||||
TransactionFile string `long:"transaction-file" short:"F" description:"The file containing the unsigned transaction to sign on (encoded in hex)"`
|
|
||||||
config.NetworkFlags
|
|
||||||
}
|
|
||||||
|
|
||||||
type parseConfig struct {
|
|
||||||
Transaction string `long:"transaction" short:"t" description:"The transaction to parse (encoded in hex)"`
|
|
||||||
TransactionFile string `long:"transaction-file" short:"F" description:"The file containing the transaction to parse (encoded in hex)"`
|
|
||||||
Verbose bool `long:"verbose" short:"v" description:"Verbose: show transaction inputs"`
|
|
||||||
config.NetworkFlags
|
|
||||||
}
|
|
||||||
|
|
||||||
type showAddressesConfig struct {
|
|
||||||
DaemonAddress string `long:"daemonaddress" short:"d" description:"Wallet daemon server to connect to (default: localhost:8082)"`
|
DaemonAddress string `long:"daemonaddress" short:"d" description:"Wallet daemon server to connect to (default: localhost:8082)"`
|
||||||
|
Transaction string `long:"transaction" short:"t" description:"The signed transaction to broadcast (encoded in hex)" required:"true"`
|
||||||
config.NetworkFlags
|
config.NetworkFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
type newAddressConfig struct {
|
type showAddressConfig struct {
|
||||||
DaemonAddress string `long:"daemonaddress" short:"d" description:"Wallet daemon server to connect to (default: localhost:8082)"`
|
DaemonAddress string `long:"daemonaddress" short:"d" description:"Wallet daemon server to connect to (default: localhost:8082)"`
|
||||||
config.NetworkFlags
|
config.NetworkFlags
|
||||||
}
|
}
|
||||||
@@ -102,7 +85,6 @@ type startDaemonConfig struct {
|
|||||||
Password string `long:"password" short:"p" description:"Wallet password"`
|
Password string `long:"password" short:"p" description:"Wallet password"`
|
||||||
RPCServer string `long:"rpcserver" short:"s" description:"RPC server to connect to"`
|
RPCServer string `long:"rpcserver" short:"s" description:"RPC server to connect to"`
|
||||||
Listen string `short:"l" long:"listen" description:"Address to listen on (default: 0.0.0.0:8082)"`
|
Listen string `short:"l" long:"listen" description:"Address to listen on (default: 0.0.0.0:8082)"`
|
||||||
Profile string `long:"profile" description:"Enable HTTP profiling on given port -- NOTE port must be between 1024 and 65536"`
|
|
||||||
config.NetworkFlags
|
config.NetworkFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,17 +123,9 @@ func parseCommandLine() (subCommand string, config interface{}) {
|
|||||||
parser.AddCommand(broadcastSubCmd, "Broadcast the given transaction",
|
parser.AddCommand(broadcastSubCmd, "Broadcast the given transaction",
|
||||||
"Broadcast the given transaction", broadcastConf)
|
"Broadcast the given transaction", broadcastConf)
|
||||||
|
|
||||||
parseConf := &parseConfig{}
|
showAddressConf := &showAddressConfig{DaemonAddress: defaultListen}
|
||||||
parser.AddCommand(parseSubCmd, "Parse the given transaction and print its contents",
|
parser.AddCommand(showAddressSubCmd, "Shows the public address of the current wallet",
|
||||||
"Parse the given transaction and print its contents", parseConf)
|
"Shows the public address of the current wallet", showAddressConf)
|
||||||
|
|
||||||
showAddressesConf := &showAddressesConfig{DaemonAddress: defaultListen}
|
|
||||||
parser.AddCommand(showAddressesSubCmd, "Shows all generated public addresses of the current wallet",
|
|
||||||
"Shows all generated public addresses of the current wallet", showAddressesConf)
|
|
||||||
|
|
||||||
newAddressConf := &newAddressConfig{DaemonAddress: defaultListen}
|
|
||||||
parser.AddCommand(newAddressSubCmd, "Generates new public address of the current wallet and shows it",
|
|
||||||
"Generates new public address of the current wallet and shows it", newAddressConf)
|
|
||||||
|
|
||||||
dumpUnencryptedDataConf := &dumpUnencryptedDataConfig{}
|
dumpUnencryptedDataConf := &dumpUnencryptedDataConfig{}
|
||||||
parser.AddCommand(dumpUnencryptedDataSubCmd, "Prints the unencrypted wallet data",
|
parser.AddCommand(dumpUnencryptedDataSubCmd, "Prints the unencrypted wallet data",
|
||||||
@@ -219,27 +193,13 @@ func parseCommandLine() (subCommand string, config interface{}) {
|
|||||||
printErrorAndExit(err)
|
printErrorAndExit(err)
|
||||||
}
|
}
|
||||||
config = broadcastConf
|
config = broadcastConf
|
||||||
case parseSubCmd:
|
case showAddressSubCmd:
|
||||||
combineNetworkFlags(&parseConf.NetworkFlags, &cfg.NetworkFlags)
|
combineNetworkFlags(&showAddressConf.NetworkFlags, &cfg.NetworkFlags)
|
||||||
err := parseConf.ResolveNetwork(parser)
|
err := showAddressConf.ResolveNetwork(parser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
printErrorAndExit(err)
|
printErrorAndExit(err)
|
||||||
}
|
}
|
||||||
config = parseConf
|
config = showAddressConf
|
||||||
case showAddressesSubCmd:
|
|
||||||
combineNetworkFlags(&showAddressesConf.NetworkFlags, &cfg.NetworkFlags)
|
|
||||||
err := showAddressesConf.ResolveNetwork(parser)
|
|
||||||
if err != nil {
|
|
||||||
printErrorAndExit(err)
|
|
||||||
}
|
|
||||||
config = showAddressesConf
|
|
||||||
case newAddressSubCmd:
|
|
||||||
combineNetworkFlags(&newAddressConf.NetworkFlags, &cfg.NetworkFlags)
|
|
||||||
err := newAddressConf.ResolveNetwork(parser)
|
|
||||||
if err != nil {
|
|
||||||
printErrorAndExit(err)
|
|
||||||
}
|
|
||||||
config = newAddressConf
|
|
||||||
case dumpUnencryptedDataSubCmd:
|
case dumpUnencryptedDataSubCmd:
|
||||||
combineNetworkFlags(&dumpUnencryptedDataConf.NetworkFlags, &cfg.NetworkFlags)
|
combineNetworkFlags(&dumpUnencryptedDataConf.NetworkFlags, &cfg.NetworkFlags)
|
||||||
err := dumpUnencryptedDataConf.ResolveNetwork(parser)
|
err := dumpUnencryptedDataConf.ResolveNetwork(parser)
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ func create(conf *createConfig) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
file := keys.File{
|
file := keys.File{
|
||||||
Version: keys.LastVersion,
|
|
||||||
EncryptedMnemonics: encryptedMnemonics,
|
EncryptedMnemonics: encryptedMnemonics,
|
||||||
ExtendedPublicKeys: extendedPublicKeys,
|
ExtendedPublicKeys: extendedPublicKeys,
|
||||||
MinimumSignatures: conf.MinimumSignatures,
|
MinimumSignatures: conf.MinimumSignatures,
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.25.0
|
||||||
// protoc v3.12.3
|
// protoc v3.12.3
|
||||||
// source: kaspawalletd.proto
|
// source: kaspawalletd.proto
|
||||||
|
|
||||||
package pb
|
package pb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
proto "github.com/golang/protobuf/proto"
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
@@ -20,6 +21,10 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||||
|
// of the legacy proto package is being used.
|
||||||
|
const _ = proto.ProtoPackageIsVersion4
|
||||||
|
|
||||||
type GetBalanceRequest struct {
|
type GetBalanceRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -63,9 +68,8 @@ type GetBalanceResponse struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Available uint64 `protobuf:"varint,1,opt,name=available,proto3" json:"available,omitempty"`
|
Available uint64 `protobuf:"varint,1,opt,name=available,proto3" json:"available,omitempty"`
|
||||||
Pending uint64 `protobuf:"varint,2,opt,name=pending,proto3" json:"pending,omitempty"`
|
Pending uint64 `protobuf:"varint,2,opt,name=pending,proto3" json:"pending,omitempty"`
|
||||||
AddressBalances []*AddressBalances `protobuf:"bytes,3,rep,name=addressBalances,proto3" json:"addressBalances,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetBalanceResponse) Reset() {
|
func (x *GetBalanceResponse) Reset() {
|
||||||
@@ -114,76 +118,6 @@ func (x *GetBalanceResponse) GetPending() uint64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetBalanceResponse) GetAddressBalances() []*AddressBalances {
|
|
||||||
if x != nil {
|
|
||||||
return x.AddressBalances
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type AddressBalances struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
|
|
||||||
Available uint64 `protobuf:"varint,2,opt,name=available,proto3" json:"available,omitempty"`
|
|
||||||
Pending uint64 `protobuf:"varint,3,opt,name=pending,proto3" json:"pending,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AddressBalances) Reset() {
|
|
||||||
*x = AddressBalances{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[2]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AddressBalances) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*AddressBalances) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *AddressBalances) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[2]
|
|
||||||
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 AddressBalances.ProtoReflect.Descriptor instead.
|
|
||||||
func (*AddressBalances) Descriptor() ([]byte, []int) {
|
|
||||||
return file_kaspawalletd_proto_rawDescGZIP(), []int{2}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AddressBalances) GetAddress() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Address
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AddressBalances) GetAvailable() uint64 {
|
|
||||||
if x != nil {
|
|
||||||
return x.Available
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AddressBalances) GetPending() uint64 {
|
|
||||||
if x != nil {
|
|
||||||
return x.Pending
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateUnsignedTransactionRequest struct {
|
type CreateUnsignedTransactionRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -196,7 +130,7 @@ type CreateUnsignedTransactionRequest struct {
|
|||||||
func (x *CreateUnsignedTransactionRequest) Reset() {
|
func (x *CreateUnsignedTransactionRequest) Reset() {
|
||||||
*x = CreateUnsignedTransactionRequest{}
|
*x = CreateUnsignedTransactionRequest{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[3]
|
mi := &file_kaspawalletd_proto_msgTypes[2]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -209,7 +143,7 @@ func (x *CreateUnsignedTransactionRequest) String() string {
|
|||||||
func (*CreateUnsignedTransactionRequest) ProtoMessage() {}
|
func (*CreateUnsignedTransactionRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *CreateUnsignedTransactionRequest) ProtoReflect() protoreflect.Message {
|
func (x *CreateUnsignedTransactionRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[3]
|
mi := &file_kaspawalletd_proto_msgTypes[2]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -222,7 +156,7 @@ func (x *CreateUnsignedTransactionRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use CreateUnsignedTransactionRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use CreateUnsignedTransactionRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*CreateUnsignedTransactionRequest) Descriptor() ([]byte, []int) {
|
func (*CreateUnsignedTransactionRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_kaspawalletd_proto_rawDescGZIP(), []int{3}
|
return file_kaspawalletd_proto_rawDescGZIP(), []int{2}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CreateUnsignedTransactionRequest) GetAddress() string {
|
func (x *CreateUnsignedTransactionRequest) GetAddress() string {
|
||||||
@@ -250,7 +184,7 @@ type CreateUnsignedTransactionResponse struct {
|
|||||||
func (x *CreateUnsignedTransactionResponse) Reset() {
|
func (x *CreateUnsignedTransactionResponse) Reset() {
|
||||||
*x = CreateUnsignedTransactionResponse{}
|
*x = CreateUnsignedTransactionResponse{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[4]
|
mi := &file_kaspawalletd_proto_msgTypes[3]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -263,7 +197,7 @@ func (x *CreateUnsignedTransactionResponse) String() string {
|
|||||||
func (*CreateUnsignedTransactionResponse) ProtoMessage() {}
|
func (*CreateUnsignedTransactionResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *CreateUnsignedTransactionResponse) ProtoReflect() protoreflect.Message {
|
func (x *CreateUnsignedTransactionResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[4]
|
mi := &file_kaspawalletd_proto_msgTypes[3]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -276,7 +210,7 @@ func (x *CreateUnsignedTransactionResponse) ProtoReflect() protoreflect.Message
|
|||||||
|
|
||||||
// Deprecated: Use CreateUnsignedTransactionResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use CreateUnsignedTransactionResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*CreateUnsignedTransactionResponse) Descriptor() ([]byte, []int) {
|
func (*CreateUnsignedTransactionResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_kaspawalletd_proto_rawDescGZIP(), []int{4}
|
return file_kaspawalletd_proto_rawDescGZIP(), []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CreateUnsignedTransactionResponse) GetUnsignedTransaction() []byte {
|
func (x *CreateUnsignedTransactionResponse) GetUnsignedTransaction() []byte {
|
||||||
@@ -286,14 +220,54 @@ func (x *CreateUnsignedTransactionResponse) GetUnsignedTransaction() []byte {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ShowAddressesRequest struct {
|
type GetReceiveAddressRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ShowAddressesRequest) Reset() {
|
func (x *GetReceiveAddressRequest) Reset() {
|
||||||
*x = ShowAddressesRequest{}
|
*x = GetReceiveAddressRequest{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_kaspawalletd_proto_msgTypes[4]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetReceiveAddressRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GetReceiveAddressRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GetReceiveAddressRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_kaspawalletd_proto_msgTypes[4]
|
||||||
|
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 GetReceiveAddressRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GetReceiveAddressRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_kaspawalletd_proto_rawDescGZIP(), []int{4}
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetReceiveAddressResponse struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetReceiveAddressResponse) Reset() {
|
||||||
|
*x = GetReceiveAddressResponse{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[5]
|
mi := &file_kaspawalletd_proto_msgTypes[5]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
@@ -301,13 +275,13 @@ func (x *ShowAddressesRequest) Reset() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ShowAddressesRequest) String() string {
|
func (x *GetReceiveAddressResponse) String() string {
|
||||||
return protoimpl.X.MessageStringOf(x)
|
return protoimpl.X.MessageStringOf(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*ShowAddressesRequest) ProtoMessage() {}
|
func (*GetReceiveAddressResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *ShowAddressesRequest) ProtoReflect() protoreflect.Message {
|
func (x *GetReceiveAddressResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[5]
|
mi := &file_kaspawalletd_proto_msgTypes[5]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
@@ -319,137 +293,12 @@ func (x *ShowAddressesRequest) ProtoReflect() protoreflect.Message {
|
|||||||
return mi.MessageOf(x)
|
return mi.MessageOf(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Use ShowAddressesRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use GetReceiveAddressResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*ShowAddressesRequest) Descriptor() ([]byte, []int) {
|
func (*GetReceiveAddressResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_kaspawalletd_proto_rawDescGZIP(), []int{5}
|
return file_kaspawalletd_proto_rawDescGZIP(), []int{5}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ShowAddressesResponse struct {
|
func (x *GetReceiveAddressResponse) GetAddress() string {
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Address []string `protobuf:"bytes,1,rep,name=address,proto3" json:"address,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ShowAddressesResponse) Reset() {
|
|
||||||
*x = ShowAddressesResponse{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[6]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ShowAddressesResponse) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*ShowAddressesResponse) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *ShowAddressesResponse) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[6]
|
|
||||||
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 ShowAddressesResponse.ProtoReflect.Descriptor instead.
|
|
||||||
func (*ShowAddressesResponse) Descriptor() ([]byte, []int) {
|
|
||||||
return file_kaspawalletd_proto_rawDescGZIP(), []int{6}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ShowAddressesResponse) GetAddress() []string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Address
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type NewAddressRequest struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NewAddressRequest) Reset() {
|
|
||||||
*x = NewAddressRequest{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[7]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NewAddressRequest) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*NewAddressRequest) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *NewAddressRequest) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[7]
|
|
||||||
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 NewAddressRequest.ProtoReflect.Descriptor instead.
|
|
||||||
func (*NewAddressRequest) Descriptor() ([]byte, []int) {
|
|
||||||
return file_kaspawalletd_proto_rawDescGZIP(), []int{7}
|
|
||||||
}
|
|
||||||
|
|
||||||
type NewAddressResponse struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NewAddressResponse) Reset() {
|
|
||||||
*x = NewAddressResponse{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[8]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NewAddressResponse) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*NewAddressResponse) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *NewAddressResponse) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[8]
|
|
||||||
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 NewAddressResponse.ProtoReflect.Descriptor instead.
|
|
||||||
func (*NewAddressResponse) Descriptor() ([]byte, []int) {
|
|
||||||
return file_kaspawalletd_proto_rawDescGZIP(), []int{8}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NewAddressResponse) GetAddress() string {
|
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Address
|
return x.Address
|
||||||
}
|
}
|
||||||
@@ -467,7 +316,7 @@ type BroadcastRequest struct {
|
|||||||
func (x *BroadcastRequest) Reset() {
|
func (x *BroadcastRequest) Reset() {
|
||||||
*x = BroadcastRequest{}
|
*x = BroadcastRequest{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[9]
|
mi := &file_kaspawalletd_proto_msgTypes[6]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -480,7 +329,7 @@ func (x *BroadcastRequest) String() string {
|
|||||||
func (*BroadcastRequest) ProtoMessage() {}
|
func (*BroadcastRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *BroadcastRequest) ProtoReflect() protoreflect.Message {
|
func (x *BroadcastRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[9]
|
mi := &file_kaspawalletd_proto_msgTypes[6]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -493,7 +342,7 @@ func (x *BroadcastRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use BroadcastRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use BroadcastRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*BroadcastRequest) Descriptor() ([]byte, []int) {
|
func (*BroadcastRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_kaspawalletd_proto_rawDescGZIP(), []int{9}
|
return file_kaspawalletd_proto_rawDescGZIP(), []int{6}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *BroadcastRequest) GetTransaction() []byte {
|
func (x *BroadcastRequest) GetTransaction() []byte {
|
||||||
@@ -514,7 +363,7 @@ type BroadcastResponse struct {
|
|||||||
func (x *BroadcastResponse) Reset() {
|
func (x *BroadcastResponse) Reset() {
|
||||||
*x = BroadcastResponse{}
|
*x = BroadcastResponse{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[10]
|
mi := &file_kaspawalletd_proto_msgTypes[7]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -527,7 +376,7 @@ func (x *BroadcastResponse) String() string {
|
|||||||
func (*BroadcastResponse) ProtoMessage() {}
|
func (*BroadcastResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *BroadcastResponse) ProtoReflect() protoreflect.Message {
|
func (x *BroadcastResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[10]
|
mi := &file_kaspawalletd_proto_msgTypes[7]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -540,7 +389,7 @@ func (x *BroadcastResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use BroadcastResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use BroadcastResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*BroadcastResponse) Descriptor() ([]byte, []int) {
|
func (*BroadcastResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_kaspawalletd_proto_rawDescGZIP(), []int{10}
|
return file_kaspawalletd_proto_rawDescGZIP(), []int{7}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *BroadcastResponse) GetTxID() string {
|
func (x *BroadcastResponse) GetTxID() string {
|
||||||
@@ -559,7 +408,7 @@ type ShutdownRequest struct {
|
|||||||
func (x *ShutdownRequest) Reset() {
|
func (x *ShutdownRequest) Reset() {
|
||||||
*x = ShutdownRequest{}
|
*x = ShutdownRequest{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[11]
|
mi := &file_kaspawalletd_proto_msgTypes[8]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -572,7 +421,7 @@ func (x *ShutdownRequest) String() string {
|
|||||||
func (*ShutdownRequest) ProtoMessage() {}
|
func (*ShutdownRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *ShutdownRequest) ProtoReflect() protoreflect.Message {
|
func (x *ShutdownRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[11]
|
mi := &file_kaspawalletd_proto_msgTypes[8]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -585,7 +434,7 @@ func (x *ShutdownRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use ShutdownRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use ShutdownRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*ShutdownRequest) Descriptor() ([]byte, []int) {
|
func (*ShutdownRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_kaspawalletd_proto_rawDescGZIP(), []int{11}
|
return file_kaspawalletd_proto_rawDescGZIP(), []int{8}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ShutdownResponse struct {
|
type ShutdownResponse struct {
|
||||||
@@ -597,7 +446,7 @@ type ShutdownResponse struct {
|
|||||||
func (x *ShutdownResponse) Reset() {
|
func (x *ShutdownResponse) Reset() {
|
||||||
*x = ShutdownResponse{}
|
*x = ShutdownResponse{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[12]
|
mi := &file_kaspawalletd_proto_msgTypes[9]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -610,7 +459,7 @@ func (x *ShutdownResponse) String() string {
|
|||||||
func (*ShutdownResponse) ProtoMessage() {}
|
func (*ShutdownResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *ShutdownResponse) ProtoReflect() protoreflect.Message {
|
func (x *ShutdownResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_kaspawalletd_proto_msgTypes[12]
|
mi := &file_kaspawalletd_proto_msgTypes[9]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -623,7 +472,7 @@ func (x *ShutdownResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use ShutdownResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use ShutdownResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*ShutdownResponse) Descriptor() ([]byte, []int) {
|
func (*ShutdownResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_kaspawalletd_proto_rawDescGZIP(), []int{12}
|
return file_kaspawalletd_proto_rawDescGZIP(), []int{9}
|
||||||
}
|
}
|
||||||
|
|
||||||
var File_kaspawalletd_proto protoreflect.FileDescriptor
|
var File_kaspawalletd_proto protoreflect.FileDescriptor
|
||||||
@@ -631,79 +480,63 @@ var File_kaspawalletd_proto protoreflect.FileDescriptor
|
|||||||
var file_kaspawalletd_proto_rawDesc = []byte{
|
var file_kaspawalletd_proto_rawDesc = []byte{
|
||||||
0x0a, 0x12, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x70,
|
0x0a, 0x12, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2e, 0x70,
|
||||||
0x72, 0x6f, 0x74, 0x6f, 0x22, 0x13, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e,
|
0x72, 0x6f, 0x74, 0x6f, 0x22, 0x13, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e,
|
||||||
0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x88, 0x01, 0x0a, 0x12, 0x47, 0x65,
|
0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x4c, 0x0a, 0x12, 0x47, 0x65, 0x74,
|
||||||
0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||||
0x12, 0x1c, 0x0a, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20,
|
0x1c, 0x0a, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01,
|
||||||
0x01, 0x28, 0x04, 0x52, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x18,
|
0x28, 0x04, 0x52, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x18, 0x0a,
|
||||||
0x0a, 0x07, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52,
|
0x07, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07,
|
||||||
0x07, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x3a, 0x0a, 0x0f, 0x61, 0x64, 0x64, 0x72,
|
0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x22, 0x54, 0x0a, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74,
|
||||||
0x65, 0x73, 0x73, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
|
0x65, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63,
|
||||||
0x0b, 0x32, 0x10, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x61, 0x6c, 0x61, 0x6e,
|
0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61,
|
||||||
0x63, 0x65, 0x73, 0x52, 0x0f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x61, 0x6c, 0x61,
|
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64,
|
||||||
0x6e, 0x63, 0x65, 0x73, 0x22, 0x63, 0x0a, 0x0f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42,
|
0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18,
|
||||||
0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65,
|
0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x55, 0x0a,
|
||||||
0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
|
0x21, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54,
|
||||||
0x73, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02,
|
0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||||
0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12,
|
0x73, 0x65, 0x12, 0x30, 0x0a, 0x13, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72,
|
||||||
0x18, 0x0a, 0x07, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04,
|
|
||||||
0x52, 0x07, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x22, 0x54, 0x0a, 0x20, 0x43, 0x72, 0x65,
|
|
||||||
0x61, 0x74, 0x65, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73,
|
|
||||||
0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a,
|
|
||||||
0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
|
|
||||||
0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e,
|
|
||||||
0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22,
|
|
||||||
0x55, 0x0a, 0x21, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65,
|
|
||||||
0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70,
|
|
||||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x13, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64,
|
|
||||||
0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28,
|
|
||||||
0x0c, 0x52, 0x13, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73,
|
|
||||||
0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x16, 0x0a, 0x14, 0x53, 0x68, 0x6f, 0x77, 0x41, 0x64,
|
|
||||||
0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x31,
|
|
||||||
0x0a, 0x15, 0x53, 0x68, 0x6f, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52,
|
|
||||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65,
|
|
||||||
0x73, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
|
|
||||||
0x73, 0x22, 0x13, 0x0a, 0x11, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52,
|
|
||||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2e, 0x0a, 0x12, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64,
|
|
||||||
0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07,
|
|
||||||
0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61,
|
|
||||||
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x34, 0x0a, 0x10, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63,
|
|
||||||
0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x74, 0x72,
|
|
||||||
0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52,
|
0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52,
|
||||||
0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x27, 0x0a, 0x11,
|
0x13, 0x75, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63,
|
||||||
0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
0x74, 0x69, 0x6f, 0x6e, 0x22, 0x1a, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69,
|
||||||
0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
0x76, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||||
0x04, 0x74, 0x78, 0x49, 0x44, 0x22, 0x11, 0x0a, 0x0f, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77,
|
0x22, 0x35, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x64,
|
||||||
0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x12, 0x0a, 0x10, 0x53, 0x68, 0x75, 0x74,
|
0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a,
|
||||||
0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x91, 0x03, 0x0a,
|
0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
|
||||||
0x0c, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x12, 0x37, 0x0a,
|
0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x34, 0x0a, 0x10, 0x42, 0x72, 0x6f, 0x61, 0x64,
|
||||||
0x0a, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x2e, 0x47, 0x65,
|
0x63, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x74,
|
||||||
0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c,
|
||||||
0x13, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70,
|
0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x27, 0x0a,
|
||||||
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x64, 0x0a, 0x19, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
|
0x11, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||||
|
0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||||
|
0x52, 0x04, 0x74, 0x78, 0x49, 0x44, 0x22, 0x11, 0x0a, 0x0f, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f,
|
||||||
|
0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x12, 0x0a, 0x10, 0x53, 0x68, 0x75,
|
||||||
|
0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe4, 0x02,
|
||||||
|
0x0a, 0x0c, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x12, 0x37,
|
||||||
|
0x0a, 0x0a, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x2e, 0x47,
|
||||||
|
0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||||
|
0x1a, 0x13, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x73,
|
||||||
|
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x64, 0x0a, 0x19, 0x43, 0x72, 0x65, 0x61, 0x74,
|
||||||
|
0x65, 0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63,
|
||||||
|
0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x6e, 0x73,
|
||||||
|
0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
|
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
|
||||||
0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74,
|
0x55, 0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74,
|
||||||
0x69, 0x6f, 0x6e, 0x12, 0x21, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x6e, 0x73, 0x69,
|
0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a,
|
||||||
0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52,
|
0x11, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65,
|
||||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55,
|
0x73, 0x73, 0x12, 0x19, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41,
|
||||||
0x6e, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69,
|
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e,
|
||||||
0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x0d,
|
0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
|
||||||
0x53, 0x68, 0x6f, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x15, 0x2e,
|
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x31, 0x0a, 0x08, 0x53,
|
||||||
0x53, 0x68, 0x6f, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71,
|
0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x10, 0x2e, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x53, 0x68, 0x6f, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65,
|
0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x53, 0x68, 0x75, 0x74,
|
||||||
0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x37,
|
0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x34,
|
||||||
0x0a, 0x0a, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x2e, 0x4e,
|
0x0a, 0x09, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x12, 0x11, 0x2e, 0x42, 0x72,
|
||||||
0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12,
|
||||||
0x1a, 0x13, 0x2e, 0x4e, 0x65, 0x77, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73,
|
0x2e, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x31, 0x0a, 0x08, 0x53, 0x68, 0x75, 0x74, 0x64,
|
0x73, 0x65, 0x22, 0x00, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
|
||||||
0x6f, 0x77, 0x6e, 0x12, 0x10, 0x2e, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65,
|
0x6f, 0x6d, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x6e, 0x65, 0x74, 0x2f, 0x6b, 0x61, 0x73, 0x70,
|
||||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e,
|
0x61, 0x64, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x77, 0x61, 0x6c, 0x6c,
|
||||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x34, 0x0a, 0x09, 0x42, 0x72,
|
0x65, 0x74, 0x2f, 0x64, 0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72,
|
||||||
0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x12, 0x11, 0x2e, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63,
|
0x6f, 0x74, 0x6f, 0x33,
|
||||||
0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x42, 0x72, 0x6f,
|
|
||||||
0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
|
|
||||||
0x42, 0x36, 0x5a, 0x34, 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, 0x63,
|
|
||||||
0x6d, 0x64, 0x2f, 0x6b, 0x61, 0x73, 0x70, 0x61, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2f, 0x64,
|
|
||||||
0x61, 0x65, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -718,41 +551,35 @@ func file_kaspawalletd_proto_rawDescGZIP() []byte {
|
|||||||
return file_kaspawalletd_proto_rawDescData
|
return file_kaspawalletd_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_kaspawalletd_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
|
var file_kaspawalletd_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
|
||||||
var file_kaspawalletd_proto_goTypes = []interface{}{
|
var file_kaspawalletd_proto_goTypes = []interface{}{
|
||||||
(*GetBalanceRequest)(nil), // 0: GetBalanceRequest
|
(*GetBalanceRequest)(nil), // 0: GetBalanceRequest
|
||||||
(*GetBalanceResponse)(nil), // 1: GetBalanceResponse
|
(*GetBalanceResponse)(nil), // 1: GetBalanceResponse
|
||||||
(*AddressBalances)(nil), // 2: AddressBalances
|
(*CreateUnsignedTransactionRequest)(nil), // 2: CreateUnsignedTransactionRequest
|
||||||
(*CreateUnsignedTransactionRequest)(nil), // 3: CreateUnsignedTransactionRequest
|
(*CreateUnsignedTransactionResponse)(nil), // 3: CreateUnsignedTransactionResponse
|
||||||
(*CreateUnsignedTransactionResponse)(nil), // 4: CreateUnsignedTransactionResponse
|
(*GetReceiveAddressRequest)(nil), // 4: GetReceiveAddressRequest
|
||||||
(*ShowAddressesRequest)(nil), // 5: ShowAddressesRequest
|
(*GetReceiveAddressResponse)(nil), // 5: GetReceiveAddressResponse
|
||||||
(*ShowAddressesResponse)(nil), // 6: ShowAddressesResponse
|
(*BroadcastRequest)(nil), // 6: BroadcastRequest
|
||||||
(*NewAddressRequest)(nil), // 7: NewAddressRequest
|
(*BroadcastResponse)(nil), // 7: BroadcastResponse
|
||||||
(*NewAddressResponse)(nil), // 8: NewAddressResponse
|
(*ShutdownRequest)(nil), // 8: ShutdownRequest
|
||||||
(*BroadcastRequest)(nil), // 9: BroadcastRequest
|
(*ShutdownResponse)(nil), // 9: ShutdownResponse
|
||||||
(*BroadcastResponse)(nil), // 10: BroadcastResponse
|
|
||||||
(*ShutdownRequest)(nil), // 11: ShutdownRequest
|
|
||||||
(*ShutdownResponse)(nil), // 12: ShutdownResponse
|
|
||||||
}
|
}
|
||||||
var file_kaspawalletd_proto_depIdxs = []int32{
|
var file_kaspawalletd_proto_depIdxs = []int32{
|
||||||
2, // 0: GetBalanceResponse.addressBalances:type_name -> AddressBalances
|
0, // 0: kaspawalletd.GetBalance:input_type -> GetBalanceRequest
|
||||||
0, // 1: kaspawalletd.GetBalance:input_type -> GetBalanceRequest
|
2, // 1: kaspawalletd.CreateUnsignedTransaction:input_type -> CreateUnsignedTransactionRequest
|
||||||
3, // 2: kaspawalletd.CreateUnsignedTransaction:input_type -> CreateUnsignedTransactionRequest
|
4, // 2: kaspawalletd.GetReceiveAddress:input_type -> GetReceiveAddressRequest
|
||||||
5, // 3: kaspawalletd.ShowAddresses:input_type -> ShowAddressesRequest
|
8, // 3: kaspawalletd.Shutdown:input_type -> ShutdownRequest
|
||||||
7, // 4: kaspawalletd.NewAddress:input_type -> NewAddressRequest
|
6, // 4: kaspawalletd.Broadcast:input_type -> BroadcastRequest
|
||||||
11, // 5: kaspawalletd.Shutdown:input_type -> ShutdownRequest
|
1, // 5: kaspawalletd.GetBalance:output_type -> GetBalanceResponse
|
||||||
9, // 6: kaspawalletd.Broadcast:input_type -> BroadcastRequest
|
3, // 6: kaspawalletd.CreateUnsignedTransaction:output_type -> CreateUnsignedTransactionResponse
|
||||||
1, // 7: kaspawalletd.GetBalance:output_type -> GetBalanceResponse
|
5, // 7: kaspawalletd.GetReceiveAddress:output_type -> GetReceiveAddressResponse
|
||||||
4, // 8: kaspawalletd.CreateUnsignedTransaction:output_type -> CreateUnsignedTransactionResponse
|
9, // 8: kaspawalletd.Shutdown:output_type -> ShutdownResponse
|
||||||
6, // 9: kaspawalletd.ShowAddresses:output_type -> ShowAddressesResponse
|
7, // 9: kaspawalletd.Broadcast:output_type -> BroadcastResponse
|
||||||
8, // 10: kaspawalletd.NewAddress:output_type -> NewAddressResponse
|
5, // [5:10] is the sub-list for method output_type
|
||||||
12, // 11: kaspawalletd.Shutdown:output_type -> ShutdownResponse
|
0, // [0:5] is the sub-list for method input_type
|
||||||
10, // 12: kaspawalletd.Broadcast:output_type -> BroadcastResponse
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
7, // [7:13] is the sub-list for method output_type
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
1, // [1:7] is the sub-list for method input_type
|
0, // [0:0] is the sub-list for field type_name
|
||||||
1, // [1:1] is the sub-list for extension type_name
|
|
||||||
1, // [1:1] is the sub-list for extension extendee
|
|
||||||
0, // [0:1] is the sub-list for field type_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_kaspawalletd_proto_init() }
|
func init() { file_kaspawalletd_proto_init() }
|
||||||
@@ -786,18 +613,6 @@ func file_kaspawalletd_proto_init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_kaspawalletd_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
file_kaspawalletd_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*AddressBalances); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_kaspawalletd_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*CreateUnsignedTransactionRequest); i {
|
switch v := v.(*CreateUnsignedTransactionRequest); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
@@ -809,7 +624,7 @@ func file_kaspawalletd_proto_init() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_kaspawalletd_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
file_kaspawalletd_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*CreateUnsignedTransactionResponse); i {
|
switch v := v.(*CreateUnsignedTransactionResponse); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
@@ -821,8 +636,20 @@ func file_kaspawalletd_proto_init() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
file_kaspawalletd_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*GetReceiveAddressRequest); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
file_kaspawalletd_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
file_kaspawalletd_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*ShowAddressesRequest); i {
|
switch v := v.(*GetReceiveAddressResponse); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
case 1:
|
case 1:
|
||||||
@@ -834,42 +661,6 @@ func file_kaspawalletd_proto_init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_kaspawalletd_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
file_kaspawalletd_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*ShowAddressesResponse); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_kaspawalletd_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*NewAddressRequest); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_kaspawalletd_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*NewAddressResponse); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_kaspawalletd_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*BroadcastRequest); i {
|
switch v := v.(*BroadcastRequest); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
@@ -881,7 +672,7 @@ func file_kaspawalletd_proto_init() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_kaspawalletd_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
|
file_kaspawalletd_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*BroadcastResponse); i {
|
switch v := v.(*BroadcastResponse); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
@@ -893,7 +684,7 @@ func file_kaspawalletd_proto_init() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_kaspawalletd_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
|
file_kaspawalletd_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*ShutdownRequest); i {
|
switch v := v.(*ShutdownRequest); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
@@ -905,7 +696,7 @@ func file_kaspawalletd_proto_init() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_kaspawalletd_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
|
file_kaspawalletd_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*ShutdownResponse); i {
|
switch v := v.(*ShutdownResponse); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
@@ -924,7 +715,7 @@ func file_kaspawalletd_proto_init() {
|
|||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_kaspawalletd_proto_rawDesc,
|
RawDescriptor: file_kaspawalletd_proto_rawDesc,
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 13,
|
NumMessages: 10,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ option go_package = "github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb";
|
|||||||
service kaspawalletd {
|
service kaspawalletd {
|
||||||
rpc GetBalance (GetBalanceRequest) returns (GetBalanceResponse) {}
|
rpc GetBalance (GetBalanceRequest) returns (GetBalanceResponse) {}
|
||||||
rpc CreateUnsignedTransaction (CreateUnsignedTransactionRequest) returns (CreateUnsignedTransactionResponse) {}
|
rpc CreateUnsignedTransaction (CreateUnsignedTransactionRequest) returns (CreateUnsignedTransactionResponse) {}
|
||||||
rpc ShowAddresses (ShowAddressesRequest) returns (ShowAddressesResponse) {}
|
rpc GetReceiveAddress (GetReceiveAddressRequest) returns (GetReceiveAddressResponse) {}
|
||||||
rpc NewAddress (NewAddressRequest) returns (NewAddressResponse) {}
|
|
||||||
rpc Shutdown (ShutdownRequest) returns (ShutdownResponse) {}
|
rpc Shutdown (ShutdownRequest) returns (ShutdownResponse) {}
|
||||||
rpc Broadcast (BroadcastRequest) returns (BroadcastResponse) {}
|
rpc Broadcast (BroadcastRequest) returns (BroadcastResponse) {}
|
||||||
}
|
}
|
||||||
@@ -17,13 +16,6 @@ message GetBalanceRequest {
|
|||||||
message GetBalanceResponse {
|
message GetBalanceResponse {
|
||||||
uint64 available = 1;
|
uint64 available = 1;
|
||||||
uint64 pending = 2;
|
uint64 pending = 2;
|
||||||
repeated AddressBalances addressBalances = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message AddressBalances {
|
|
||||||
string address = 1;
|
|
||||||
uint64 available = 2;
|
|
||||||
uint64 pending = 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message CreateUnsignedTransactionRequest {
|
message CreateUnsignedTransactionRequest {
|
||||||
@@ -35,17 +27,10 @@ message CreateUnsignedTransactionResponse {
|
|||||||
bytes unsignedTransaction = 1;
|
bytes unsignedTransaction = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ShowAddressesRequest {
|
message GetReceiveAddressRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
message ShowAddressesResponse {
|
message GetReceiveAddressResponse {
|
||||||
repeated string address = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message NewAddressRequest {
|
|
||||||
}
|
|
||||||
|
|
||||||
message NewAddressResponse {
|
|
||||||
string address = 1;
|
string address = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,7 @@ import (
|
|||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
// is compatible with the grpc package it is being compiled against.
|
// is compatible with the grpc package it is being compiled against.
|
||||||
// Requires gRPC-Go v1.32.0 or later.
|
const _ = grpc.SupportPackageIsVersion6
|
||||||
const _ = grpc.SupportPackageIsVersion7
|
|
||||||
|
|
||||||
// KaspawalletdClient is the client API for Kaspawalletd service.
|
// KaspawalletdClient is the client API for Kaspawalletd service.
|
||||||
//
|
//
|
||||||
@@ -20,8 +19,7 @@ const _ = grpc.SupportPackageIsVersion7
|
|||||||
type KaspawalletdClient interface {
|
type KaspawalletdClient interface {
|
||||||
GetBalance(ctx context.Context, in *GetBalanceRequest, opts ...grpc.CallOption) (*GetBalanceResponse, error)
|
GetBalance(ctx context.Context, in *GetBalanceRequest, opts ...grpc.CallOption) (*GetBalanceResponse, error)
|
||||||
CreateUnsignedTransaction(ctx context.Context, in *CreateUnsignedTransactionRequest, opts ...grpc.CallOption) (*CreateUnsignedTransactionResponse, error)
|
CreateUnsignedTransaction(ctx context.Context, in *CreateUnsignedTransactionRequest, opts ...grpc.CallOption) (*CreateUnsignedTransactionResponse, error)
|
||||||
ShowAddresses(ctx context.Context, in *ShowAddressesRequest, opts ...grpc.CallOption) (*ShowAddressesResponse, error)
|
GetReceiveAddress(ctx context.Context, in *GetReceiveAddressRequest, opts ...grpc.CallOption) (*GetReceiveAddressResponse, error)
|
||||||
NewAddress(ctx context.Context, in *NewAddressRequest, opts ...grpc.CallOption) (*NewAddressResponse, error)
|
|
||||||
Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*ShutdownResponse, error)
|
Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*ShutdownResponse, error)
|
||||||
Broadcast(ctx context.Context, in *BroadcastRequest, opts ...grpc.CallOption) (*BroadcastResponse, error)
|
Broadcast(ctx context.Context, in *BroadcastRequest, opts ...grpc.CallOption) (*BroadcastResponse, error)
|
||||||
}
|
}
|
||||||
@@ -52,18 +50,9 @@ func (c *kaspawalletdClient) CreateUnsignedTransaction(ctx context.Context, in *
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *kaspawalletdClient) ShowAddresses(ctx context.Context, in *ShowAddressesRequest, opts ...grpc.CallOption) (*ShowAddressesResponse, error) {
|
func (c *kaspawalletdClient) GetReceiveAddress(ctx context.Context, in *GetReceiveAddressRequest, opts ...grpc.CallOption) (*GetReceiveAddressResponse, error) {
|
||||||
out := new(ShowAddressesResponse)
|
out := new(GetReceiveAddressResponse)
|
||||||
err := c.cc.Invoke(ctx, "/kaspawalletd/ShowAddresses", in, out, opts...)
|
err := c.cc.Invoke(ctx, "/kaspawalletd/GetReceiveAddress", in, out, opts...)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *kaspawalletdClient) NewAddress(ctx context.Context, in *NewAddressRequest, opts ...grpc.CallOption) (*NewAddressResponse, error) {
|
|
||||||
out := new(NewAddressResponse)
|
|
||||||
err := c.cc.Invoke(ctx, "/kaspawalletd/NewAddress", in, out, opts...)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -94,8 +83,7 @@ func (c *kaspawalletdClient) Broadcast(ctx context.Context, in *BroadcastRequest
|
|||||||
type KaspawalletdServer interface {
|
type KaspawalletdServer interface {
|
||||||
GetBalance(context.Context, *GetBalanceRequest) (*GetBalanceResponse, error)
|
GetBalance(context.Context, *GetBalanceRequest) (*GetBalanceResponse, error)
|
||||||
CreateUnsignedTransaction(context.Context, *CreateUnsignedTransactionRequest) (*CreateUnsignedTransactionResponse, error)
|
CreateUnsignedTransaction(context.Context, *CreateUnsignedTransactionRequest) (*CreateUnsignedTransactionResponse, error)
|
||||||
ShowAddresses(context.Context, *ShowAddressesRequest) (*ShowAddressesResponse, error)
|
GetReceiveAddress(context.Context, *GetReceiveAddressRequest) (*GetReceiveAddressResponse, error)
|
||||||
NewAddress(context.Context, *NewAddressRequest) (*NewAddressResponse, error)
|
|
||||||
Shutdown(context.Context, *ShutdownRequest) (*ShutdownResponse, error)
|
Shutdown(context.Context, *ShutdownRequest) (*ShutdownResponse, error)
|
||||||
Broadcast(context.Context, *BroadcastRequest) (*BroadcastResponse, error)
|
Broadcast(context.Context, *BroadcastRequest) (*BroadcastResponse, error)
|
||||||
mustEmbedUnimplementedKaspawalletdServer()
|
mustEmbedUnimplementedKaspawalletdServer()
|
||||||
@@ -105,35 +93,25 @@ type KaspawalletdServer interface {
|
|||||||
type UnimplementedKaspawalletdServer struct {
|
type UnimplementedKaspawalletdServer struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (UnimplementedKaspawalletdServer) GetBalance(context.Context, *GetBalanceRequest) (*GetBalanceResponse, error) {
|
func (*UnimplementedKaspawalletdServer) GetBalance(context.Context, *GetBalanceRequest) (*GetBalanceResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetBalance not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method GetBalance not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedKaspawalletdServer) CreateUnsignedTransaction(context.Context, *CreateUnsignedTransactionRequest) (*CreateUnsignedTransactionResponse, error) {
|
func (*UnimplementedKaspawalletdServer) CreateUnsignedTransaction(context.Context, *CreateUnsignedTransactionRequest) (*CreateUnsignedTransactionResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method CreateUnsignedTransaction not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method CreateUnsignedTransaction not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedKaspawalletdServer) ShowAddresses(context.Context, *ShowAddressesRequest) (*ShowAddressesResponse, error) {
|
func (*UnimplementedKaspawalletdServer) GetReceiveAddress(context.Context, *GetReceiveAddressRequest) (*GetReceiveAddressResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method ShowAddresses not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method GetReceiveAddress not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedKaspawalletdServer) NewAddress(context.Context, *NewAddressRequest) (*NewAddressResponse, error) {
|
func (*UnimplementedKaspawalletdServer) Shutdown(context.Context, *ShutdownRequest) (*ShutdownResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method NewAddress not implemented")
|
|
||||||
}
|
|
||||||
func (UnimplementedKaspawalletdServer) Shutdown(context.Context, *ShutdownRequest) (*ShutdownResponse, error) {
|
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method Shutdown not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method Shutdown not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedKaspawalletdServer) Broadcast(context.Context, *BroadcastRequest) (*BroadcastResponse, error) {
|
func (*UnimplementedKaspawalletdServer) Broadcast(context.Context, *BroadcastRequest) (*BroadcastResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method Broadcast not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method Broadcast not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedKaspawalletdServer) mustEmbedUnimplementedKaspawalletdServer() {}
|
func (*UnimplementedKaspawalletdServer) mustEmbedUnimplementedKaspawalletdServer() {}
|
||||||
|
|
||||||
// UnsafeKaspawalletdServer may be embedded to opt out of forward compatibility for this service.
|
func RegisterKaspawalletdServer(s *grpc.Server, srv KaspawalletdServer) {
|
||||||
// Use of this interface is not recommended, as added methods to KaspawalletdServer will
|
s.RegisterService(&_Kaspawalletd_serviceDesc, srv)
|
||||||
// result in compilation errors.
|
|
||||||
type UnsafeKaspawalletdServer interface {
|
|
||||||
mustEmbedUnimplementedKaspawalletdServer()
|
|
||||||
}
|
|
||||||
|
|
||||||
func RegisterKaspawalletdServer(s grpc.ServiceRegistrar, srv KaspawalletdServer) {
|
|
||||||
s.RegisterService(&Kaspawalletd_ServiceDesc, srv)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func _Kaspawalletd_GetBalance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _Kaspawalletd_GetBalance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
@@ -172,38 +150,20 @@ func _Kaspawalletd_CreateUnsignedTransaction_Handler(srv interface{}, ctx contex
|
|||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func _Kaspawalletd_ShowAddresses_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _Kaspawalletd_GetReceiveAddress_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
in := new(ShowAddressesRequest)
|
in := new(GetReceiveAddressRequest)
|
||||||
if err := dec(in); err != nil {
|
if err := dec(in); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if interceptor == nil {
|
if interceptor == nil {
|
||||||
return srv.(KaspawalletdServer).ShowAddresses(ctx, in)
|
return srv.(KaspawalletdServer).GetReceiveAddress(ctx, in)
|
||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/kaspawalletd/ShowAddresses",
|
FullMethod: "/kaspawalletd/GetReceiveAddress",
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(KaspawalletdServer).ShowAddresses(ctx, req.(*ShowAddressesRequest))
|
return srv.(KaspawalletdServer).GetReceiveAddress(ctx, req.(*GetReceiveAddressRequest))
|
||||||
}
|
|
||||||
return interceptor(ctx, in, info, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
func _Kaspawalletd_NewAddress_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
|
||||||
in := new(NewAddressRequest)
|
|
||||||
if err := dec(in); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if interceptor == nil {
|
|
||||||
return srv.(KaspawalletdServer).NewAddress(ctx, in)
|
|
||||||
}
|
|
||||||
info := &grpc.UnaryServerInfo{
|
|
||||||
Server: srv,
|
|
||||||
FullMethod: "/kaspawalletd/NewAddress",
|
|
||||||
}
|
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
||||||
return srv.(KaspawalletdServer).NewAddress(ctx, req.(*NewAddressRequest))
|
|
||||||
}
|
}
|
||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
@@ -244,10 +204,7 @@ func _Kaspawalletd_Broadcast_Handler(srv interface{}, ctx context.Context, dec f
|
|||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kaspawalletd_ServiceDesc is the grpc.ServiceDesc for Kaspawalletd service.
|
var _Kaspawalletd_serviceDesc = grpc.ServiceDesc{
|
||||||
// It's only intended for direct use with grpc.RegisterService,
|
|
||||||
// and not to be introspected or modified (even as a copy)
|
|
||||||
var Kaspawalletd_ServiceDesc = grpc.ServiceDesc{
|
|
||||||
ServiceName: "kaspawalletd",
|
ServiceName: "kaspawalletd",
|
||||||
HandlerType: (*KaspawalletdServer)(nil),
|
HandlerType: (*KaspawalletdServer)(nil),
|
||||||
Methods: []grpc.MethodDesc{
|
Methods: []grpc.MethodDesc{
|
||||||
@@ -260,12 +217,8 @@ var Kaspawalletd_ServiceDesc = grpc.ServiceDesc{
|
|||||||
Handler: _Kaspawalletd_CreateUnsignedTransaction_Handler,
|
Handler: _Kaspawalletd_CreateUnsignedTransaction_Handler,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
MethodName: "ShowAddresses",
|
MethodName: "GetReceiveAddress",
|
||||||
Handler: _Kaspawalletd_ShowAddresses_Handler,
|
Handler: _Kaspawalletd_GetReceiveAddress_Handler,
|
||||||
},
|
|
||||||
{
|
|
||||||
MethodName: "NewAddress",
|
|
||||||
Handler: _Kaspawalletd_NewAddress_Handler,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
MethodName: "Shutdown",
|
MethodName: "Shutdown",
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package server
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
|
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
|
||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
|
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
|
||||||
"github.com/kaspanet/kaspad/util"
|
"github.com/kaspanet/kaspad/util"
|
||||||
@@ -24,39 +23,13 @@ func (s *server) changeAddress() (util.Address, error) {
|
|||||||
walletAddr := &walletAddress{
|
walletAddr := &walletAddress{
|
||||||
index: s.keysFile.LastUsedInternalIndex(),
|
index: s.keysFile.LastUsedInternalIndex(),
|
||||||
cosignerIndex: s.keysFile.CosignerIndex,
|
cosignerIndex: s.keysFile.CosignerIndex,
|
||||||
keyChain: libkaspawallet.InternalKeychain,
|
keyChain: internalKeychain,
|
||||||
}
|
}
|
||||||
path := s.walletAddressPath(walletAddr)
|
path := s.walletAddressPath(walletAddr)
|
||||||
return libkaspawallet.Address(s.params, s.keysFile.ExtendedPublicKeys, s.keysFile.MinimumSignatures, path, s.keysFile.ECDSA)
|
return libkaspawallet.Address(s.params, s.keysFile.ExtendedPublicKeys, s.keysFile.MinimumSignatures, path, s.keysFile.ECDSA)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) ShowAddresses(_ context.Context, request *pb.ShowAddressesRequest) (*pb.ShowAddressesResponse, error) {
|
func (s *server) GetReceiveAddress(_ context.Context, request *pb.GetReceiveAddressRequest) (*pb.GetReceiveAddressResponse, error) {
|
||||||
s.lock.Lock()
|
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
if !s.isSynced() {
|
|
||||||
return nil, errors.New("server is not synced")
|
|
||||||
}
|
|
||||||
|
|
||||||
addresses := make([]string, 0)
|
|
||||||
for i := uint32(1); i <= s.keysFile.LastUsedExternalIndex(); i++ {
|
|
||||||
walletAddr := &walletAddress{
|
|
||||||
index: i,
|
|
||||||
cosignerIndex: s.keysFile.CosignerIndex,
|
|
||||||
keyChain: libkaspawallet.ExternalKeychain,
|
|
||||||
}
|
|
||||||
path := s.walletAddressPath(walletAddr)
|
|
||||||
address, err := libkaspawallet.Address(s.params, s.keysFile.ExtendedPublicKeys, s.keysFile.MinimumSignatures, path, s.keysFile.ECDSA)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
addresses = append(addresses, address.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return &pb.ShowAddressesResponse{Address: addresses}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) NewAddress(_ context.Context, request *pb.NewAddressRequest) (*pb.NewAddressResponse, error) {
|
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@@ -77,7 +50,7 @@ func (s *server) NewAddress(_ context.Context, request *pb.NewAddressRequest) (*
|
|||||||
walletAddr := &walletAddress{
|
walletAddr := &walletAddress{
|
||||||
index: s.keysFile.LastUsedExternalIndex(),
|
index: s.keysFile.LastUsedExternalIndex(),
|
||||||
cosignerIndex: s.keysFile.CosignerIndex,
|
cosignerIndex: s.keysFile.CosignerIndex,
|
||||||
keyChain: libkaspawallet.ExternalKeychain,
|
keyChain: externalKeychain,
|
||||||
}
|
}
|
||||||
path := s.walletAddressPath(walletAddr)
|
path := s.walletAddressPath(walletAddr)
|
||||||
address, err := libkaspawallet.Address(s.params, s.keysFile.ExtendedPublicKeys, s.keysFile.MinimumSignatures, path, s.keysFile.ECDSA)
|
address, err := libkaspawallet.Address(s.params, s.keysFile.ExtendedPublicKeys, s.keysFile.MinimumSignatures, path, s.keysFile.ECDSA)
|
||||||
@@ -85,7 +58,7 @@ func (s *server) NewAddress(_ context.Context, request *pb.NewAddressRequest) (*
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &pb.NewAddressResponse{Address: address.String()}, nil
|
return &pb.GetReceiveAddressResponse{Address: address.String()}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) walletAddressString(wAddr *walletAddress) (string, error) {
|
func (s *server) walletAddressString(wAddr *walletAddress) (string, error) {
|
||||||
|
|||||||
@@ -2,14 +2,9 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
|
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
|
||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type balancesType struct{ available, pending uint64 }
|
|
||||||
type balancesMapType map[*walletAddress]*balancesType
|
|
||||||
|
|
||||||
func (s *server) GetBalance(_ context.Context, _ *pb.GetBalanceRequest) (*pb.GetBalanceResponse, error) {
|
func (s *server) GetBalance(_ context.Context, _ *pb.GetBalanceRequest) (*pb.GetBalanceResponse, error) {
|
||||||
s.lock.RLock()
|
s.lock.RLock()
|
||||||
defer s.lock.RUnlock()
|
defer s.lock.RUnlock()
|
||||||
@@ -18,47 +13,19 @@ func (s *server) GetBalance(_ context.Context, _ *pb.GetBalanceRequest) (*pb.Get
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
daaScore := dagInfo.VirtualDAAScore
|
|
||||||
maturity := s.params.BlockCoinbaseMaturity
|
|
||||||
|
|
||||||
balancesMap := make(balancesMapType, 0)
|
var availableBalance, pendingBalance uint64
|
||||||
for _, entry := range s.utxosSortedByAmount {
|
for _, entry := range s.utxos {
|
||||||
amount := entry.UTXOEntry.Amount()
|
if isUTXOSpendable(entry, dagInfo.VirtualDAAScore, s.params.BlockCoinbaseMaturity) {
|
||||||
address := entry.address
|
availableBalance += entry.UTXOEntry.Amount()
|
||||||
balances, ok := balancesMap[address]
|
|
||||||
if !ok {
|
|
||||||
balances = new(balancesType)
|
|
||||||
balancesMap[address] = balances
|
|
||||||
}
|
|
||||||
if isUTXOSpendable(entry, daaScore, maturity) {
|
|
||||||
balances.available += amount
|
|
||||||
} else {
|
} else {
|
||||||
balances.pending += amount
|
pendingBalance += entry.UTXOEntry.Amount()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addressBalances := make([]*pb.AddressBalances, len(balancesMap))
|
|
||||||
i := 0
|
|
||||||
var available, pending uint64
|
|
||||||
for walletAddress, balances := range balancesMap {
|
|
||||||
address, err := libkaspawallet.Address(s.params, s.keysFile.ExtendedPublicKeys, s.keysFile.MinimumSignatures, s.walletAddressPath(walletAddress), s.keysFile.ECDSA)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
addressBalances[i] = &pb.AddressBalances{
|
|
||||||
Address: address.String(),
|
|
||||||
Available: balances.available,
|
|
||||||
Pending: balances.pending,
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
available += balances.available
|
|
||||||
pending += balances.pending
|
|
||||||
}
|
|
||||||
|
|
||||||
return &pb.GetBalanceResponse{
|
return &pb.GetBalanceResponse{
|
||||||
Available: available,
|
Available: availableBalance,
|
||||||
Pending: pending,
|
Pending: pendingBalance,
|
||||||
AddressBalances: addressBalances,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
|
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
|
||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
|
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
||||||
@@ -18,7 +17,7 @@ func (s *server) CreateUnsignedTransaction(_ context.Context, request *pb.Create
|
|||||||
return nil, errors.New("server is not synced")
|
return nil, errors.New("server is not synced")
|
||||||
}
|
}
|
||||||
|
|
||||||
err := s.refreshUTXOs()
|
err := s.refreshExistingUTXOs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -67,7 +66,7 @@ func (s *server) selectUTXOs(spendAmount uint64, feePerInput uint64) (
|
|||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, utxo := range s.utxosSortedByAmount {
|
for _, utxo := range s.utxos {
|
||||||
if !isUTXOSpendable(utxo, dagInfo.VirtualDAAScore, s.params.BlockCoinbaseMaturity) {
|
if !isUTXOSpendable(utxo, dagInfo.VirtualDAAScore, s.params.BlockCoinbaseMaturity) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,9 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/util/profiling"
|
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
|
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
|
||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/keys"
|
"github.com/kaspanet/kaspad/cmd/kaspawallet/keys"
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
"github.com/kaspanet/kaspad/domain/dagconfig"
|
"github.com/kaspanet/kaspad/domain/dagconfig"
|
||||||
"github.com/kaspanet/kaspad/infrastructure/network/rpcclient"
|
"github.com/kaspanet/kaspad/infrastructure/network/rpcclient"
|
||||||
"github.com/kaspanet/kaspad/infrastructure/os/signal"
|
"github.com/kaspanet/kaspad/infrastructure/os/signal"
|
||||||
@@ -26,25 +25,20 @@ type server struct {
|
|||||||
rpcClient *rpcclient.RPCClient
|
rpcClient *rpcclient.RPCClient
|
||||||
params *dagconfig.Params
|
params *dagconfig.Params
|
||||||
|
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
utxosSortedByAmount []*walletUTXO
|
utxos map[externalapi.DomainOutpoint]*walletUTXO
|
||||||
nextSyncStartIndex uint32
|
nextSyncStartIndex uint32
|
||||||
keysFile *keys.File
|
keysFile *keys.File
|
||||||
shutdown chan struct{}
|
shutdown chan struct{}
|
||||||
addressSet walletAddressSet
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start starts the kaspawalletd server
|
// Start starts the kaspawalletd server
|
||||||
func Start(params *dagconfig.Params, listen, rpcServer string, keysFilePath string, profile string) error {
|
func Start(params *dagconfig.Params, listen, rpcServer string, keysFilePath string) error {
|
||||||
initLog(defaultLogFile, defaultErrLogFile)
|
initLog(defaultLogFile, defaultErrLogFile)
|
||||||
|
|
||||||
defer panics.HandlePanic(log, "MAIN", nil)
|
defer panics.HandlePanic(log, "MAIN", nil)
|
||||||
interrupt := signal.InterruptListener()
|
interrupt := signal.InterruptListener()
|
||||||
|
|
||||||
if profile != "" {
|
|
||||||
profiling.Start(profile, log)
|
|
||||||
}
|
|
||||||
|
|
||||||
listener, err := net.Listen("tcp", listen)
|
listener, err := net.Listen("tcp", listen)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return (errors.Wrapf(err, "Error listening to tcp at %s", listen))
|
return (errors.Wrapf(err, "Error listening to tcp at %s", listen))
|
||||||
@@ -62,13 +56,12 @@ func Start(params *dagconfig.Params, listen, rpcServer string, keysFilePath stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
serverInstance := &server{
|
serverInstance := &server{
|
||||||
rpcClient: rpcClient,
|
rpcClient: rpcClient,
|
||||||
params: params,
|
params: params,
|
||||||
utxosSortedByAmount: []*walletUTXO{},
|
utxos: make(map[externalapi.DomainOutpoint]*walletUTXO),
|
||||||
nextSyncStartIndex: 0,
|
nextSyncStartIndex: 0,
|
||||||
keysFile: keysFile,
|
keysFile: keysFile,
|
||||||
shutdown: make(chan struct{}),
|
shutdown: make(chan struct{}),
|
||||||
addressSet: make(walletAddressSet),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spawn("serverInstance.sync", func() {
|
spawn("serverInstance.sync", func() {
|
||||||
|
|||||||
@@ -1,16 +1,20 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sort"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
|
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
"github.com/kaspanet/kaspad/app/appmessage"
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var keyChains = []uint8{libkaspawallet.ExternalKeychain, libkaspawallet.InternalKeychain}
|
const (
|
||||||
|
// externalKeychain is the key chain that is used to create receive addresses
|
||||||
|
externalKeychain = 0
|
||||||
|
// internalKeychain is used to create change addresses
|
||||||
|
internalKeychain = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
var keyChains = []uint8{externalKeychain, internalKeychain}
|
||||||
|
|
||||||
type walletAddressSet map[string]*walletAddress
|
type walletAddressSet map[string]*walletAddress
|
||||||
|
|
||||||
@@ -27,18 +31,17 @@ func (s *server) sync() error {
|
|||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
err := s.collectRecentAddresses()
|
err := s.collectUTXOsFromRecentAddresses()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.collectFarAddresses()
|
err = s.collectUTXOsFromFarAddresses()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.refreshExistingUTXOsWithLock()
|
err = s.refreshExistingUTXOsWithLock()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -75,12 +78,12 @@ func (s *server) addressesToQuery(start, end uint32) (walletAddressSet, error) {
|
|||||||
return addresses, nil
|
return addresses, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// collectFarAddresses collects numIndexesToQuery addresses
|
// collectUTXOsFromFarAddresses collects numIndexesToQuery UTXOs
|
||||||
// from the last point it stopped in the previous call.
|
// from the last point it stopped in the previous call.
|
||||||
func (s *server) collectFarAddresses() error {
|
func (s *server) collectUTXOsFromFarAddresses() error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
err := s.collectAddresses(s.nextSyncStartIndex, s.nextSyncStartIndex+numIndexesToQuery)
|
err := s.collectUTXOs(s.nextSyncStartIndex, s.nextSyncStartIndex+numIndexesToQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -101,14 +104,14 @@ func (s *server) maxUsedIndex() uint32 {
|
|||||||
return maxUsedIndex
|
return maxUsedIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
// collectRecentAddresses collects addresses from used addresses until
|
// collectUTXOsFromRecentAddresses collects UTXOs from used addresses until
|
||||||
// the address with the index of the last used address + 1000.
|
// the address with the index of the last used address + 1000.
|
||||||
// collectRecentAddresses scans addresses in batches of numIndexesToQuery,
|
// collectUTXOsFromRecentAddresses scans addresses in batches of numIndexesToQuery,
|
||||||
// and releases the lock between scans.
|
// and releases the lock between scans.
|
||||||
func (s *server) collectRecentAddresses() error {
|
func (s *server) collectUTXOsFromRecentAddresses() error {
|
||||||
maxUsedIndex := s.maxUsedIndex()
|
maxUsedIndex := s.maxUsedIndex()
|
||||||
for i := uint32(0); i < maxUsedIndex+1000; i += numIndexesToQuery {
|
for i := uint32(0); i < maxUsedIndex+1000; i += numIndexesToQuery {
|
||||||
err := s.collectAddressesWithLock(i, i+numIndexesToQuery)
|
err := s.collectUTXOsWithLock(i, i+numIndexesToQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -117,25 +120,30 @@ func (s *server) collectRecentAddresses() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) collectAddressesWithLock(start, end uint32) error {
|
func (s *server) collectUTXOsWithLock(start, end uint32) error {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
return s.collectAddresses(start, end)
|
return s.collectUTXOs(start, end)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) collectAddresses(start, end uint32) error {
|
func (s *server) collectUTXOs(start, end uint32) error {
|
||||||
addressSet, err := s.addressesToQuery(start, end)
|
addressSet, err := s.addressesToQuery(start, end)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
getBalancesByAddressesResponse, err := s.rpcClient.GetBalancesByAddresses(addressSet.strings())
|
getUTXOsByAddressesResponse, err := s.rpcClient.GetUTXOsByAddresses(addressSet.strings())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.updateAddressesAndLastUsedIndexes(addressSet, getBalancesByAddressesResponse)
|
err = s.updateLastUsedIndexes(addressSet, getUTXOsByAddressesResponse)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.updateUTXOs(addressSet, getUTXOsByAddressesResponse)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -143,29 +151,36 @@ func (s *server) collectAddresses(start, end uint32) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) updateAddressesAndLastUsedIndexes(requestedAddressSet walletAddressSet,
|
func (s *server) updateUTXOs(addressSet walletAddressSet,
|
||||||
getBalancesByAddressesResponse *appmessage.GetBalancesByAddressesResponseMessage) error {
|
getUTXOsByAddressesResponse *appmessage.GetUTXOsByAddressesResponseMessage) error {
|
||||||
|
|
||||||
|
for _, entry := range getUTXOsByAddressesResponse.Entries {
|
||||||
|
err := s.addEntryToUTXOSet(entry, addressSet)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *server) updateLastUsedIndexes(addressSet walletAddressSet,
|
||||||
|
getUTXOsByAddressesResponse *appmessage.GetUTXOsByAddressesResponseMessage) error {
|
||||||
|
|
||||||
lastUsedExternalIndex := s.keysFile.LastUsedExternalIndex()
|
lastUsedExternalIndex := s.keysFile.LastUsedExternalIndex()
|
||||||
lastUsedInternalIndex := s.keysFile.LastUsedInternalIndex()
|
lastUsedInternalIndex := s.keysFile.LastUsedInternalIndex()
|
||||||
|
|
||||||
for _, entry := range getBalancesByAddressesResponse.Entries {
|
for _, entry := range getUTXOsByAddressesResponse.Entries {
|
||||||
walletAddress, ok := requestedAddressSet[entry.Address]
|
walletAddress, ok := addressSet[entry.Address]
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.Errorf("Got result from address %s even though it wasn't requested", entry.Address)
|
return errors.Errorf("Got result from address %s even though it wasn't requested", entry.Address)
|
||||||
}
|
}
|
||||||
|
|
||||||
if entry.Balance == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if walletAddress.cosignerIndex != s.keysFile.CosignerIndex {
|
if walletAddress.cosignerIndex != s.keysFile.CosignerIndex {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
s.addressSet[entry.Address] = walletAddress
|
if walletAddress.keyChain == externalKeychain {
|
||||||
|
|
||||||
if walletAddress.keyChain == libkaspawallet.ExternalKeychain {
|
|
||||||
if walletAddress.index > lastUsedExternalIndex {
|
if walletAddress.index > lastUsedExternalIndex {
|
||||||
lastUsedExternalIndex = walletAddress.index
|
lastUsedExternalIndex = walletAddress.index
|
||||||
}
|
}
|
||||||
@@ -189,49 +204,58 @@ func (s *server) refreshExistingUTXOsWithLock() error {
|
|||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
return s.refreshUTXOs()
|
return s.refreshExistingUTXOs()
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateUTXOSet clears the current UTXO set, and re-fills it with the given entries
|
func (s *server) addEntryToUTXOSet(entry *appmessage.UTXOsByAddressesEntry, addressSet walletAddressSet) error {
|
||||||
func (s *server) updateUTXOSet(entries []*appmessage.UTXOsByAddressesEntry) error {
|
outpoint, err := appmessage.RPCOutpointToDomainOutpoint(entry.Outpoint)
|
||||||
utxos := make([]*walletUTXO, len(entries))
|
|
||||||
|
|
||||||
for i, entry := range entries {
|
|
||||||
outpoint, err := appmessage.RPCOutpointToDomainOutpoint(entry.Outpoint)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
utxoEntry, err := appmessage.RPCUTXOEntryToUTXOEntry(entry.UTXOEntry)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
address, ok := s.addressSet[entry.Address]
|
|
||||||
if !ok {
|
|
||||||
return errors.Errorf("Got result from address %s even though it wasn't requested", entry.Address)
|
|
||||||
}
|
|
||||||
utxos[i] = &walletUTXO{
|
|
||||||
Outpoint: outpoint,
|
|
||||||
UTXOEntry: utxoEntry,
|
|
||||||
address: address,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Slice(utxos, func(i, j int) bool { return utxos[i].UTXOEntry.Amount() > utxos[j].UTXOEntry.Amount() })
|
|
||||||
|
|
||||||
s.utxosSortedByAmount = utxos
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) refreshUTXOs() error {
|
|
||||||
getUTXOsByAddressesResponse, err := s.rpcClient.GetUTXOsByAddresses(s.addressSet.strings())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.updateUTXOSet(getUTXOsByAddressesResponse.Entries)
|
utxoEntry, err := appmessage.RPCUTXOEntryToUTXOEntry(entry.UTXOEntry)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
address, ok := addressSet[entry.Address]
|
||||||
|
if !ok {
|
||||||
|
return errors.Errorf("Got result from address %s even though it wasn't requested", entry.Address)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.utxos[*outpoint] = &walletUTXO{
|
||||||
|
Outpoint: outpoint,
|
||||||
|
UTXOEntry: utxoEntry,
|
||||||
|
address: address,
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *server) refreshExistingUTXOs() error {
|
||||||
|
addressSet := make(walletAddressSet, len(s.utxos))
|
||||||
|
for _, utxo := range s.utxos {
|
||||||
|
addressString, err := s.walletAddressString(utxo.address)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
addressSet[addressString] = utxo.address
|
||||||
|
}
|
||||||
|
|
||||||
|
getUTXOsByAddressesResponse, err := s.rpcClient.GetUTXOsByAddresses(addressSet.strings())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.utxos = make(map[externalapi.DomainOutpoint]*walletUTXO, len(getUTXOsByAddressesResponse.Entries))
|
||||||
|
for _, entry := range getUTXOsByAddressesResponse.Entries {
|
||||||
|
err := s.addEntryToUTXOSet(entry, addressSet)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) isSynced() bool {
|
func (s *server) isSynced() bool {
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ func encryptMnemonic(mnemonic string, password []byte) (*EncryptedMnemonic, erro
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
aead, err := getAEAD(defaultNumThreads, password, salt)
|
aead, err := getAEAD(password, salt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,10 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/kaspanet/kaspad/cmd/kaspawallet/utils"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/utils"
|
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/domain/dagconfig"
|
"github.com/kaspanet/kaspad/domain/dagconfig"
|
||||||
"github.com/kaspanet/kaspad/util"
|
"github.com/kaspanet/kaspad/util"
|
||||||
@@ -24,9 +22,6 @@ var (
|
|||||||
defaultAppDir = util.AppDir("kaspawallet", false)
|
defaultAppDir = util.AppDir("kaspawallet", false)
|
||||||
)
|
)
|
||||||
|
|
||||||
// LastVersion is the most up to date file format version
|
|
||||||
const LastVersion = 1
|
|
||||||
|
|
||||||
func defaultKeysFile(netParams *dagconfig.Params) string {
|
func defaultKeysFile(netParams *dagconfig.Params) string {
|
||||||
return filepath.Join(defaultAppDir, netParams.Name, "keys.json")
|
return filepath.Join(defaultAppDir, netParams.Name, "keys.json")
|
||||||
}
|
}
|
||||||
@@ -37,8 +32,6 @@ type encryptedPrivateKeyJSON struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type keysFileJSON struct {
|
type keysFileJSON struct {
|
||||||
Version uint32 `json:"version"`
|
|
||||||
NumThreads uint8 `json:"numThreads,omitempty"` // This field is ignored for versions different from 0. See more details at the function `numThreads`.
|
|
||||||
EncryptedPrivateKeys []*encryptedPrivateKeyJSON `json:"encryptedMnemonics"`
|
EncryptedPrivateKeys []*encryptedPrivateKeyJSON `json:"encryptedMnemonics"`
|
||||||
ExtendedPublicKeys []string `json:"publicKeys"`
|
ExtendedPublicKeys []string `json:"publicKeys"`
|
||||||
MinimumSignatures uint32 `json:"minimumSignatures"`
|
MinimumSignatures uint32 `json:"minimumSignatures"`
|
||||||
@@ -56,8 +49,6 @@ type EncryptedMnemonic struct {
|
|||||||
|
|
||||||
// File holds all the data related to the wallet keys
|
// File holds all the data related to the wallet keys
|
||||||
type File struct {
|
type File struct {
|
||||||
Version uint32
|
|
||||||
NumThreads uint8 // This field is ignored for versions different than 0
|
|
||||||
EncryptedMnemonics []*EncryptedMnemonic
|
EncryptedMnemonics []*EncryptedMnemonic
|
||||||
ExtendedPublicKeys []string
|
ExtendedPublicKeys []string
|
||||||
MinimumSignatures uint32
|
MinimumSignatures uint32
|
||||||
@@ -78,8 +69,6 @@ func (d *File) toJSON() *keysFileJSON {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &keysFileJSON{
|
return &keysFileJSON{
|
||||||
Version: d.Version,
|
|
||||||
NumThreads: d.NumThreads,
|
|
||||||
EncryptedPrivateKeys: encryptedPrivateKeysJSON,
|
EncryptedPrivateKeys: encryptedPrivateKeysJSON,
|
||||||
ExtendedPublicKeys: d.ExtendedPublicKeys,
|
ExtendedPublicKeys: d.ExtendedPublicKeys,
|
||||||
MinimumSignatures: d.MinimumSignatures,
|
MinimumSignatures: d.MinimumSignatures,
|
||||||
@@ -90,26 +79,7 @@ func (d *File) toJSON() *keysFileJSON {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFileFromMnemonic generates a new File from the given mnemonic string
|
|
||||||
func NewFileFromMnemonic(params *dagconfig.Params, mnemonic string, password string) (*File, error) {
|
|
||||||
encryptedMnemonics, extendedPublicKeys, err :=
|
|
||||||
encryptedMnemonicExtendedPublicKeyPairs(params, []string{mnemonic}, password, false)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &File{
|
|
||||||
Version: LastVersion,
|
|
||||||
NumThreads: defaultNumThreads,
|
|
||||||
EncryptedMnemonics: encryptedMnemonics,
|
|
||||||
ExtendedPublicKeys: extendedPublicKeys,
|
|
||||||
MinimumSignatures: 1,
|
|
||||||
ECDSA: false,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *File) fromJSON(fileJSON *keysFileJSON) error {
|
func (d *File) fromJSON(fileJSON *keysFileJSON) error {
|
||||||
d.Version = fileJSON.Version
|
|
||||||
d.NumThreads = fileJSON.NumThreads
|
|
||||||
d.MinimumSignatures = fileJSON.MinimumSignatures
|
d.MinimumSignatures = fileJSON.MinimumSignatures
|
||||||
d.ECDSA = fileJSON.ECDSA
|
d.ECDSA = fileJSON.ECDSA
|
||||||
d.ExtendedPublicKeys = fileJSON.ExtendedPublicKeys
|
d.ExtendedPublicKeys = fileJSON.ExtendedPublicKeys
|
||||||
@@ -211,20 +181,10 @@ func (d *File) DecryptMnemonics(cmdLinePassword string) ([]string, error) {
|
|||||||
if len(password) == 0 {
|
if len(password) == 0 {
|
||||||
password = getPassword("Password:")
|
password = getPassword("Password:")
|
||||||
}
|
}
|
||||||
|
|
||||||
var numThreads uint8
|
|
||||||
if len(d.EncryptedMnemonics) > 0 {
|
|
||||||
var err error
|
|
||||||
numThreads, err = d.numThreads(password)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
privateKeys := make([]string, len(d.EncryptedMnemonics))
|
privateKeys := make([]string, len(d.EncryptedMnemonics))
|
||||||
for i, encryptedPrivateKey := range d.EncryptedMnemonics {
|
for i, encryptedPrivateKey := range d.EncryptedMnemonics {
|
||||||
var err error
|
var err error
|
||||||
privateKeys[i], err = decryptMnemonic(numThreads, encryptedPrivateKey, password)
|
privateKeys[i], err = decryptMnemonic(encryptedPrivateKey, password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -318,72 +278,13 @@ func (d *File) Save() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultNumThreads = 8
|
func getAEAD(password, salt []byte) (cipher.AEAD, error) {
|
||||||
|
key := argon2.IDKey(password, salt, 1, 64*1024, uint8(runtime.NumCPU()), 32)
|
||||||
func (d *File) numThreads(password []byte) (uint8, error) {
|
|
||||||
// There's a bug in v0 wallets where the number of threads
|
|
||||||
// was determined by the number of logical CPUs at the machine,
|
|
||||||
// which made the authentication non-deterministic across platforms.
|
|
||||||
// In order to solve it we introduce v1 where the number of threads
|
|
||||||
// is constant, and brute force the number of threads in v0. After we
|
|
||||||
// find the right amount via brute force we save the result to the file.
|
|
||||||
|
|
||||||
if d.Version != 0 {
|
|
||||||
return defaultNumThreads, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
numThreads, err := d.detectNumThreads(password, d.EncryptedMnemonics[0])
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
d.NumThreads = numThreads
|
|
||||||
err = d.Save()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return numThreads, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *File) detectNumThreads(password []byte, encryptedMnemonic *EncryptedMnemonic) (uint8, error) {
|
|
||||||
firstGuessNumThreads := d.NumThreads
|
|
||||||
if d.NumThreads == 0 {
|
|
||||||
firstGuessNumThreads = uint8(runtime.NumCPU())
|
|
||||||
}
|
|
||||||
_, err := decryptMnemonic(firstGuessNumThreads, encryptedMnemonic, password)
|
|
||||||
if err != nil {
|
|
||||||
if !strings.Contains(err.Error(), "message authentication failed") {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return firstGuessNumThreads, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for numThreadsGuess := uint8(1); ; numThreadsGuess++ {
|
|
||||||
if numThreadsGuess == firstGuessNumThreads {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := decryptMnemonic(numThreadsGuess, encryptedMnemonic, password)
|
|
||||||
if err != nil {
|
|
||||||
const maxTries = 255
|
|
||||||
if numThreadsGuess == maxTries || !strings.Contains(err.Error(), "message authentication failed") {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return numThreadsGuess, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAEAD(threads uint8, password, salt []byte) (cipher.AEAD, error) {
|
|
||||||
key := argon2.IDKey(password, salt, 1, 64*1024, threads, 32)
|
|
||||||
return chacha20poly1305.NewX(key)
|
return chacha20poly1305.NewX(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func decryptMnemonic(numThreads uint8, encryptedPrivateKey *EncryptedMnemonic, password []byte) (string, error) {
|
func decryptMnemonic(encryptedPrivateKey *EncryptedMnemonic, password []byte) (string, error) {
|
||||||
aead, err := getAEAD(numThreads, password, encryptedPrivateKey.salt)
|
aead, err := getAEAD(password, encryptedPrivateKey.salt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
package libkaspawallet
|
|
||||||
|
|
||||||
const (
|
|
||||||
// ExternalKeychain is the key chain that is used to create receive addresses
|
|
||||||
ExternalKeychain = 0
|
|
||||||
// InternalKeychain is used to create change addresses
|
|
||||||
InternalKeychain = 1
|
|
||||||
)
|
|
||||||
@@ -163,7 +163,7 @@ func TestMultisig(t *testing.T) {
|
|||||||
t.Fatalf("Expected extractedSignedTxOneStep and extractedSignedTxStep2 IDs to be equal")
|
t.Fatalf("Expected extractedSignedTxOneStep and extractedSignedTxStep2 IDs to be equal")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, virtualChangeSet, err := tc.AddBlock([]*externalapi.DomainHash{block1Hash}, nil, []*externalapi.DomainTransaction{extractedSignedTxStep2})
|
_, insertionResult, err := tc.AddBlock([]*externalapi.DomainHash{block1Hash}, nil, []*externalapi.DomainTransaction{extractedSignedTxStep2})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("AddBlock: %+v", err)
|
t.Fatalf("AddBlock: %+v", err)
|
||||||
}
|
}
|
||||||
@@ -172,7 +172,7 @@ func TestMultisig(t *testing.T) {
|
|||||||
TransactionID: *consensushashing.TransactionID(extractedSignedTxStep2),
|
TransactionID: *consensushashing.TransactionID(extractedSignedTxStep2),
|
||||||
Index: 0,
|
Index: 0,
|
||||||
}
|
}
|
||||||
if !virtualChangeSet.VirtualUTXODiff.ToAdd().Contains(addedUTXO) {
|
if !insertionResult.VirtualUTXODiff.ToAdd().Contains(addedUTXO) {
|
||||||
t.Fatalf("Transaction wasn't accepted in the DAG")
|
t.Fatalf("Transaction wasn't accepted in the DAG")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -294,7 +294,7 @@ func TestP2PK(t *testing.T) {
|
|||||||
t.Fatalf("ExtractTransaction: %+v", err)
|
t.Fatalf("ExtractTransaction: %+v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, virtualChangeSet, err := tc.AddBlock([]*externalapi.DomainHash{block1Hash}, nil, []*externalapi.DomainTransaction{tx})
|
_, insertionResult, err := tc.AddBlock([]*externalapi.DomainHash{block1Hash}, nil, []*externalapi.DomainTransaction{tx})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("AddBlock: %+v", err)
|
t.Fatalf("AddBlock: %+v", err)
|
||||||
}
|
}
|
||||||
@@ -303,7 +303,7 @@ func TestP2PK(t *testing.T) {
|
|||||||
TransactionID: *consensushashing.TransactionID(tx),
|
TransactionID: *consensushashing.TransactionID(tx),
|
||||||
Index: 0,
|
Index: 0,
|
||||||
}
|
}
|
||||||
if !virtualChangeSet.VirtualUTXODiff.ToAdd().Contains(addedUTXO) {
|
if !insertionResult.VirtualUTXODiff.ToAdd().Contains(addedUTXO) {
|
||||||
t.Fatalf("Transaction wasn't accepted in the DAG")
|
t.Fatalf("Transaction wasn't accepted in the DAG")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -19,12 +19,8 @@ func main() {
|
|||||||
err = sign(config.(*signConfig))
|
err = sign(config.(*signConfig))
|
||||||
case broadcastSubCmd:
|
case broadcastSubCmd:
|
||||||
err = broadcast(config.(*broadcastConfig))
|
err = broadcast(config.(*broadcastConfig))
|
||||||
case parseSubCmd:
|
case showAddressSubCmd:
|
||||||
err = parse(config.(*parseConfig))
|
err = showAddress(config.(*showAddressConfig))
|
||||||
case showAddressesSubCmd:
|
|
||||||
err = showAddresses(config.(*showAddressesConfig))
|
|
||||||
case newAddressSubCmd:
|
|
||||||
err = newAddress(config.(*newAddressConfig))
|
|
||||||
case dumpUnencryptedDataSubCmd:
|
case dumpUnencryptedDataSubCmd:
|
||||||
err = dumpUnencryptedData(config.(*dumpUnencryptedDataConfig))
|
err = dumpUnencryptedData(config.(*dumpUnencryptedDataConfig))
|
||||||
case startDaemonSubCmd:
|
case startDaemonSubCmd:
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet/serialization"
|
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"io/ioutil"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func parse(conf *parseConfig) error {
|
|
||||||
if conf.Transaction == "" && conf.TransactionFile == "" {
|
|
||||||
return errors.Errorf("Either --transaction or --transaction-file is required")
|
|
||||||
}
|
|
||||||
if conf.Transaction != "" && conf.TransactionFile != "" {
|
|
||||||
return errors.Errorf("Both --transaction and --transaction-file cannot be passed at the same time")
|
|
||||||
}
|
|
||||||
|
|
||||||
transactionHex := conf.Transaction
|
|
||||||
if conf.TransactionFile != "" {
|
|
||||||
transactionHexBytes, err := ioutil.ReadFile(conf.TransactionFile)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "Could not read hex from %s", conf.TransactionFile)
|
|
||||||
}
|
|
||||||
transactionHex = strings.TrimSpace(string(transactionHexBytes))
|
|
||||||
}
|
|
||||||
|
|
||||||
transaction, err := hex.DecodeString(transactionHex)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
partiallySignedTransaction, err := serialization.DeserializePartiallySignedTransaction(transaction)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Transaction ID: \t%s\n", consensushashing.TransactionID(partiallySignedTransaction.Tx))
|
|
||||||
fmt.Println()
|
|
||||||
|
|
||||||
allInputSompi := uint64(0)
|
|
||||||
for index, input := range partiallySignedTransaction.Tx.Inputs {
|
|
||||||
partiallySignedInput := partiallySignedTransaction.PartiallySignedInputs[index]
|
|
||||||
|
|
||||||
if conf.Verbose {
|
|
||||||
fmt.Printf("Input %d: \tOutpoint: %s:%d \tAmount: %.2f Kaspa\n", index, input.PreviousOutpoint.TransactionID,
|
|
||||||
input.PreviousOutpoint.Index, float64(partiallySignedInput.PrevOutput.Value)/float64(constants.SompiPerKaspa))
|
|
||||||
}
|
|
||||||
|
|
||||||
allInputSompi += partiallySignedInput.PrevOutput.Value
|
|
||||||
}
|
|
||||||
if conf.Verbose {
|
|
||||||
fmt.Println()
|
|
||||||
}
|
|
||||||
|
|
||||||
allOutputSompi := uint64(0)
|
|
||||||
for index, output := range partiallySignedTransaction.Tx.Outputs {
|
|
||||||
scriptPublicKeyType, scriptPublicKeyAddress, err := txscript.ExtractScriptPubKeyAddress(output.ScriptPublicKey, conf.ActiveNetParams)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
addressString := scriptPublicKeyAddress.EncodeAddress()
|
|
||||||
if scriptPublicKeyType == txscript.NonStandardTy {
|
|
||||||
scriptPublicKeyHex := hex.EncodeToString(output.ScriptPublicKey.Script)
|
|
||||||
addressString = fmt.Sprintf("<Non-standard transaction script public key: %s>", scriptPublicKeyHex)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Output %d: \tRecipient: %s \tAmount: %.2f Kaspa\n",
|
|
||||||
index, addressString, float64(output.Value)/float64(constants.SompiPerKaspa))
|
|
||||||
|
|
||||||
allOutputSompi += output.Value
|
|
||||||
}
|
|
||||||
fmt.Println()
|
|
||||||
|
|
||||||
fmt.Printf("Fee:\t%d Sompi\n", allInputSompi-allOutputSompi)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
|
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newAddress(conf *newAddressConfig) error {
|
func showAddress(conf *showAddressConfig) error {
|
||||||
daemonClient, tearDown, err := client.Connect(conf.DaemonAddress)
|
daemonClient, tearDown, err := client.Connect(conf.DaemonAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -17,11 +17,11 @@ func newAddress(conf *newAddressConfig) error {
|
|||||||
ctx, cancel := context.WithTimeout(context.Background(), daemonTimeout)
|
ctx, cancel := context.WithTimeout(context.Background(), daemonTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
response, err := daemonClient.NewAddress(ctx, &pb.NewAddressRequest{})
|
response, err := daemonClient.GetReceiveAddress(ctx, &pb.GetReceiveAddressRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("New address:\n%s\n", response.Address)
|
fmt.Printf("Address:\n%s\n", response.Address)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/client"
|
|
||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/pb"
|
|
||||||
)
|
|
||||||
|
|
||||||
func showAddresses(conf *showAddressesConfig) error {
|
|
||||||
daemonClient, tearDown, err := client.Connect(conf.DaemonAddress)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer tearDown()
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), daemonTimeout)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
response, err := daemonClient.ShowAddresses(ctx, &pb.ShowAddressesRequest{})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Addresses (%d):\n", len(response.Address))
|
|
||||||
for _, address := range response.Address {
|
|
||||||
fmt.Println(address)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -5,9 +5,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/keys"
|
"github.com/kaspanet/kaspad/cmd/kaspawallet/keys"
|
||||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
|
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"io/ioutil"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func sign(conf *signConfig) error {
|
func sign(conf *signConfig) error {
|
||||||
@@ -16,23 +13,7 @@ func sign(conf *signConfig) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if conf.Transaction == "" && conf.TransactionFile == "" {
|
partiallySignedTransaction, err := hex.DecodeString(conf.Transaction)
|
||||||
return errors.Errorf("Either --transaction or --transaction-file is required")
|
|
||||||
}
|
|
||||||
if conf.Transaction != "" && conf.TransactionFile != "" {
|
|
||||||
return errors.Errorf("Both --transaction and --transaction-file cannot be passed at the same time")
|
|
||||||
}
|
|
||||||
|
|
||||||
transactionHex := conf.Transaction
|
|
||||||
if conf.TransactionFile != "" {
|
|
||||||
transactionHexBytes, err := ioutil.ReadFile(conf.TransactionFile)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "Could not read hex from %s", conf.TransactionFile)
|
|
||||||
}
|
|
||||||
transactionHex = strings.TrimSpace(string(transactionHexBytes))
|
|
||||||
}
|
|
||||||
|
|
||||||
partiallySignedTransaction, err := hex.DecodeString(transactionHex)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ package main
|
|||||||
import "github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/server"
|
import "github.com/kaspanet/kaspad/cmd/kaspawallet/daemon/server"
|
||||||
|
|
||||||
func startDaemon(conf *startDaemonConfig) error {
|
func startDaemon(conf *startDaemonConfig) error {
|
||||||
return server.Start(conf.NetParams(), conf.Listen, conf.RPCServer, conf.KeysFile, conf.Profile)
|
return server.Start(conf.NetParams(), conf.Listen, conf.RPCServer, conf.KeysFile)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,25 +39,24 @@ type consensus struct {
|
|||||||
finalityManager model.FinalityManager
|
finalityManager model.FinalityManager
|
||||||
pruningProofManager model.PruningProofManager
|
pruningProofManager model.PruningProofManager
|
||||||
|
|
||||||
acceptanceDataStore model.AcceptanceDataStore
|
acceptanceDataStore model.AcceptanceDataStore
|
||||||
blockStore model.BlockStore
|
blockStore model.BlockStore
|
||||||
blockHeaderStore model.BlockHeaderStore
|
blockHeaderStore model.BlockHeaderStore
|
||||||
pruningStore model.PruningStore
|
pruningStore model.PruningStore
|
||||||
ghostdagDataStores []model.GHOSTDAGDataStore
|
ghostdagDataStores []model.GHOSTDAGDataStore
|
||||||
blockRelationStores []model.BlockRelationStore
|
blockRelationStores []model.BlockRelationStore
|
||||||
blockStatusStore model.BlockStatusStore
|
blockStatusStore model.BlockStatusStore
|
||||||
consensusStateStore model.ConsensusStateStore
|
consensusStateStore model.ConsensusStateStore
|
||||||
headersSelectedTipStore model.HeaderSelectedTipStore
|
headersSelectedTipStore model.HeaderSelectedTipStore
|
||||||
multisetStore model.MultisetStore
|
multisetStore model.MultisetStore
|
||||||
reachabilityDataStores []model.ReachabilityDataStore
|
reachabilityDataStores []model.ReachabilityDataStore
|
||||||
utxoDiffStore model.UTXODiffStore
|
utxoDiffStore model.UTXODiffStore
|
||||||
finalityStore model.FinalityStore
|
finalityStore model.FinalityStore
|
||||||
headersSelectedChainStore model.HeadersSelectedChainStore
|
headersSelectedChainStore model.HeadersSelectedChainStore
|
||||||
daaBlocksStore model.DAABlocksStore
|
daaBlocksStore model.DAABlocksStore
|
||||||
blocksWithTrustedDataDAAWindowStore model.BlocksWithTrustedDataDAAWindowStore
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *consensus) ValidateAndInsertBlockWithTrustedData(block *externalapi.BlockWithTrustedData, validateUTXO bool) (*externalapi.VirtualChangeSet, error) {
|
func (s *consensus) ValidateAndInsertBlockWithTrustedData(block *externalapi.BlockWithTrustedData, validateUTXO bool) (*externalapi.BlockInsertionResult, error) {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@@ -120,6 +119,7 @@ func (s *consensus) Init(skipAddingGenesis bool) error {
|
|||||||
if !skipAddingGenesis && s.blockStore.Count(stagingArea) == 0 {
|
if !skipAddingGenesis && s.blockStore.Count(stagingArea) == 0 {
|
||||||
genesisWithTrustedData := &externalapi.BlockWithTrustedData{
|
genesisWithTrustedData := &externalapi.BlockWithTrustedData{
|
||||||
Block: s.genesisBlock,
|
Block: s.genesisBlock,
|
||||||
|
DAAScore: 0,
|
||||||
DAAWindow: nil,
|
DAAWindow: nil,
|
||||||
GHOSTDAGData: []*externalapi.BlockGHOSTDAGDataHashPair{
|
GHOSTDAGData: []*externalapi.BlockGHOSTDAGDataHashPair{
|
||||||
{
|
{
|
||||||
@@ -137,11 +137,11 @@ func (s *consensus) Init(skipAddingGenesis bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *consensus) PruningPointAndItsAnticone() ([]*externalapi.DomainHash, error) {
|
func (s *consensus) PruningPointAndItsAnticoneWithTrustedData() ([]*externalapi.BlockWithTrustedData, error) {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
return s.pruningManager.PruningPointAndItsAnticone()
|
return s.pruningManager.PruningPointAndItsAnticoneWithTrustedData()
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildBlock builds a block over the current state, with the transactions
|
// BuildBlock builds a block over the current state, with the transactions
|
||||||
@@ -157,7 +157,7 @@ func (s *consensus) BuildBlock(coinbaseData *externalapi.DomainCoinbaseData,
|
|||||||
|
|
||||||
// ValidateAndInsertBlock validates the given block and, if valid, applies it
|
// ValidateAndInsertBlock validates the given block and, if valid, applies it
|
||||||
// to the current state
|
// to the current state
|
||||||
func (s *consensus) ValidateAndInsertBlock(block *externalapi.DomainBlock, shouldValidateAgainstUTXO bool) (*externalapi.VirtualChangeSet, error) {
|
func (s *consensus) ValidateAndInsertBlock(block *externalapi.DomainBlock, shouldValidateAgainstUTXO bool) (*externalapi.BlockInsertionResult, error) {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
@@ -182,12 +182,7 @@ func (s *consensus) ValidateTransactionAndPopulateWithConsensusData(transaction
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
virtualPastMedianTime, err := s.pastMedianTimeManager.PastMedianTime(stagingArea, model.VirtualBlockHash)
|
err = s.transactionValidator.ValidateTransactionInContextIgnoringUTXO(stagingArea, transaction, model.VirtualBlockHash)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = s.transactionValidator.ValidateTransactionInContextIgnoringUTXO(stagingArea, transaction, model.VirtualBlockHash, virtualPastMedianTime)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -286,15 +281,13 @@ func (s *consensus) GetBlockInfo(blockHash *externalapi.DomainHash) (*externalap
|
|||||||
|
|
||||||
blockInfo.BlueScore = ghostdagData.BlueScore()
|
blockInfo.BlueScore = ghostdagData.BlueScore()
|
||||||
blockInfo.BlueWork = ghostdagData.BlueWork()
|
blockInfo.BlueWork = ghostdagData.BlueWork()
|
||||||
blockInfo.SelectedParent = ghostdagData.SelectedParent()
|
|
||||||
blockInfo.MergeSetBlues = ghostdagData.MergeSetBlues()
|
|
||||||
blockInfo.MergeSetReds = ghostdagData.MergeSetReds()
|
|
||||||
|
|
||||||
return blockInfo, nil
|
return blockInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *consensus) GetBlockRelations(blockHash *externalapi.DomainHash) (
|
func (s *consensus) GetBlockRelations(blockHash *externalapi.DomainHash) (
|
||||||
parents []*externalapi.DomainHash, children []*externalapi.DomainHash, err error) {
|
parents []*externalapi.DomainHash, selectedParent *externalapi.DomainHash,
|
||||||
|
children []*externalapi.DomainHash, err error) {
|
||||||
|
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
@@ -303,10 +296,15 @@ func (s *consensus) GetBlockRelations(blockHash *externalapi.DomainHash) (
|
|||||||
|
|
||||||
blockRelation, err := s.blockRelationStores[0].BlockRelation(s.databaseContext, stagingArea, blockHash)
|
blockRelation, err := s.blockRelationStores[0].BlockRelation(s.databaseContext, stagingArea, blockHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return blockRelation.Parents, blockRelation.Children, nil
|
blockGHOSTDAGData, err := s.ghostdagDataStores[0].Get(s.databaseContext, stagingArea, blockHash, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return blockRelation.Parents, blockGHOSTDAGData.SelectedParent(), blockRelation.Children, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *consensus) GetBlockAcceptanceData(blockHash *externalapi.DomainHash) (externalapi.AcceptanceData, error) {
|
func (s *consensus) GetBlockAcceptanceData(blockHash *externalapi.DomainHash) (externalapi.AcceptanceData, error) {
|
||||||
@@ -715,13 +713,26 @@ func (s *consensus) PopulateMass(transaction *externalapi.DomainTransaction) {
|
|||||||
s.transactionValidator.PopulateMass(transaction)
|
s.transactionValidator.PopulateMass(transaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *consensus) ResolveVirtual() (*externalapi.VirtualChangeSet, bool, error) {
|
func (s *consensus) ResolveVirtual() error {
|
||||||
s.lock.Lock()
|
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
// In order to prevent a situation that the consensus lock is held for too much time, we
|
// In order to prevent a situation that the consensus lock is held for too much time, we
|
||||||
// release the lock each time resolve 100 blocks.
|
// release the lock each time resolve 100 blocks.
|
||||||
return s.consensusStateManager.ResolveVirtual(100)
|
for {
|
||||||
|
var isCompletelyResolved bool
|
||||||
|
var err error
|
||||||
|
func() {
|
||||||
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
|
isCompletelyResolved, err = s.consensusStateManager.ResolveVirtual(100)
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if isCompletelyResolved {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *consensus) BuildPruningPointProof() (*externalapi.PruningPointProof, error) {
|
func (s *consensus) BuildPruningPointProof() (*externalapi.PruningPointProof, error) {
|
||||||
@@ -735,102 +746,20 @@ func (s *consensus) ValidatePruningPointProof(pruningPointProof *externalapi.Pru
|
|||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
log.Infof("Validating the pruning point proof")
|
return s.pruningProofManager.ValidatePruningPointProof(pruningPointProof)
|
||||||
err := s.pruningProofManager.ValidatePruningPointProof(pruningPointProof)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("Done validating the pruning point proof")
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *consensus) ApplyPruningPointProof(pruningPointProof *externalapi.PruningPointProof) error {
|
func (s *consensus) ApplyPruningPointProof(pruningPointProof *externalapi.PruningPointProof) error {
|
||||||
s.lock.Lock()
|
stagingArea := model.NewStagingArea()
|
||||||
defer s.lock.Unlock()
|
err := s.pruningProofManager.ApplyPruningPointProof(stagingArea, pruningPointProof)
|
||||||
|
if err != nil {
|
||||||
log.Infof("Applying the pruning point proof")
|
return err
|
||||||
err := s.pruningProofManager.ApplyPruningPointProof(pruningPointProof)
|
}
|
||||||
|
|
||||||
|
err = staging.CommitAllChanges(s.databaseContext, stagingArea)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Done applying the pruning point proof")
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *consensus) BlockDAAWindowHashes(blockHash *externalapi.DomainHash) ([]*externalapi.DomainHash, error) {
|
|
||||||
s.lock.Lock()
|
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
stagingArea := model.NewStagingArea()
|
|
||||||
return s.dagTraversalManager.DAABlockWindow(stagingArea, blockHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *consensus) TrustedDataDataDAAHeader(trustedBlockHash, daaBlockHash *externalapi.DomainHash, daaBlockWindowIndex uint64) (*externalapi.TrustedDataDataDAAHeader, error) {
|
|
||||||
s.lock.Lock()
|
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
stagingArea := model.NewStagingArea()
|
|
||||||
header, err := s.blockHeaderStore.BlockHeader(s.databaseContext, stagingArea, daaBlockHash)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ghostdagData, err := s.ghostdagDataStores[0].Get(s.databaseContext, stagingArea, daaBlockHash, false)
|
|
||||||
isNotFoundError := database.IsNotFoundError(err)
|
|
||||||
if !isNotFoundError && err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !isNotFoundError {
|
|
||||||
return &externalapi.TrustedDataDataDAAHeader{
|
|
||||||
Header: header,
|
|
||||||
GHOSTDAGData: ghostdagData,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
ghostdagDataHashPair, err := s.blocksWithTrustedDataDAAWindowStore.DAAWindowBlock(s.databaseContext, stagingArea, trustedBlockHash, daaBlockWindowIndex)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &externalapi.TrustedDataDataDAAHeader{
|
|
||||||
Header: header,
|
|
||||||
GHOSTDAGData: ghostdagDataHashPair.GHOSTDAGData,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *consensus) TrustedBlockAssociatedGHOSTDAGDataBlockHashes(blockHash *externalapi.DomainHash) ([]*externalapi.DomainHash, error) {
|
|
||||||
s.lock.Lock()
|
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
return s.pruningManager.TrustedBlockAssociatedGHOSTDAGDataBlockHashes(model.NewStagingArea(), blockHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *consensus) TrustedGHOSTDAGData(blockHash *externalapi.DomainHash) (*externalapi.BlockGHOSTDAGData, error) {
|
|
||||||
s.lock.Lock()
|
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
stagingArea := model.NewStagingArea()
|
|
||||||
ghostdagData, err := s.ghostdagDataStores[0].Get(s.databaseContext, stagingArea, blockHash, false)
|
|
||||||
isNotFoundError := database.IsNotFoundError(err)
|
|
||||||
if isNotFoundError || ghostdagData.SelectedParent().Equal(model.VirtualGenesisBlockHash) {
|
|
||||||
return s.ghostdagDataStores[0].Get(s.databaseContext, stagingArea, blockHash, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ghostdagData, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *consensus) IsChainBlock(blockHash *externalapi.DomainHash) (bool, error) {
|
|
||||||
s.lock.Lock()
|
|
||||||
defer s.lock.Unlock()
|
|
||||||
|
|
||||||
stagingArea := model.NewStagingArea()
|
|
||||||
virtualGHOSTDAGData, err := s.ghostdagDataStores[0].Get(s.databaseContext, stagingArea, model.VirtualBlockHash, false)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.dagTopologyManagers[0].IsInSelectedParentChainOf(stagingArea, blockHash, virtualGHOSTDAGData.SelectedParent())
|
|
||||||
}
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user