mirror of
https://github.com/kaspanet/kaspad.git
synced 2026-02-22 19:45:36 +00:00
Compare commits
95 Commits
v0.6.1
...
v0.7.2-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b88e34fd84 | ||
|
|
689098082f | ||
|
|
a359e2248b | ||
|
|
513ffa7e0c | ||
|
|
ef6c46a231 | ||
|
|
22237a4a8d | ||
|
|
6ab8ada9ff | ||
|
|
9a756939d8 | ||
|
|
aea3baf897 | ||
|
|
f8d0f7f67a | ||
|
|
fed34273a1 | ||
|
|
34a1b30006 | ||
|
|
798abf2103 | ||
|
|
75e539f4d2 | ||
|
|
946e65d1c6 | ||
|
|
b8e36eacfd | ||
|
|
cd49c1dac7 | ||
|
|
86411a5ca5 | ||
|
|
1186cad9ca | ||
|
|
e66de86a82 | ||
|
|
1e08bfca9c | ||
|
|
64f5b96295 | ||
|
|
8d38a28b82 | ||
|
|
1743dc694a | ||
|
|
8fb30a5895 | ||
|
|
d59ed71465 | ||
|
|
ea0f5ca60e | ||
|
|
bf74341257 | ||
|
|
c4e6dee1e6 | ||
|
|
34ab661cde | ||
|
|
26b3ce4eb7 | ||
|
|
e10e418971 | ||
|
|
4c915f12b7 | ||
|
|
3c454eefe9 | ||
|
|
3839767aed | ||
|
|
fc0a7ca7e3 | ||
|
|
a32a9011c7 | ||
|
|
5da957f16e | ||
|
|
505d264603 | ||
|
|
883361fea3 | ||
|
|
13a6872a45 | ||
|
|
c82a951a24 | ||
|
|
bbb9dfa4cd | ||
|
|
86d51fa1cb | ||
|
|
8dd7b95423 | ||
|
|
b668d98942 | ||
|
|
e9602cc777 | ||
|
|
5fd164bf66 | ||
|
|
83e7c9e8e4 | ||
|
|
a6b8eea369 | ||
|
|
15b545ee2b | ||
|
|
667b2d46e9 | ||
|
|
53ab906ea8 | ||
|
|
5d20772f94 | ||
|
|
d4728bd9b6 | ||
|
|
4dbd64478c | ||
|
|
7756baf9a9 | ||
|
|
c331293a2e | ||
|
|
fcae491e6d | ||
|
|
5a4cafe342 | ||
|
|
8dae378bd9 | ||
|
|
8dd409dc1c | ||
|
|
74110a2e49 | ||
|
|
ce876a7c44 | ||
|
|
d14809694f | ||
|
|
450ff81f86 | ||
|
|
1f04f30ea7 | ||
|
|
3e4e8d8b6b | ||
|
|
31c0399484 | ||
|
|
8cac582f6d | ||
|
|
f2a3ccd9ab | ||
|
|
31b5cd8d28 | ||
|
|
96bd1fa99b | ||
|
|
48d498e820 | ||
|
|
32c5cfeaf5 | ||
|
|
d55f4e8164 | ||
|
|
1927e81202 | ||
|
|
8a4ece1101 | ||
|
|
0bf1052abf | ||
|
|
2af03c1ccf | ||
|
|
a2aa58c8a4 | ||
|
|
7e74fc0b2b | ||
|
|
0653e59e16 | ||
|
|
32463ce906 | ||
|
|
23a3594c18 | ||
|
|
ffe153efa7 | ||
|
|
ca3172dad0 | ||
|
|
22dc3f998f | ||
|
|
91f4ed9825 | ||
|
|
aa9556aa59 | ||
|
|
91f0fe5740 | ||
|
|
b0fecc9f87 | ||
|
|
53cccd405f | ||
|
|
5b84184921 | ||
|
|
af1df425a2 |
@@ -40,10 +40,8 @@ recommended that `GOPATH` is set to a directory in your home directory such as
|
||||
```bash
|
||||
$ git clone https://github.com/kaspanet/kaspad $GOPATH/src/github.com/kaspanet/kaspad
|
||||
$ cd $GOPATH/src/github.com/kaspanet/kaspad
|
||||
$ ./test.sh
|
||||
$ go install . ./cmd/...
|
||||
```
|
||||
`./test.sh` tests can be skipped, but some things might not run correctly on your system if tests fail.
|
||||
|
||||
- Kaspad (and utilities) should now be installed in `$GOPATH/bin`. If you did
|
||||
not already add the bin directory to your system path during Go installation,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,635 +0,0 @@
|
||||
// Copyright (c) 2013-2014 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package addressmanager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/kaspanet/kaspad/config"
|
||||
"github.com/kaspanet/kaspad/dbaccess"
|
||||
"github.com/kaspanet/kaspad/util/mstime"
|
||||
"github.com/kaspanet/kaspad/util/subnetworkid"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/kaspanet/kaspad/domainmessage"
|
||||
)
|
||||
|
||||
// naTest is used to describe a test to be performed against the NetAddressKey
|
||||
// method.
|
||||
type naTest struct {
|
||||
in domainmessage.NetAddress
|
||||
want AddressKey
|
||||
}
|
||||
|
||||
// naTests houses all of the tests to be performed against the NetAddressKey
|
||||
// method.
|
||||
var naTests = make([]naTest, 0)
|
||||
|
||||
// Put some IP in here for convenience. Points to google.
|
||||
var someIP = "173.194.115.66"
|
||||
|
||||
// addNaTests
|
||||
func addNaTests() {
|
||||
// IPv4
|
||||
// Localhost
|
||||
addNaTest("127.0.0.1", 16111, "127.0.0.1:16111")
|
||||
addNaTest("127.0.0.1", 16110, "127.0.0.1:16110")
|
||||
|
||||
// Class A
|
||||
addNaTest("1.0.0.1", 16111, "1.0.0.1:16111")
|
||||
addNaTest("2.2.2.2", 16110, "2.2.2.2:16110")
|
||||
addNaTest("27.253.252.251", 8335, "27.253.252.251:8335")
|
||||
addNaTest("123.3.2.1", 8336, "123.3.2.1:8336")
|
||||
|
||||
// Private Class A
|
||||
addNaTest("10.0.0.1", 16111, "10.0.0.1:16111")
|
||||
addNaTest("10.1.1.1", 16110, "10.1.1.1:16110")
|
||||
addNaTest("10.2.2.2", 8335, "10.2.2.2:8335")
|
||||
addNaTest("10.10.10.10", 8336, "10.10.10.10:8336")
|
||||
|
||||
// Class B
|
||||
addNaTest("128.0.0.1", 16111, "128.0.0.1:16111")
|
||||
addNaTest("129.1.1.1", 16110, "129.1.1.1:16110")
|
||||
addNaTest("180.2.2.2", 8335, "180.2.2.2:8335")
|
||||
addNaTest("191.10.10.10", 8336, "191.10.10.10:8336")
|
||||
|
||||
// Private Class B
|
||||
addNaTest("172.16.0.1", 16111, "172.16.0.1:16111")
|
||||
addNaTest("172.16.1.1", 16110, "172.16.1.1:16110")
|
||||
addNaTest("172.16.2.2", 8335, "172.16.2.2:8335")
|
||||
addNaTest("172.16.172.172", 8336, "172.16.172.172:8336")
|
||||
|
||||
// Class C
|
||||
addNaTest("193.0.0.1", 16111, "193.0.0.1:16111")
|
||||
addNaTest("200.1.1.1", 16110, "200.1.1.1:16110")
|
||||
addNaTest("205.2.2.2", 8335, "205.2.2.2:8335")
|
||||
addNaTest("223.10.10.10", 8336, "223.10.10.10:8336")
|
||||
|
||||
// Private Class C
|
||||
addNaTest("192.168.0.1", 16111, "192.168.0.1:16111")
|
||||
addNaTest("192.168.1.1", 16110, "192.168.1.1:16110")
|
||||
addNaTest("192.168.2.2", 8335, "192.168.2.2:8335")
|
||||
addNaTest("192.168.192.192", 8336, "192.168.192.192:8336")
|
||||
|
||||
// IPv6
|
||||
// Localhost
|
||||
addNaTest("::1", 16111, "[::1]:16111")
|
||||
addNaTest("fe80::1", 16110, "[fe80::1]:16110")
|
||||
|
||||
// Link-local
|
||||
addNaTest("fe80::1:1", 16111, "[fe80::1:1]:16111")
|
||||
addNaTest("fe91::2:2", 16110, "[fe91::2:2]:16110")
|
||||
addNaTest("fea2::3:3", 8335, "[fea2::3:3]:8335")
|
||||
addNaTest("feb3::4:4", 8336, "[feb3::4:4]:8336")
|
||||
|
||||
// Site-local
|
||||
addNaTest("fec0::1:1", 16111, "[fec0::1:1]:16111")
|
||||
addNaTest("fed1::2:2", 16110, "[fed1::2:2]:16110")
|
||||
addNaTest("fee2::3:3", 8335, "[fee2::3:3]:8335")
|
||||
addNaTest("fef3::4:4", 8336, "[fef3::4:4]:8336")
|
||||
}
|
||||
|
||||
func addNaTest(ip string, port uint16, want AddressKey) {
|
||||
nip := net.ParseIP(ip)
|
||||
na := *domainmessage.NewNetAddressIPPort(nip, port, domainmessage.SFNodeNetwork)
|
||||
test := naTest{na, want}
|
||||
naTests = append(naTests, test)
|
||||
}
|
||||
|
||||
func lookupFuncForTest(host string) ([]net.IP, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func newAddrManagerForTest(t *testing.T, testName string,
|
||||
localSubnetworkID *subnetworkid.SubnetworkID) (addressManager *AddressManager, teardown func()) {
|
||||
|
||||
cfg := config.DefaultConfig()
|
||||
cfg.SubnetworkID = localSubnetworkID
|
||||
|
||||
dbPath, err := ioutil.TempDir("", testName)
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating temporary directory: %s", err)
|
||||
}
|
||||
|
||||
databaseContext, err := dbaccess.New(dbPath)
|
||||
if err != nil {
|
||||
t.Fatalf("error creating db: %s", err)
|
||||
}
|
||||
|
||||
addressManager = New(cfg, databaseContext)
|
||||
|
||||
return addressManager, func() {
|
||||
err := databaseContext.Close()
|
||||
if err != nil {
|
||||
t.Fatalf("error closing the database: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStartStop(t *testing.T) {
|
||||
amgr, teardown := newAddrManagerForTest(t, "TestStartStop", nil)
|
||||
defer teardown()
|
||||
err := amgr.Start()
|
||||
if err != nil {
|
||||
t.Fatalf("Address Manager failed to start: %v", err)
|
||||
}
|
||||
err = amgr.Stop()
|
||||
if err != nil {
|
||||
t.Fatalf("Address Manager failed to stop: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddAddressByIP(t *testing.T) {
|
||||
fmtErr := errors.Errorf("")
|
||||
addrErr := &net.AddrError{}
|
||||
var tests = []struct {
|
||||
addrIP string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
someIP + ":16111",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
someIP,
|
||||
addrErr,
|
||||
},
|
||||
{
|
||||
someIP[:12] + ":8333",
|
||||
fmtErr,
|
||||
},
|
||||
{
|
||||
someIP + ":abcd",
|
||||
fmtErr,
|
||||
},
|
||||
}
|
||||
|
||||
amgr, teardown := newAddrManagerForTest(t, "TestAddAddressByIP", nil)
|
||||
defer teardown()
|
||||
for i, test := range tests {
|
||||
err := amgr.AddAddressByIP(test.addrIP, nil)
|
||||
if test.err != nil && err == nil {
|
||||
t.Errorf("TestAddAddressByIP test %d failed expected an error and got none", i)
|
||||
continue
|
||||
}
|
||||
if test.err == nil && err != nil {
|
||||
t.Errorf("TestAddAddressByIP test %d failed expected no error and got one", i)
|
||||
continue
|
||||
}
|
||||
if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
|
||||
t.Errorf("TestAddAddressByIP test %d failed got %v, want %v", i,
|
||||
reflect.TypeOf(err), reflect.TypeOf(test.err))
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddLocalAddress(t *testing.T) {
|
||||
var tests = []struct {
|
||||
address domainmessage.NetAddress
|
||||
priority AddressPriority
|
||||
valid bool
|
||||
}{
|
||||
{
|
||||
domainmessage.NetAddress{IP: net.ParseIP("192.168.0.100")},
|
||||
InterfacePrio,
|
||||
false,
|
||||
},
|
||||
{
|
||||
domainmessage.NetAddress{IP: net.ParseIP("204.124.1.1")},
|
||||
InterfacePrio,
|
||||
true,
|
||||
},
|
||||
{
|
||||
domainmessage.NetAddress{IP: net.ParseIP("204.124.1.1")},
|
||||
BoundPrio,
|
||||
true,
|
||||
},
|
||||
{
|
||||
domainmessage.NetAddress{IP: net.ParseIP("::1")},
|
||||
InterfacePrio,
|
||||
false,
|
||||
},
|
||||
{
|
||||
domainmessage.NetAddress{IP: net.ParseIP("fe80::1")},
|
||||
InterfacePrio,
|
||||
false,
|
||||
},
|
||||
{
|
||||
domainmessage.NetAddress{IP: net.ParseIP("2620:100::1")},
|
||||
InterfacePrio,
|
||||
true,
|
||||
},
|
||||
}
|
||||
amgr, teardown := newAddrManagerForTest(t, "TestAddLocalAddress", nil)
|
||||
defer teardown()
|
||||
for x, test := range tests {
|
||||
result := amgr.AddLocalAddress(&test.address, test.priority)
|
||||
if result == nil && !test.valid {
|
||||
t.Errorf("TestAddLocalAddress test #%d failed: %s should have "+
|
||||
"been accepted", x, test.address.IP)
|
||||
continue
|
||||
}
|
||||
if result != nil && test.valid {
|
||||
t.Errorf("TestAddLocalAddress test #%d failed: %s should not have "+
|
||||
"been accepted", x, test.address.IP)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAttempt(t *testing.T) {
|
||||
amgr, teardown := newAddrManagerForTest(t, "TestAttempt", nil)
|
||||
defer teardown()
|
||||
|
||||
// Add a new address and get it
|
||||
err := amgr.AddAddressByIP(someIP+":8333", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Adding address failed: %v", err)
|
||||
}
|
||||
ka := amgr.GetAddress()
|
||||
|
||||
if !ka.LastAttempt().IsZero() {
|
||||
t.Errorf("Address should not have attempts, but does")
|
||||
}
|
||||
|
||||
na := ka.NetAddress()
|
||||
amgr.Attempt(na)
|
||||
|
||||
if ka.LastAttempt().IsZero() {
|
||||
t.Errorf("Address should have an attempt, but does not")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnected(t *testing.T) {
|
||||
amgr, teardown := newAddrManagerForTest(t, "TestConnected", nil)
|
||||
defer teardown()
|
||||
|
||||
// Add a new address and get it
|
||||
err := amgr.AddAddressByIP(someIP+":8333", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Adding address failed: %v", err)
|
||||
}
|
||||
ka := amgr.GetAddress()
|
||||
na := ka.NetAddress()
|
||||
// make it an hour ago
|
||||
na.Timestamp = mstime.Now().Add(time.Hour * -1)
|
||||
|
||||
amgr.Connected(na)
|
||||
|
||||
if !ka.NetAddress().Timestamp.After(na.Timestamp) {
|
||||
t.Errorf("Address should have a new timestamp, but does not")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNeedMoreAddresses(t *testing.T) {
|
||||
amgr, teardown := newAddrManagerForTest(t, "TestNeedMoreAddresses", nil)
|
||||
defer teardown()
|
||||
addrsToAdd := 1500
|
||||
b := amgr.NeedMoreAddresses()
|
||||
if !b {
|
||||
t.Errorf("Expected that we need more addresses")
|
||||
}
|
||||
addrs := make([]*domainmessage.NetAddress, addrsToAdd)
|
||||
|
||||
var err error
|
||||
for i := 0; i < addrsToAdd; i++ {
|
||||
s := AddressKey(fmt.Sprintf("%d.%d.173.147:8333", i/128+60, i%128+60))
|
||||
addrs[i], err = amgr.DeserializeNetAddress(s)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to turn %s into an address: %v", s, err)
|
||||
}
|
||||
}
|
||||
|
||||
srcAddr := domainmessage.NewNetAddressIPPort(net.IPv4(173, 144, 173, 111), 8333, 0)
|
||||
|
||||
amgr.AddAddresses(addrs, srcAddr, nil)
|
||||
numAddrs := amgr.TotalNumAddresses()
|
||||
if numAddrs > addrsToAdd {
|
||||
t.Errorf("Number of addresses is too many %d vs %d", numAddrs, addrsToAdd)
|
||||
}
|
||||
|
||||
b = amgr.NeedMoreAddresses()
|
||||
if b {
|
||||
t.Errorf("Expected that we don't need more addresses")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGood(t *testing.T) {
|
||||
amgr, teardown := newAddrManagerForTest(t, "TestGood", nil)
|
||||
defer teardown()
|
||||
addrsToAdd := 64 * 64
|
||||
addrs := make([]*domainmessage.NetAddress, addrsToAdd)
|
||||
subnetworkCount := 32
|
||||
subnetworkIDs := make([]*subnetworkid.SubnetworkID, subnetworkCount)
|
||||
|
||||
var err error
|
||||
for i := 0; i < addrsToAdd; i++ {
|
||||
s := AddressKey(fmt.Sprintf("%d.173.147.%d:8333", i/64+60, i%64+60))
|
||||
addrs[i], err = amgr.DeserializeNetAddress(s)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to turn %s into an address: %v", s, err)
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < subnetworkCount; i++ {
|
||||
subnetworkIDs[i] = &subnetworkid.SubnetworkID{0xff - byte(i)}
|
||||
}
|
||||
|
||||
srcAddr := domainmessage.NewNetAddressIPPort(net.IPv4(173, 144, 173, 111), 8333, 0)
|
||||
|
||||
amgr.AddAddresses(addrs, srcAddr, nil)
|
||||
for i, addr := range addrs {
|
||||
amgr.Good(addr, subnetworkIDs[i%subnetworkCount])
|
||||
}
|
||||
|
||||
numAddrs := amgr.TotalNumAddresses()
|
||||
if numAddrs >= addrsToAdd {
|
||||
t.Errorf("Number of addresses is too many: %d vs %d", numAddrs, addrsToAdd)
|
||||
}
|
||||
|
||||
numCache := len(amgr.AddressCache(true, nil))
|
||||
if numCache == 0 || numCache >= numAddrs/4 {
|
||||
t.Errorf("Number of addresses in cache: got %d, want positive and less than %d",
|
||||
numCache, numAddrs/4)
|
||||
}
|
||||
|
||||
for i := 0; i < subnetworkCount; i++ {
|
||||
numCache = len(amgr.AddressCache(false, subnetworkIDs[i]))
|
||||
if numCache == 0 || numCache >= numAddrs/subnetworkCount {
|
||||
t.Errorf("Number of addresses in subnetwork cache: got %d, want positive and less than %d",
|
||||
numCache, numAddrs/4/subnetworkCount)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoodChangeSubnetworkID(t *testing.T) {
|
||||
amgr, teardown := newAddrManagerForTest(t, "TestGoodChangeSubnetworkID", nil)
|
||||
defer teardown()
|
||||
addr := domainmessage.NewNetAddressIPPort(net.IPv4(173, 144, 173, 111), 8333, 0)
|
||||
addrKey := NetAddressKey(addr)
|
||||
srcAddr := domainmessage.NewNetAddressIPPort(net.IPv4(173, 144, 173, 111), 8333, 0)
|
||||
|
||||
oldSubnetwork := subnetworkid.SubnetworkIDNative
|
||||
amgr.AddAddress(addr, srcAddr, oldSubnetwork)
|
||||
amgr.Good(addr, oldSubnetwork)
|
||||
|
||||
// make sure address was saved to addressIndex under oldSubnetwork
|
||||
ka := amgr.knownAddress(addr)
|
||||
if ka == nil {
|
||||
t.Fatalf("Address was not found after first time .Good called")
|
||||
}
|
||||
if !ka.SubnetworkID().IsEqual(oldSubnetwork) {
|
||||
t.Fatalf("Address index did not point to oldSubnetwork")
|
||||
}
|
||||
|
||||
// make sure address was added to correct bucket under oldSubnetwork
|
||||
bucket := amgr.subnetworkTriedAddresBucketArrays[*oldSubnetwork][amgr.triedAddressBucketIndex(addr)]
|
||||
wasFound := false
|
||||
for _, ka := range bucket {
|
||||
if NetAddressKey(ka.NetAddress()) == addrKey {
|
||||
wasFound = true
|
||||
}
|
||||
}
|
||||
if !wasFound {
|
||||
t.Fatalf("Address was not found in the correct bucket in oldSubnetwork")
|
||||
}
|
||||
|
||||
// now call .Good again with a different subnetwork
|
||||
newSubnetwork := subnetworkid.SubnetworkIDRegistry
|
||||
amgr.Good(addr, newSubnetwork)
|
||||
|
||||
// make sure address was updated in addressIndex under newSubnetwork
|
||||
ka = amgr.knownAddress(addr)
|
||||
if ka == nil {
|
||||
t.Fatalf("Address was not found after second time .Good called")
|
||||
}
|
||||
if !ka.SubnetworkID().IsEqual(newSubnetwork) {
|
||||
t.Fatalf("Address index did not point to newSubnetwork")
|
||||
}
|
||||
|
||||
// make sure address was removed from bucket under oldSubnetwork
|
||||
bucket = amgr.subnetworkTriedAddresBucketArrays[*oldSubnetwork][amgr.triedAddressBucketIndex(addr)]
|
||||
wasFound = false
|
||||
for _, ka := range bucket {
|
||||
if NetAddressKey(ka.NetAddress()) == addrKey {
|
||||
wasFound = true
|
||||
}
|
||||
}
|
||||
if wasFound {
|
||||
t.Fatalf("Address was not removed from bucket in oldSubnetwork")
|
||||
}
|
||||
|
||||
// make sure address was added to correct bucket under newSubnetwork
|
||||
bucket = amgr.subnetworkTriedAddresBucketArrays[*newSubnetwork][amgr.triedAddressBucketIndex(addr)]
|
||||
wasFound = false
|
||||
for _, ka := range bucket {
|
||||
if NetAddressKey(ka.NetAddress()) == addrKey {
|
||||
wasFound = true
|
||||
}
|
||||
}
|
||||
if !wasFound {
|
||||
t.Fatalf("Address was not found in the correct bucket in newSubnetwork")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAddress(t *testing.T) {
|
||||
localSubnetworkID := &subnetworkid.SubnetworkID{0xff}
|
||||
amgr, teardown := newAddrManagerForTest(t, "TestGetAddress", localSubnetworkID)
|
||||
defer teardown()
|
||||
|
||||
// Get an address from an empty set (should error)
|
||||
if rv := amgr.GetAddress(); rv != nil {
|
||||
t.Errorf("GetAddress failed: got: %v want: %v\n", rv, nil)
|
||||
}
|
||||
|
||||
// Add a new address and get it
|
||||
err := amgr.AddAddressByIP(someIP+":8332", localSubnetworkID)
|
||||
if err != nil {
|
||||
t.Fatalf("Adding address failed: %v", err)
|
||||
}
|
||||
ka := amgr.GetAddress()
|
||||
if ka == nil {
|
||||
t.Fatalf("Did not get an address where there is one in the pool")
|
||||
}
|
||||
amgr.Attempt(ka.NetAddress())
|
||||
|
||||
// Checks that we don't get it if we find that it has other subnetwork ID than expected.
|
||||
actualSubnetworkID := &subnetworkid.SubnetworkID{0xfe}
|
||||
amgr.Good(ka.NetAddress(), actualSubnetworkID)
|
||||
ka = amgr.GetAddress()
|
||||
if ka != nil {
|
||||
t.Errorf("Didn't expect to get an address because there shouldn't be any address from subnetwork ID %s or nil", localSubnetworkID)
|
||||
}
|
||||
|
||||
// Checks that the total number of addresses incremented although the new address is not full node or a partial node of the same subnetwork as the local node.
|
||||
numAddrs := amgr.TotalNumAddresses()
|
||||
if numAddrs != 1 {
|
||||
t.Errorf("Wrong number of addresses: got %d, want %d", numAddrs, 1)
|
||||
}
|
||||
|
||||
// Now we repeat the same process, but now the address has the expected subnetwork ID.
|
||||
|
||||
// Add a new address and get it
|
||||
err = amgr.AddAddressByIP(someIP+":8333", localSubnetworkID)
|
||||
if err != nil {
|
||||
t.Fatalf("Adding address failed: %v", err)
|
||||
}
|
||||
ka = amgr.GetAddress()
|
||||
if ka == nil {
|
||||
t.Fatalf("Did not get an address where there is one in the pool")
|
||||
}
|
||||
if ka.NetAddress().IP.String() != someIP {
|
||||
t.Errorf("Wrong IP: got %v, want %v", ka.NetAddress().IP.String(), someIP)
|
||||
}
|
||||
if !ka.SubnetworkID().IsEqual(localSubnetworkID) {
|
||||
t.Errorf("Wrong Subnetwork ID: got %v, want %v", *ka.SubnetworkID(), localSubnetworkID)
|
||||
}
|
||||
amgr.Attempt(ka.NetAddress())
|
||||
|
||||
// Mark this as a good address and get it
|
||||
amgr.Good(ka.NetAddress(), localSubnetworkID)
|
||||
ka = amgr.GetAddress()
|
||||
if ka == nil {
|
||||
t.Fatalf("Did not get an address where there is one in the pool")
|
||||
}
|
||||
if ka.NetAddress().IP.String() != someIP {
|
||||
t.Errorf("Wrong IP: got %v, want %v", ka.NetAddress().IP.String(), someIP)
|
||||
}
|
||||
if *ka.SubnetworkID() != *localSubnetworkID {
|
||||
t.Errorf("Wrong Subnetwork ID: got %v, want %v", ka.SubnetworkID(), localSubnetworkID)
|
||||
}
|
||||
|
||||
numAddrs = amgr.TotalNumAddresses()
|
||||
if numAddrs != 2 {
|
||||
t.Errorf("Wrong number of addresses: got %d, want %d", numAddrs, 1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetBestLocalAddress(t *testing.T) {
|
||||
localAddrs := []domainmessage.NetAddress{
|
||||
{IP: net.ParseIP("192.168.0.100")},
|
||||
{IP: net.ParseIP("::1")},
|
||||
{IP: net.ParseIP("fe80::1")},
|
||||
{IP: net.ParseIP("2001:470::1")},
|
||||
}
|
||||
|
||||
var tests = []struct {
|
||||
remoteAddr domainmessage.NetAddress
|
||||
want0 domainmessage.NetAddress
|
||||
want1 domainmessage.NetAddress
|
||||
want2 domainmessage.NetAddress
|
||||
want3 domainmessage.NetAddress
|
||||
}{
|
||||
{
|
||||
// Remote connection from public IPv4
|
||||
domainmessage.NetAddress{IP: net.ParseIP("204.124.8.1")},
|
||||
domainmessage.NetAddress{IP: net.IPv4zero},
|
||||
domainmessage.NetAddress{IP: net.IPv4zero},
|
||||
domainmessage.NetAddress{IP: net.ParseIP("204.124.8.100")},
|
||||
domainmessage.NetAddress{IP: net.ParseIP("fd87:d87e:eb43:25::1")},
|
||||
},
|
||||
{
|
||||
// Remote connection from private IPv4
|
||||
domainmessage.NetAddress{IP: net.ParseIP("172.16.0.254")},
|
||||
domainmessage.NetAddress{IP: net.IPv4zero},
|
||||
domainmessage.NetAddress{IP: net.IPv4zero},
|
||||
domainmessage.NetAddress{IP: net.IPv4zero},
|
||||
domainmessage.NetAddress{IP: net.IPv4zero},
|
||||
},
|
||||
{
|
||||
// Remote connection from public IPv6
|
||||
domainmessage.NetAddress{IP: net.ParseIP("2602:100:abcd::102")},
|
||||
domainmessage.NetAddress{IP: net.IPv6zero},
|
||||
domainmessage.NetAddress{IP: net.ParseIP("2001:470::1")},
|
||||
domainmessage.NetAddress{IP: net.ParseIP("2001:470::1")},
|
||||
domainmessage.NetAddress{IP: net.ParseIP("2001:470::1")},
|
||||
},
|
||||
/* XXX
|
||||
{
|
||||
// Remote connection from Tor
|
||||
domainmessage.NetAddress{IP: net.ParseIP("fd87:d87e:eb43::100")},
|
||||
domainmessage.NetAddress{IP: net.IPv4zero},
|
||||
domainmessage.NetAddress{IP: net.ParseIP("204.124.8.100")},
|
||||
domainmessage.NetAddress{IP: net.ParseIP("fd87:d87e:eb43:25::1")},
|
||||
},
|
||||
*/
|
||||
}
|
||||
|
||||
amgr, teardown := newAddrManagerForTest(t, "TestGetBestLocalAddress", nil)
|
||||
defer teardown()
|
||||
|
||||
// Test against default when there's no address
|
||||
for x, test := range tests {
|
||||
got := amgr.GetBestLocalAddress(&test.remoteAddr)
|
||||
if !test.want0.IP.Equal(got.IP) {
|
||||
t.Errorf("TestGetBestLocalAddress test1 #%d failed for remote address %s: want %s got %s",
|
||||
x, test.remoteAddr.IP, test.want1.IP, got.IP)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
for _, localAddr := range localAddrs {
|
||||
amgr.AddLocalAddress(&localAddr, InterfacePrio)
|
||||
}
|
||||
|
||||
// Test against want1
|
||||
for x, test := range tests {
|
||||
got := amgr.GetBestLocalAddress(&test.remoteAddr)
|
||||
if !test.want1.IP.Equal(got.IP) {
|
||||
t.Errorf("TestGetBestLocalAddress test1 #%d failed for remote address %s: want %s got %s",
|
||||
x, test.remoteAddr.IP, test.want1.IP, got.IP)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Add a public IP to the list of local addresses.
|
||||
localAddr := domainmessage.NetAddress{IP: net.ParseIP("204.124.8.100")}
|
||||
amgr.AddLocalAddress(&localAddr, InterfacePrio)
|
||||
|
||||
// Test against want2
|
||||
for x, test := range tests {
|
||||
got := amgr.GetBestLocalAddress(&test.remoteAddr)
|
||||
if !test.want2.IP.Equal(got.IP) {
|
||||
t.Errorf("TestGetBestLocalAddress test2 #%d failed for remote address %s: want %s got %s",
|
||||
x, test.remoteAddr.IP, test.want2.IP, got.IP)
|
||||
continue
|
||||
}
|
||||
}
|
||||
/*
|
||||
// Add a Tor generated IP address
|
||||
localAddr = domainmessage.NetAddress{IP: net.ParseIP("fd87:d87e:eb43:25::1")}
|
||||
amgr.AddLocalAddress(&localAddr, ManualPrio)
|
||||
// Test against want3
|
||||
for x, test := range tests {
|
||||
got := amgr.GetBestLocalAddress(&test.remoteAddr)
|
||||
if !test.want3.IP.Equal(got.IP) {
|
||||
t.Errorf("TestGetBestLocalAddress test3 #%d failed for remote address %s: want %s got %s",
|
||||
x, test.remoteAddr.IP, test.want3.IP, got.IP)
|
||||
continue
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
func TestNetAddressKey(t *testing.T) {
|
||||
addNaTests()
|
||||
|
||||
t.Logf("Running %d tests", len(naTests))
|
||||
for i, test := range naTests {
|
||||
key := NetAddressKey(&test.in)
|
||||
if key != test.want {
|
||||
t.Errorf("NetAddressKey #%d\n got: %s want: %s", i, key, test.want)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
// Copyright (c) 2013-2015 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package addressmanager
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domainmessage"
|
||||
"github.com/kaspanet/kaspad/util/mstime"
|
||||
)
|
||||
|
||||
func TstKnownAddressIsBad(ka *KnownAddress) bool {
|
||||
return ka.isBad()
|
||||
}
|
||||
|
||||
func TstKnownAddressChance(ka *KnownAddress) float64 {
|
||||
return ka.chance()
|
||||
}
|
||||
|
||||
func TstNewKnownAddress(na *domainmessage.NetAddress, attempts int,
|
||||
lastattempt, lastsuccess mstime.Time, tried bool, refs int) *KnownAddress {
|
||||
return &KnownAddress{netAddress: na, attempts: attempts, lastAttempt: lastattempt,
|
||||
lastSuccess: lastsuccess, tried: tried, referenceCount: refs}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
// Copyright (c) 2013-2014 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package addressmanager
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/util/mstime"
|
||||
"time"
|
||||
|
||||
"github.com/kaspanet/kaspad/util/subnetworkid"
|
||||
|
||||
"github.com/kaspanet/kaspad/domainmessage"
|
||||
)
|
||||
|
||||
// KnownAddress tracks information about a known network address that is used
|
||||
// to determine how viable an address is.
|
||||
type KnownAddress struct {
|
||||
netAddress *domainmessage.NetAddress
|
||||
sourceAddress *domainmessage.NetAddress
|
||||
attempts int
|
||||
lastAttempt mstime.Time
|
||||
lastSuccess mstime.Time
|
||||
tried bool
|
||||
referenceCount int // reference count of new buckets
|
||||
subnetworkID *subnetworkid.SubnetworkID
|
||||
isBanned bool
|
||||
bannedTime mstime.Time
|
||||
}
|
||||
|
||||
// NetAddress returns the underlying domainmessage.NetAddress associated with the
|
||||
// known address.
|
||||
func (ka *KnownAddress) NetAddress() *domainmessage.NetAddress {
|
||||
return ka.netAddress
|
||||
}
|
||||
|
||||
// SubnetworkID returns the subnetwork ID of the known address.
|
||||
func (ka *KnownAddress) SubnetworkID() *subnetworkid.SubnetworkID {
|
||||
return ka.subnetworkID
|
||||
}
|
||||
|
||||
// LastAttempt returns the last time the known address was attempted.
|
||||
func (ka *KnownAddress) LastAttempt() mstime.Time {
|
||||
return ka.lastAttempt
|
||||
}
|
||||
|
||||
// chance returns the selection probability for a known address. The priority
|
||||
// depends upon how recently the address has been seen, how recently it was last
|
||||
// attempted and how often attempts to connect to it have failed.
|
||||
func (ka *KnownAddress) chance() float64 {
|
||||
now := mstime.Now()
|
||||
lastAttempt := now.Sub(ka.lastAttempt)
|
||||
|
||||
if lastAttempt < 0 {
|
||||
lastAttempt = 0
|
||||
}
|
||||
|
||||
c := 1.0
|
||||
|
||||
// Very recent attempts are less likely to be retried.
|
||||
if lastAttempt < 10*time.Minute {
|
||||
c *= 0.01
|
||||
}
|
||||
|
||||
// Failed attempts deprioritise.
|
||||
for i := ka.attempts; i > 0; i-- {
|
||||
c /= 1.5
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// isBad returns true if the address in question has not been tried in the last
|
||||
// minute and meets one of the following criteria:
|
||||
// 1) It claims to be from the future
|
||||
// 2) It hasn't been seen in over a month
|
||||
// 3) It has failed at least three times and never succeeded
|
||||
// 4) It has failed ten times in the last week
|
||||
// All addresses that meet these criteria are assumed to be worthless and not
|
||||
// worth keeping hold of.
|
||||
func (ka *KnownAddress) isBad() bool {
|
||||
if ka.lastAttempt.After(mstime.Now().Add(-1 * time.Minute)) {
|
||||
return false
|
||||
}
|
||||
|
||||
// From the future?
|
||||
if ka.netAddress.Timestamp.After(mstime.Now().Add(10 * time.Minute)) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Over a month old?
|
||||
if ka.netAddress.Timestamp.Before(mstime.Now().Add(-1 * numMissingDays * time.Hour * 24)) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Never succeeded?
|
||||
if ka.lastSuccess.IsZero() && ka.attempts >= numRetries {
|
||||
return true
|
||||
}
|
||||
|
||||
// Hasn't succeeded in too long?
|
||||
if !ka.lastSuccess.After(mstime.Now().Add(-1*minBadDays*time.Hour*24)) &&
|
||||
ka.attempts >= maxFailures {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
// Copyright (c) 2013-2015 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package addressmanager_test
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/util/mstime"
|
||||
"math"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/kaspanet/kaspad/addressmanager"
|
||||
"github.com/kaspanet/kaspad/domainmessage"
|
||||
)
|
||||
|
||||
func TestChance(t *testing.T) {
|
||||
now := mstime.Now()
|
||||
var tests = []struct {
|
||||
addr *addressmanager.KnownAddress
|
||||
expected float64
|
||||
}{
|
||||
{
|
||||
//Test normal case
|
||||
addressmanager.TstNewKnownAddress(&domainmessage.NetAddress{Timestamp: now.Add(-35 * time.Second)},
|
||||
0, mstime.Now().Add(-30*time.Minute), mstime.Now(), false, 0),
|
||||
1.0,
|
||||
}, {
|
||||
//Test case in which lastseen < 0
|
||||
addressmanager.TstNewKnownAddress(&domainmessage.NetAddress{Timestamp: now.Add(20 * time.Second)},
|
||||
0, mstime.Now().Add(-30*time.Minute), mstime.Now(), false, 0),
|
||||
1.0,
|
||||
}, {
|
||||
//Test case in which lastAttempt < 0
|
||||
addressmanager.TstNewKnownAddress(&domainmessage.NetAddress{Timestamp: now.Add(-35 * time.Second)},
|
||||
0, mstime.Now().Add(30*time.Minute), mstime.Now(), false, 0),
|
||||
1.0 * .01,
|
||||
}, {
|
||||
//Test case in which lastAttempt < ten minutes
|
||||
addressmanager.TstNewKnownAddress(&domainmessage.NetAddress{Timestamp: now.Add(-35 * time.Second)},
|
||||
0, mstime.Now().Add(-5*time.Minute), mstime.Now(), false, 0),
|
||||
1.0 * .01,
|
||||
}, {
|
||||
//Test case with several failed attempts.
|
||||
addressmanager.TstNewKnownAddress(&domainmessage.NetAddress{Timestamp: now.Add(-35 * time.Second)},
|
||||
2, mstime.Now().Add(-30*time.Minute), mstime.Now(), false, 0),
|
||||
1 / 1.5 / 1.5,
|
||||
},
|
||||
}
|
||||
|
||||
err := .0001
|
||||
for i, test := range tests {
|
||||
chance := addressmanager.TstKnownAddressChance(test.addr)
|
||||
if math.Abs(test.expected-chance) >= err {
|
||||
t.Errorf("case %d: got %f, expected %f", i, chance, test.expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsBad(t *testing.T) {
|
||||
now := mstime.Now()
|
||||
future := now.Add(35 * time.Minute)
|
||||
monthOld := now.Add(-43 * time.Hour * 24)
|
||||
secondsOld := now.Add(-2 * time.Second)
|
||||
minutesOld := now.Add(-27 * time.Minute)
|
||||
hoursOld := now.Add(-5 * time.Hour)
|
||||
zeroTime := mstime.Time{}
|
||||
|
||||
futureNa := &domainmessage.NetAddress{Timestamp: future}
|
||||
minutesOldNa := &domainmessage.NetAddress{Timestamp: minutesOld}
|
||||
monthOldNa := &domainmessage.NetAddress{Timestamp: monthOld}
|
||||
currentNa := &domainmessage.NetAddress{Timestamp: secondsOld}
|
||||
|
||||
//Test addresses that have been tried in the last minute.
|
||||
if addressmanager.TstKnownAddressIsBad(addressmanager.TstNewKnownAddress(futureNa, 3, secondsOld, zeroTime, false, 0)) {
|
||||
t.Errorf("test case 1: addresses that have been tried in the last minute are not bad.")
|
||||
}
|
||||
if addressmanager.TstKnownAddressIsBad(addressmanager.TstNewKnownAddress(monthOldNa, 3, secondsOld, zeroTime, false, 0)) {
|
||||
t.Errorf("test case 2: addresses that have been tried in the last minute are not bad.")
|
||||
}
|
||||
if addressmanager.TstKnownAddressIsBad(addressmanager.TstNewKnownAddress(currentNa, 3, secondsOld, zeroTime, false, 0)) {
|
||||
t.Errorf("test case 3: addresses that have been tried in the last minute are not bad.")
|
||||
}
|
||||
if addressmanager.TstKnownAddressIsBad(addressmanager.TstNewKnownAddress(currentNa, 3, secondsOld, monthOld, true, 0)) {
|
||||
t.Errorf("test case 4: addresses that have been tried in the last minute are not bad.")
|
||||
}
|
||||
if addressmanager.TstKnownAddressIsBad(addressmanager.TstNewKnownAddress(currentNa, 2, secondsOld, secondsOld, true, 0)) {
|
||||
t.Errorf("test case 5: addresses that have been tried in the last minute are not bad.")
|
||||
}
|
||||
|
||||
//Test address that claims to be from the future.
|
||||
if !addressmanager.TstKnownAddressIsBad(addressmanager.TstNewKnownAddress(futureNa, 0, minutesOld, hoursOld, true, 0)) {
|
||||
t.Errorf("test case 6: addresses that claim to be from the future are bad.")
|
||||
}
|
||||
|
||||
//Test address that has not been seen in over a month.
|
||||
if !addressmanager.TstKnownAddressIsBad(addressmanager.TstNewKnownAddress(monthOldNa, 0, minutesOld, hoursOld, true, 0)) {
|
||||
t.Errorf("test case 7: addresses more than a month old are bad.")
|
||||
}
|
||||
|
||||
//It has failed at least three times and never succeeded.
|
||||
if !addressmanager.TstKnownAddressIsBad(addressmanager.TstNewKnownAddress(minutesOldNa, 3, minutesOld, zeroTime, true, 0)) {
|
||||
t.Errorf("test case 8: addresses that have never succeeded are bad.")
|
||||
}
|
||||
|
||||
//It has failed ten times in the last week
|
||||
if !addressmanager.TstKnownAddressIsBad(addressmanager.TstNewKnownAddress(minutesOldNa, 10, minutesOld, monthOld, true, 0)) {
|
||||
t.Errorf("test case 9: addresses that have not succeeded in too long are bad.")
|
||||
}
|
||||
|
||||
//Test an address that should work.
|
||||
if addressmanager.TstKnownAddressIsBad(addressmanager.TstNewKnownAddress(minutesOldNa, 2, minutesOld, hoursOld, true, 0)) {
|
||||
t.Errorf("test case 10: This should be a valid address.")
|
||||
}
|
||||
}
|
||||
371
app/app.go
371
app/app.go
@@ -2,247 +2,194 @@ package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/kaspanet/kaspad/addressmanager"
|
||||
"github.com/kaspanet/kaspad/infrastructure/db/dbaccess"
|
||||
|
||||
"github.com/kaspanet/kaspad/netadapter/id"
|
||||
"github.com/kaspanet/kaspad/domain/blockdag/indexers"
|
||||
"github.com/kaspanet/kaspad/infrastructure/os/signal"
|
||||
"github.com/kaspanet/kaspad/util/profiling"
|
||||
"github.com/kaspanet/kaspad/version"
|
||||
|
||||
"github.com/kaspanet/kaspad/blockdag"
|
||||
"github.com/kaspanet/kaspad/blockdag/indexers"
|
||||
"github.com/kaspanet/kaspad/config"
|
||||
"github.com/kaspanet/kaspad/connmanager"
|
||||
"github.com/kaspanet/kaspad/dbaccess"
|
||||
"github.com/kaspanet/kaspad/dnsseed"
|
||||
"github.com/kaspanet/kaspad/domainmessage"
|
||||
"github.com/kaspanet/kaspad/mempool"
|
||||
"github.com/kaspanet/kaspad/mining"
|
||||
"github.com/kaspanet/kaspad/netadapter"
|
||||
"github.com/kaspanet/kaspad/protocol"
|
||||
"github.com/kaspanet/kaspad/rpc"
|
||||
"github.com/kaspanet/kaspad/signal"
|
||||
"github.com/kaspanet/kaspad/txscript"
|
||||
"github.com/kaspanet/kaspad/util"
|
||||
"github.com/kaspanet/kaspad/util/panics"
|
||||
|
||||
"github.com/kaspanet/kaspad/infrastructure/config"
|
||||
"github.com/kaspanet/kaspad/infrastructure/os/execenv"
|
||||
"github.com/kaspanet/kaspad/infrastructure/os/limits"
|
||||
"github.com/kaspanet/kaspad/infrastructure/os/winservice"
|
||||
)
|
||||
|
||||
// App is a wrapper for all the kaspad services
|
||||
type App struct {
|
||||
cfg *config.Config
|
||||
rpcServer *rpc.Server
|
||||
addressManager *addressmanager.AddressManager
|
||||
protocolManager *protocol.Manager
|
||||
connectionManager *connmanager.ConnectionManager
|
||||
netAdapter *netadapter.NetAdapter
|
||||
|
||||
started, shutdown int32
|
||||
var desiredLimits = &limits.DesiredLimits{
|
||||
FileLimitWant: 2048,
|
||||
FileLimitMin: 1024,
|
||||
}
|
||||
|
||||
// Start launches all the kaspad services.
|
||||
func (a *App) Start() {
|
||||
// Already started?
|
||||
if atomic.AddInt32(&a.started, 1) != 1 {
|
||||
return
|
||||
}
|
||||
var serviceDescription = &winservice.ServiceDescription{
|
||||
Name: "kaspadsvc",
|
||||
DisplayName: "Kaspad Service",
|
||||
Description: "Downloads and stays synchronized with the Kaspa blockDAG and " +
|
||||
"provides DAG services to applications.",
|
||||
}
|
||||
|
||||
log.Trace("Starting kaspad")
|
||||
type kaspadApp struct {
|
||||
cfg *config.Config
|
||||
}
|
||||
|
||||
err := a.protocolManager.Start()
|
||||
// StartApp starts the kaspad app, and blocks until it finishes running
|
||||
func StartApp() error {
|
||||
execenv.Initialize(desiredLimits)
|
||||
|
||||
// Load configuration and parse command line. This function also
|
||||
// initializes logging and configures it accordingly.
|
||||
cfg, err := config.LoadConfig()
|
||||
if err != nil {
|
||||
panics.Exit(log, fmt.Sprintf("Error starting the p2p protocol: %+v", err))
|
||||
fmt.Fprint(os.Stderr, err)
|
||||
return err
|
||||
}
|
||||
defer panics.HandlePanic(log, "MAIN", nil)
|
||||
|
||||
app := &kaspadApp{cfg: cfg}
|
||||
|
||||
// Call serviceMain on Windows to handle running as a service. When
|
||||
// the return isService flag is true, exit now since we ran as a
|
||||
// service. Otherwise, just fall through to normal operation.
|
||||
if runtime.GOOS == "windows" {
|
||||
isService, err := winservice.WinServiceMain(app.main, serviceDescription, cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if isService {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
a.maybeSeedFromDNS()
|
||||
|
||||
a.connectionManager.Start()
|
||||
|
||||
if !a.cfg.DisableRPC {
|
||||
a.rpcServer.Start()
|
||||
}
|
||||
return app.main(nil)
|
||||
}
|
||||
|
||||
// Stop gracefully shuts down all the kaspad services.
|
||||
func (a *App) Stop() error {
|
||||
// Make sure this only happens once.
|
||||
if atomic.AddInt32(&a.shutdown, 1) != 1 {
|
||||
log.Infof("Kaspad is already in the process of shutting down")
|
||||
func (app *kaspadApp) main(startedChan chan<- struct{}) error {
|
||||
// Get a channel that will be closed when a shutdown signal has been
|
||||
// triggered either from an OS signal such as SIGINT (Ctrl+C) or from
|
||||
// another subsystem such as the RPC server.
|
||||
interrupt := signal.InterruptListener()
|
||||
defer log.Info("Shutdown complete")
|
||||
|
||||
// Show version at startup.
|
||||
log.Infof("Version %s", version.Version())
|
||||
|
||||
// Enable http profiling server if requested.
|
||||
if app.cfg.Profile != "" {
|
||||
profiling.Start(app.cfg.Profile, log)
|
||||
}
|
||||
|
||||
// Perform upgrades to kaspad as new versions require it.
|
||||
if err := doUpgrades(); err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Return now if an interrupt signal was triggered.
|
||||
if signal.InterruptRequested(interrupt) {
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Warnf("Kaspad shutting down")
|
||||
|
||||
a.connectionManager.Stop()
|
||||
|
||||
err := a.protocolManager.Stop()
|
||||
if err != nil {
|
||||
log.Errorf("Error stopping the p2p protocol: %+v", err)
|
||||
}
|
||||
|
||||
// Shutdown the RPC server if it's not disabled.
|
||||
if !a.cfg.DisableRPC {
|
||||
err := a.rpcServer.Stop()
|
||||
if app.cfg.ResetDatabase {
|
||||
err := removeDatabase(app.cfg)
|
||||
if err != nil {
|
||||
log.Errorf("Error stopping rpcServer: %+v", err)
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Open the database
|
||||
databaseContext, err := openDB(app.cfg)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
log.Infof("Gracefully shutting down the database...")
|
||||
err := databaseContext.Close()
|
||||
if err != nil {
|
||||
log.Errorf("Failed to close the database: %s", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Return now if an interrupt signal was triggered.
|
||||
if signal.InterruptRequested(interrupt) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Drop indexes and exit if requested.
|
||||
if app.cfg.DropAcceptanceIndex {
|
||||
if err := indexers.DropAcceptanceIndex(databaseContext); err != nil {
|
||||
log.Errorf("%s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create componentManager and start it.
|
||||
componentManager, err := NewComponentManager(app.cfg, databaseContext, interrupt)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to start kaspad: %+v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
log.Infof("Gracefully shutting down kaspad...")
|
||||
|
||||
shutdownDone := make(chan struct{})
|
||||
go func() {
|
||||
componentManager.Stop()
|
||||
shutdownDone <- struct{}{}
|
||||
}()
|
||||
|
||||
const shutdownTimeout = 2 * time.Minute
|
||||
|
||||
select {
|
||||
case <-shutdownDone:
|
||||
case <-time.After(shutdownTimeout):
|
||||
log.Criticalf("Graceful shutdown timed out %s. Terminating...", shutdownTimeout)
|
||||
}
|
||||
log.Infof("Kaspad shutdown complete")
|
||||
}()
|
||||
|
||||
componentManager.Start()
|
||||
|
||||
if startedChan != nil {
|
||||
startedChan <- struct{}{}
|
||||
}
|
||||
|
||||
// Wait until the interrupt signal is received from an OS signal or
|
||||
// shutdown is requested through one of the subsystems such as the RPC
|
||||
// server.
|
||||
<-interrupt
|
||||
return nil
|
||||
}
|
||||
|
||||
// New returns a new App instance configured to listen on addr for the
|
||||
// kaspa network type specified by dagParams. Use start to begin accepting
|
||||
// connections from peers.
|
||||
func New(cfg *config.Config, databaseContext *dbaccess.DatabaseContext, interrupt <-chan struct{}) (*App, error) {
|
||||
indexManager, acceptanceIndex := setupIndexes(cfg)
|
||||
|
||||
sigCache := txscript.NewSigCache(cfg.SigCacheMaxSize)
|
||||
|
||||
// Create a new block DAG instance with the appropriate configuration.
|
||||
dag, err := setupDAG(cfg, databaseContext, interrupt, sigCache, indexManager)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txMempool := setupMempool(cfg, dag, sigCache)
|
||||
|
||||
netAdapter, err := netadapter.NewNetAdapter(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addressManager := addressmanager.New(cfg, databaseContext)
|
||||
|
||||
connectionManager, err := connmanager.New(cfg, netAdapter, addressManager)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
protocolManager, err := protocol.NewManager(cfg, dag, netAdapter, addressManager, txMempool, connectionManager)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rpcServer, err := setupRPC(
|
||||
cfg, dag, txMempool, sigCache, acceptanceIndex, connectionManager, addressManager, protocolManager)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &App{
|
||||
cfg: cfg,
|
||||
rpcServer: rpcServer,
|
||||
protocolManager: protocolManager,
|
||||
connectionManager: connectionManager,
|
||||
netAdapter: netAdapter,
|
||||
addressManager: addressManager,
|
||||
}, nil
|
||||
// doUpgrades performs upgrades to kaspad as new versions require it.
|
||||
// currently it's a placeholder we got from kaspad upstream, that does nothing
|
||||
func doUpgrades() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) maybeSeedFromDNS() {
|
||||
if !a.cfg.DisableDNSSeed {
|
||||
dnsseed.SeedFromDNS(a.cfg.NetParams(), a.cfg.DNSSeed, domainmessage.SFNodeNetwork, false, nil,
|
||||
a.cfg.Lookup, func(addresses []*domainmessage.NetAddress) {
|
||||
// Kaspad uses a lookup of the dns seeder here. Since seeder returns
|
||||
// IPs of nodes and not its own IP, we can not know real IP of
|
||||
// source. So we'll take first returned address as source.
|
||||
a.addressManager.AddAddresses(addresses, addresses[0], nil)
|
||||
})
|
||||
}
|
||||
}
|
||||
func setupDAG(cfg *config.Config, databaseContext *dbaccess.DatabaseContext, interrupt <-chan struct{},
|
||||
sigCache *txscript.SigCache, indexManager blockdag.IndexManager) (*blockdag.BlockDAG, error) {
|
||||
|
||||
dag, err := blockdag.New(&blockdag.Config{
|
||||
Interrupt: interrupt,
|
||||
DatabaseContext: databaseContext,
|
||||
DAGParams: cfg.NetParams(),
|
||||
TimeSource: blockdag.NewTimeSource(),
|
||||
SigCache: sigCache,
|
||||
IndexManager: indexManager,
|
||||
SubnetworkID: cfg.SubnetworkID,
|
||||
})
|
||||
return dag, err
|
||||
// dbPath returns the path to the block database given a database type.
|
||||
func databasePath(cfg *config.Config) string {
|
||||
return filepath.Join(cfg.DataDir, "db")
|
||||
}
|
||||
|
||||
func setupIndexes(cfg *config.Config) (blockdag.IndexManager, *indexers.AcceptanceIndex) {
|
||||
// Create indexes if needed.
|
||||
var indexes []indexers.Indexer
|
||||
var acceptanceIndex *indexers.AcceptanceIndex
|
||||
if cfg.AcceptanceIndex {
|
||||
log.Info("acceptance index is enabled")
|
||||
indexes = append(indexes, acceptanceIndex)
|
||||
}
|
||||
|
||||
// Create an index manager if any of the optional indexes are enabled.
|
||||
if len(indexes) < 0 {
|
||||
return nil, nil
|
||||
}
|
||||
indexManager := indexers.NewManager(indexes)
|
||||
return indexManager, acceptanceIndex
|
||||
func removeDatabase(cfg *config.Config) error {
|
||||
dbPath := databasePath(cfg)
|
||||
return os.RemoveAll(dbPath)
|
||||
}
|
||||
|
||||
func setupMempool(cfg *config.Config, dag *blockdag.BlockDAG, sigCache *txscript.SigCache) *mempool.TxPool {
|
||||
mempoolConfig := mempool.Config{
|
||||
Policy: mempool.Policy{
|
||||
AcceptNonStd: cfg.RelayNonStd,
|
||||
MaxOrphanTxs: cfg.MaxOrphanTxs,
|
||||
MaxOrphanTxSize: config.DefaultMaxOrphanTxSize,
|
||||
MinRelayTxFee: cfg.MinRelayTxFee,
|
||||
MaxTxVersion: 1,
|
||||
},
|
||||
CalcSequenceLockNoLock: func(tx *util.Tx, utxoSet blockdag.UTXOSet) (*blockdag.SequenceLock, error) {
|
||||
return dag.CalcSequenceLockNoLock(tx, utxoSet, true)
|
||||
},
|
||||
IsDeploymentActive: dag.IsDeploymentActive,
|
||||
SigCache: sigCache,
|
||||
DAG: dag,
|
||||
}
|
||||
|
||||
return mempool.New(&mempoolConfig)
|
||||
}
|
||||
|
||||
func setupRPC(cfg *config.Config,
|
||||
dag *blockdag.BlockDAG,
|
||||
txMempool *mempool.TxPool,
|
||||
sigCache *txscript.SigCache,
|
||||
acceptanceIndex *indexers.AcceptanceIndex,
|
||||
connectionManager *connmanager.ConnectionManager,
|
||||
addressManager *addressmanager.AddressManager,
|
||||
protocolManager *protocol.Manager) (*rpc.Server, error) {
|
||||
|
||||
if !cfg.DisableRPC {
|
||||
policy := mining.Policy{
|
||||
BlockMaxMass: cfg.BlockMaxMass,
|
||||
}
|
||||
blockTemplateGenerator := mining.NewBlkTmplGenerator(&policy, txMempool, dag, sigCache)
|
||||
|
||||
rpcServer, err := rpc.NewRPCServer(cfg, dag, txMempool, acceptanceIndex, blockTemplateGenerator,
|
||||
connectionManager, addressManager, protocolManager)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Signal process shutdown when the RPC server requests it.
|
||||
spawn("setupRPC-handleShutdownRequest", func() {
|
||||
<-rpcServer.RequestedProcessShutdown()
|
||||
signal.ShutdownRequestChannel <- struct{}{}
|
||||
})
|
||||
|
||||
return rpcServer, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// P2PNodeID returns the network ID associated with this App
|
||||
func (a *App) P2PNodeID() *id.ID {
|
||||
return a.netAdapter.ID()
|
||||
}
|
||||
|
||||
// AddressManager returns the AddressManager associated with this App
|
||||
func (a *App) AddressManager() *addressmanager.AddressManager {
|
||||
return a.addressManager
|
||||
}
|
||||
|
||||
// WaitForShutdown blocks until the main listener and peer handlers are stopped.
|
||||
func (a *App) WaitForShutdown() {
|
||||
// TODO(libp2p)
|
||||
// a.p2pServer.WaitForShutdown()
|
||||
func openDB(cfg *config.Config) (*dbaccess.DatabaseContext, error) {
|
||||
dbPath := databasePath(cfg)
|
||||
log.Infof("Loading database from '%s'", dbPath)
|
||||
return dbaccess.New(dbPath)
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ to a remote node running a kaspa peer. Example syntax is:
|
||||
|
||||
// Reads and validates the next kaspa message from conn using the
|
||||
// protocol version pver and the kaspa network kaspanet. The returns
|
||||
// are a domainmessage.Message, a []byte which contains the unmarshalled
|
||||
// are a appmessage.Message, a []byte which contains the unmarshalled
|
||||
// raw payload, and a possible error.
|
||||
msg, rawPayload, err := wire.ReadMessage(conn, pver, kaspanet)
|
||||
if err != nil {
|
||||
24
app/appmessage/base_message.go
Normal file
24
app/appmessage/base_message.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package appmessage
|
||||
|
||||
import "time"
|
||||
|
||||
type baseMessage struct {
|
||||
messageNumber uint64
|
||||
receivedAt time.Time
|
||||
}
|
||||
|
||||
func (b *baseMessage) MessageNumber() uint64 {
|
||||
return b.messageNumber
|
||||
}
|
||||
|
||||
func (b *baseMessage) SetMessageNumber(messageNumber uint64) {
|
||||
b.messageNumber = messageNumber
|
||||
}
|
||||
|
||||
func (b *baseMessage) ReceivedAt() time.Time {
|
||||
return b.receivedAt
|
||||
}
|
||||
|
||||
func (b *baseMessage) SetReceivedAt(receivedAt time.Time) {
|
||||
b.receivedAt = receivedAt
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
)
|
||||
|
||||
// genesisCoinbaseTx is the coinbase transaction for the genesis blocks for
|
||||
// the main network, regression test network, and test network.
|
||||
// the main network and test network.
|
||||
var genesisCoinbaseTxIns = []*TxIn{
|
||||
{
|
||||
PreviousOutpoint: Outpoint{
|
||||
@@ -352,7 +352,7 @@ func BenchmarkReadBlockHeader(b *testing.B) {
|
||||
0x3a, 0x9f, 0xb8, 0xaa, 0x4b, 0x1e, 0x5e, 0x4a, // MerkleRoot
|
||||
0x29, 0xab, 0x5f, 0x49, 0x00, 0x00, 0x00, 0x00, // Timestamp
|
||||
0xff, 0xff, 0x00, 0x1d, // Bits
|
||||
0xf3, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // Fake Nonce. TODO: (Ori) Replace to a real nonce
|
||||
0xf3, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // Fake Nonce
|
||||
0x00, // TxnCount Varint
|
||||
}
|
||||
r := bytes.NewReader(buf)
|
||||
@@ -411,3 +411,21 @@ func BenchmarkDoubleHashH(b *testing.B) {
|
||||
_ = daghash.DoubleHashH(txBytes)
|
||||
}
|
||||
}
|
||||
|
||||
// BenchmarkDoubleHashWriter performs a benchmark on how long it takes to perform
|
||||
// a double hash via the writer returning a daghash.Hash.
|
||||
func BenchmarkDoubleHashWriter(b *testing.B) {
|
||||
var buf bytes.Buffer
|
||||
err := genesisCoinbaseTx.Serialize(&buf)
|
||||
if err != nil {
|
||||
b.Fatalf("Serialize: unexpected error: %+v", err)
|
||||
}
|
||||
txBytes := buf.Bytes()
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
writer := daghash.NewDoubleHashWriter()
|
||||
_, _ = writer.Write(txBytes)
|
||||
writer.Finalize()
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"github.com/kaspanet/kaspad/netadapter/id"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/id"
|
||||
"github.com/kaspanet/kaspad/util/binaryserializer"
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
"github.com/kaspanet/kaspad/util/mstime"
|
||||
@@ -375,30 +375,31 @@ func ReadVarInt(r io.Reader) (uint64, error) {
|
||||
// on its value.
|
||||
func WriteVarInt(w io.Writer, val uint64) error {
|
||||
if val < 0xfd {
|
||||
return binaryserializer.PutUint8(w, uint8(val))
|
||||
_, err := w.Write([]byte{uint8(val)})
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if val <= math.MaxUint16 {
|
||||
err := binaryserializer.PutUint8(w, 0xfd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return binaryserializer.PutUint16(w, littleEndian, uint16(val))
|
||||
var buf [3]byte
|
||||
buf[0] = 0xfd
|
||||
littleEndian.PutUint16(buf[1:], uint16(val))
|
||||
_, err := w.Write(buf[:])
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if val <= math.MaxUint32 {
|
||||
err := binaryserializer.PutUint8(w, 0xfe)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return binaryserializer.PutUint32(w, littleEndian, uint32(val))
|
||||
var buf [5]byte
|
||||
buf[0] = 0xfe
|
||||
littleEndian.PutUint32(buf[1:], uint32(val))
|
||||
_, err := w.Write(buf[:])
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
err := binaryserializer.PutUint8(w, 0xff)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return binaryserializer.PutUint64(w, littleEndian, val)
|
||||
var buf [9]byte
|
||||
buf[0] = 0xff
|
||||
littleEndian.PutUint64(buf[1:], val)
|
||||
_, err := w.Write(buf[:])
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
// VarIntSerializeSize returns the number of bytes it would take to serialize
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -57,7 +57,7 @@ var exampleUTXOCommitment = &daghash.Hash{
|
||||
0x65, 0x9C, 0x79, 0x3C, 0xE3, 0x70, 0xD9, 0x5F,
|
||||
}
|
||||
|
||||
// TestElementEncoding tests domainmessage encode and decode for various element types. This
|
||||
// TestElementEncoding tests appmessage encode and decode for various element types. This
|
||||
// is mainly to test the "fast" paths in readElement and writeElement which use
|
||||
// type assertions to avoid reflection when possible.
|
||||
func TestElementEncoding(t *testing.T) {
|
||||
@@ -129,7 +129,7 @@ func TestElementEncoding(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
// Write to domainmessage format.
|
||||
// Write to appmessage format.
|
||||
var buf bytes.Buffer
|
||||
err := WriteElement(&buf, test.in)
|
||||
if err != nil {
|
||||
@@ -142,7 +142,7 @@ func TestElementEncoding(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Read from domainmessage format.
|
||||
// Read from appmessage format.
|
||||
rbuf := bytes.NewReader(test.buf)
|
||||
val := test.in
|
||||
if reflect.ValueOf(test.in).Kind() != reflect.Ptr {
|
||||
@@ -165,7 +165,7 @@ func TestElementEncoding(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestElementEncodingErrors performs negative tests against domainmessage encode and decode
|
||||
// TestElementEncodingErrors performs negative tests against appmessage encode and decode
|
||||
// of various element types to confirm error paths work correctly.
|
||||
func TestElementEncodingErrors(t *testing.T) {
|
||||
type writeElementReflect int32
|
||||
@@ -209,7 +209,7 @@ func TestElementEncodingErrors(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
// Encode to domainmessage format.
|
||||
// Encode to appmessage format.
|
||||
w := newFixedWriter(test.max)
|
||||
err := WriteElement(w, test.in)
|
||||
if !errors.Is(err, test.writeErr) {
|
||||
@@ -218,7 +218,7 @@ func TestElementEncodingErrors(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Decode from domainmessage format.
|
||||
// Decode from appmessage format.
|
||||
r := newFixedReader(test.max, nil)
|
||||
val := test.in
|
||||
if reflect.ValueOf(test.in).Kind() != reflect.Ptr {
|
||||
@@ -233,7 +233,7 @@ func TestElementEncodingErrors(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestVarIntEncoding tests domainmessage encode and decode for variable length integers.
|
||||
// TestVarIntEncoding tests appmessage encode and decode for variable length integers.
|
||||
func TestVarIntEncoding(t *testing.T) {
|
||||
tests := []struct {
|
||||
value uint64 // Value to encode
|
||||
@@ -266,7 +266,7 @@ func TestVarIntEncoding(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
// Encode to domainmessage format.
|
||||
// Encode to appmessage format.
|
||||
buf := &bytes.Buffer{}
|
||||
err := WriteVarInt(buf, test.value)
|
||||
if err != nil {
|
||||
@@ -279,7 +279,7 @@ func TestVarIntEncoding(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Decode from domainmessage format.
|
||||
// Decode from appmessage format.
|
||||
rbuf := bytes.NewReader(test.buf)
|
||||
val, err := ReadVarInt(rbuf)
|
||||
if err != nil {
|
||||
@@ -294,7 +294,7 @@ func TestVarIntEncoding(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestVarIntEncodingErrors performs negative tests against domainmessage encode and decode
|
||||
// TestVarIntEncodingErrors performs negative tests against appmessage encode and decode
|
||||
// of variable length integers to confirm error paths work correctly.
|
||||
func TestVarIntEncodingErrors(t *testing.T) {
|
||||
tests := []struct {
|
||||
@@ -319,7 +319,7 @@ func TestVarIntEncodingErrors(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
// Encode to domainmessage format.
|
||||
// Encode to appmessage format.
|
||||
w := newFixedWriter(test.max)
|
||||
err := WriteVarInt(w, test.in)
|
||||
if !errors.Is(err, test.writeErr) {
|
||||
@@ -328,7 +328,7 @@ func TestVarIntEncodingErrors(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Decode from domainmessage format.
|
||||
// Decode from appmessage format.
|
||||
r := newFixedReader(test.max, test.buf)
|
||||
_, err = ReadVarInt(r)
|
||||
if !errors.Is(err, test.readErr) {
|
||||
@@ -347,7 +347,7 @@ func TestVarIntNonCanonical(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string // Test name for easier identification
|
||||
in []byte // Value to decode
|
||||
pver uint32 // Protocol version for domainmessage encoding
|
||||
pver uint32 // Protocol version for appmessage encoding
|
||||
}{
|
||||
{
|
||||
"0 encoded with 3 bytes", []byte{0xfd, 0x00, 0x00},
|
||||
@@ -379,7 +379,7 @@ func TestVarIntNonCanonical(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
// Decode from domainmessage format.
|
||||
// Decode from appmessage format.
|
||||
rbuf := bytes.NewReader(test.in)
|
||||
val, err := ReadVarInt(rbuf)
|
||||
if msgErr := &(MessageError{}); !errors.As(err, &msgErr) {
|
||||
@@ -430,7 +430,7 @@ func TestVarIntSerializeSize(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestVarStringEncoding tests domainmessage encode and decode for variable length strings.
|
||||
// TestVarStringEncoding tests appmessage encode and decode for variable length strings.
|
||||
func TestVarStringEncoding(t *testing.T) {
|
||||
pver := ProtocolVersion
|
||||
|
||||
@@ -441,7 +441,7 @@ func TestVarStringEncoding(t *testing.T) {
|
||||
in string // String to encode
|
||||
out string // String to decoded value
|
||||
buf []byte // Encoded value
|
||||
pver uint32 // Protocol version for domainmessage encoding
|
||||
pver uint32 // Protocol version for appmessage encoding
|
||||
}{
|
||||
// Latest protocol version.
|
||||
// Empty string
|
||||
@@ -454,7 +454,7 @@ func TestVarStringEncoding(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
// Encode to domainmessage format.
|
||||
// Encode to appmessage format.
|
||||
var buf bytes.Buffer
|
||||
err := WriteVarString(&buf, test.in)
|
||||
if err != nil {
|
||||
@@ -467,7 +467,7 @@ func TestVarStringEncoding(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Decode from domainmessage format.
|
||||
// Decode from appmessage format.
|
||||
rbuf := bytes.NewReader(test.buf)
|
||||
val, err := ReadVarString(rbuf, test.pver)
|
||||
if err != nil {
|
||||
@@ -482,7 +482,7 @@ func TestVarStringEncoding(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestVarStringEncodingErrors performs negative tests against domainmessage encode and
|
||||
// TestVarStringEncodingErrors performs negative tests against appmessage encode and
|
||||
// decode of variable length strings to confirm error paths work correctly.
|
||||
func TestVarStringEncodingErrors(t *testing.T) {
|
||||
pver := ProtocolVersion
|
||||
@@ -493,7 +493,7 @@ func TestVarStringEncodingErrors(t *testing.T) {
|
||||
tests := []struct {
|
||||
in string // Value to encode
|
||||
buf []byte // Encoded value
|
||||
pver uint32 // Protocol version for domainmessage encoding
|
||||
pver uint32 // Protocol version for appmessage encoding
|
||||
max int // Max size of fixed buffer to induce errors
|
||||
writeErr error // Expected write error
|
||||
readErr error // Expected read error
|
||||
@@ -509,7 +509,7 @@ func TestVarStringEncodingErrors(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
// Encode to domainmessage format.
|
||||
// Encode to appmessage format.
|
||||
w := newFixedWriter(test.max)
|
||||
err := WriteVarString(w, test.in)
|
||||
if !errors.Is(err, test.writeErr) {
|
||||
@@ -518,7 +518,7 @@ func TestVarStringEncodingErrors(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Decode from domainmessage format.
|
||||
// Decode from appmessage format.
|
||||
r := newFixedReader(test.max, test.buf)
|
||||
_, err = ReadVarString(r, test.pver)
|
||||
if !errors.Is(err, test.readErr) {
|
||||
@@ -538,7 +538,7 @@ func TestVarStringOverflowErrors(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
buf []byte // Encoded value
|
||||
pver uint32 // Protocol version for domainmessage encoding
|
||||
pver uint32 // Protocol version for appmessage encoding
|
||||
err error // Expected error
|
||||
}{
|
||||
{[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
@@ -549,7 +549,7 @@ func TestVarStringOverflowErrors(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
// Decode from domainmessage format.
|
||||
// Decode from appmessage format.
|
||||
rbuf := bytes.NewReader(test.buf)
|
||||
_, err := ReadVarString(rbuf, test.pver)
|
||||
if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
|
||||
@@ -561,7 +561,7 @@ func TestVarStringOverflowErrors(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
// TestVarBytesEncoding tests domainmessage encode and decode for variable length byte array.
|
||||
// TestVarBytesEncoding tests appmessage encode and decode for variable length byte array.
|
||||
func TestVarBytesEncoding(t *testing.T) {
|
||||
pver := ProtocolVersion
|
||||
|
||||
@@ -571,7 +571,7 @@ func TestVarBytesEncoding(t *testing.T) {
|
||||
tests := []struct {
|
||||
in []byte // Byte Array to write
|
||||
buf []byte // Encoded value
|
||||
pver uint32 // Protocol version for domainmessage encoding
|
||||
pver uint32 // Protocol version for appmessage encoding
|
||||
}{
|
||||
// Latest protocol version.
|
||||
// Empty byte array
|
||||
@@ -584,7 +584,7 @@ func TestVarBytesEncoding(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
// Encode to domainmessage format.
|
||||
// Encode to appmessage format.
|
||||
var buf bytes.Buffer
|
||||
err := WriteVarBytes(&buf, test.pver, test.in)
|
||||
if err != nil {
|
||||
@@ -597,7 +597,7 @@ func TestVarBytesEncoding(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Decode from domainmessage format.
|
||||
// Decode from appmessage format.
|
||||
rbuf := bytes.NewReader(test.buf)
|
||||
val, err := ReadVarBytes(rbuf, test.pver, MaxMessagePayload,
|
||||
"test payload")
|
||||
@@ -613,7 +613,7 @@ func TestVarBytesEncoding(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestVarBytesEncodingErrors performs negative tests against domainmessage encode and
|
||||
// TestVarBytesEncodingErrors performs negative tests against appmessage encode and
|
||||
// decode of variable length byte arrays to confirm error paths work correctly.
|
||||
func TestVarBytesEncodingErrors(t *testing.T) {
|
||||
pver := ProtocolVersion
|
||||
@@ -624,7 +624,7 @@ func TestVarBytesEncodingErrors(t *testing.T) {
|
||||
tests := []struct {
|
||||
in []byte // Byte Array to write
|
||||
buf []byte // Encoded value
|
||||
pver uint32 // Protocol version for domainmessage encoding
|
||||
pver uint32 // Protocol version for appmessage encoding
|
||||
max int // Max size of fixed buffer to induce errors
|
||||
writeErr error // Expected write error
|
||||
readErr error // Expected read error
|
||||
@@ -640,7 +640,7 @@ func TestVarBytesEncodingErrors(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
// Encode to domainmessage format.
|
||||
// Encode to appmessage format.
|
||||
w := newFixedWriter(test.max)
|
||||
err := WriteVarBytes(w, test.pver, test.in)
|
||||
if !errors.Is(err, test.writeErr) {
|
||||
@@ -649,7 +649,7 @@ func TestVarBytesEncodingErrors(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Decode from domainmessage format.
|
||||
// Decode from appmessage format.
|
||||
r := newFixedReader(test.max, test.buf)
|
||||
_, err = ReadVarBytes(r, test.pver, MaxMessagePayload,
|
||||
"test payload")
|
||||
@@ -670,7 +670,7 @@ func TestVarBytesOverflowErrors(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
buf []byte // Encoded value
|
||||
pver uint32 // Protocol version for domainmessage encoding
|
||||
pver uint32 // Protocol version for appmessage encoding
|
||||
err error // Expected error
|
||||
}{
|
||||
{[]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
@@ -681,7 +681,7 @@ func TestVarBytesOverflowErrors(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
// Decode from domainmessage format.
|
||||
// Decode from appmessage format.
|
||||
rbuf := bytes.NewReader(test.buf)
|
||||
_, err := ReadVarBytes(rbuf, test.pver, MaxMessagePayload,
|
||||
"test payload")
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
Package domainmessage implements the kaspa domainmessage protocol.
|
||||
Package appmessage implements the kaspa appmessage protocol.
|
||||
|
||||
At a high level, this package provides support for marshalling and unmarshalling
|
||||
supported kaspa messages to and from the domainmessage. This package does not deal
|
||||
supported kaspa messages to and from the appmessage. This package does not deal
|
||||
with the specifics of message handling such as what to do when a message is
|
||||
received. This provides the caller with a high level of flexibility.
|
||||
|
||||
@@ -19,7 +19,7 @@ Message which allows messages of any type to be read, written, or passed around
|
||||
through channels, functions, etc. In addition, concrete implementations of most
|
||||
of the currently supported kaspa messages are provided. For these supported
|
||||
messages, all of the details of marshalling and unmarshalling to and from the
|
||||
domainmessage using kaspa encoding are handled so the caller doesn't have to concern
|
||||
appmessage using kaspa encoding are handled so the caller doesn't have to concern
|
||||
themselves with the specifics.
|
||||
|
||||
Message Interaction
|
||||
@@ -55,7 +55,7 @@ Protocol Version
|
||||
|
||||
The protocol version should be negotiated with the remote peer at a higher
|
||||
level than this package via the version (MsgVersion) message exchange, however,
|
||||
this package provides the domainmessage.ProtocolVersion constant which indicates the
|
||||
this package provides the appmessage.ProtocolVersion constant which indicates the
|
||||
latest protocol version this package supports and is typically the value to use
|
||||
for all outbound connections before a potentially lower protocol version is
|
||||
negotiated.
|
||||
@@ -66,11 +66,10 @@ The kaspa network is a magic number which is used to identify the start of a
|
||||
message and which kaspa network the message applies to. This package provides
|
||||
the following constants:
|
||||
|
||||
domainmessage.Mainnet
|
||||
domainmessage.Testnet (Test network)
|
||||
domainmessage.Regtest (Regression test network)
|
||||
domainmessage.Simnet (Simulation test network)
|
||||
domainmessage.Devnet (Development network)
|
||||
appmessage.Mainnet
|
||||
appmessage.Testnet (Test network)
|
||||
appmessage.Simnet (Simulation test network)
|
||||
appmessage.Devnet (Development network)
|
||||
|
||||
Determining Message Type
|
||||
|
||||
@@ -82,43 +81,43 @@ switch or type assertion. An example of a type switch follows:
|
||||
// Assumes msg is already a valid concrete message such as one created
|
||||
// via NewMsgVersion or read via ReadMessage.
|
||||
switch msg := msg.(type) {
|
||||
case *domainmessage.MsgVersion:
|
||||
case *appmessage.MsgVersion:
|
||||
// The message is a pointer to a MsgVersion struct.
|
||||
fmt.Printf("Protocol version: %d", msg.ProtocolVersion)
|
||||
case *domainmessage.MsgBlock:
|
||||
case *appmessage.MsgBlock:
|
||||
// The message is a pointer to a MsgBlock struct.
|
||||
fmt.Printf("Number of tx in block: %d", msg.Header.TxnCount)
|
||||
}
|
||||
|
||||
Reading Messages
|
||||
|
||||
In order to unmarshall kaspa messages from the domainmessage, use the ReadMessage
|
||||
In order to unmarshall kaspa messages from the appmessage, use the ReadMessage
|
||||
function. It accepts any io.Reader, but typically this will be a net.Conn to
|
||||
a remote node running a kaspa peer. Example syntax is:
|
||||
|
||||
// Reads and validates the next kaspa message from conn using the
|
||||
// protocol version pver and the kaspa network kaspaNet. The returns
|
||||
// are a domainmessage.Message, a []byte which contains the unmarshalled
|
||||
// are a appmessage.Message, a []byte which contains the unmarshalled
|
||||
// raw payload, and a possible error.
|
||||
msg, rawPayload, err := domainmessage.ReadMessage(conn, pver, kaspaNet)
|
||||
msg, rawPayload, err := appmessage.ReadMessage(conn, pver, kaspaNet)
|
||||
if err != nil {
|
||||
// Log and handle the error
|
||||
}
|
||||
|
||||
Writing Messages
|
||||
|
||||
In order to marshall kaspa messages to the domainmessage, use the WriteMessage
|
||||
In order to marshall kaspa messages to the appmessage, use the WriteMessage
|
||||
function. It accepts any io.Writer, but typically this will be a net.Conn to
|
||||
a remote node running a kaspa peer. Example syntax to request addresses
|
||||
from a remote peer is:
|
||||
|
||||
// Create a new getaddr kaspa message.
|
||||
msg := domainmessage.NewMsgRequestAddresses()
|
||||
msg := appmessage.NewMsgRequestAddresses()
|
||||
|
||||
// Writes a kaspa message msg to conn using the protocol version
|
||||
// pver, and the kaspa network kaspaNet. The return is a possible
|
||||
// error.
|
||||
err := domainmessage.WriteMessage(conn, msg, pver, kaspaNet)
|
||||
err := appmessage.WriteMessage(conn, msg, pver, kaspaNet)
|
||||
if err != nil {
|
||||
// Log and handle the error
|
||||
}
|
||||
@@ -127,8 +126,8 @@ Errors
|
||||
|
||||
Errors returned by this package are either the raw errors provided by underlying
|
||||
calls to read/write from streams such as io.EOF, io.ErrUnexpectedEOF, and
|
||||
io.ErrShortWrite, or of type domainmessage.MessageError. This allows the caller to
|
||||
io.ErrShortWrite, or of type appmessage.MessageError. This allows the caller to
|
||||
differentiate between general IO errors and malformed messages through type
|
||||
assertions.
|
||||
*/
|
||||
package domainmessage
|
||||
package appmessage
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -32,3 +32,16 @@ func (e *MessageError) Error() string {
|
||||
func messageError(f string, desc string) *MessageError {
|
||||
return &MessageError{Func: f, Description: desc}
|
||||
}
|
||||
|
||||
// RPCError represents an error arriving from the RPC
|
||||
type RPCError struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
// RPCErrorf formats according to a format specifier and returns the string
|
||||
// as an RPCError.
|
||||
func RPCErrorf(format string, args ...interface{}) *RPCError {
|
||||
return &RPCError{
|
||||
Message: fmt.Sprintf(format, args...),
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
195
app/appmessage/message.go
Normal file
195
app/appmessage/message.go
Normal file
@@ -0,0 +1,195 @@
|
||||
// Copyright (c) 2013-2016 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// MaxMessagePayload is the maximum bytes a message can be regardless of other
|
||||
// individual limits imposed by messages themselves.
|
||||
const MaxMessagePayload = 1024 * 1024 * 32 // 32MB
|
||||
|
||||
// MessageCommand is a number in the header of a message that represents its type.
|
||||
type MessageCommand uint32
|
||||
|
||||
func (cmd MessageCommand) String() string {
|
||||
cmdString, ok := ProtocolMessageCommandToString[cmd]
|
||||
if !ok {
|
||||
cmdString, ok = RPCMessageCommandToString[cmd]
|
||||
}
|
||||
if !ok {
|
||||
cmdString = "unknown command"
|
||||
}
|
||||
return fmt.Sprintf("%s [code %d]", cmdString, uint8(cmd))
|
||||
}
|
||||
|
||||
// Commands used in kaspa message headers which describe the type of message.
|
||||
const (
|
||||
// protocol
|
||||
CmdVersion MessageCommand = iota
|
||||
CmdVerAck
|
||||
CmdRequestAddresses
|
||||
CmdAddresses
|
||||
CmdRequestIBDBlocks
|
||||
CmdBlock
|
||||
CmdTx
|
||||
CmdPing
|
||||
CmdPong
|
||||
CmdRequestBlockLocator
|
||||
CmdBlockLocator
|
||||
CmdSelectedTip
|
||||
CmdRequestSelectedTip
|
||||
CmdInvRelayBlock
|
||||
CmdRequestRelayBlocks
|
||||
CmdInvTransaction
|
||||
CmdRequestTransactions
|
||||
CmdIBDBlock
|
||||
CmdRequestNextIBDBlocks
|
||||
CmdDoneIBDBlocks
|
||||
CmdTransactionNotFound
|
||||
CmdReject
|
||||
|
||||
// rpc
|
||||
CmdGetCurrentNetworkRequestMessage
|
||||
CmdGetCurrentNetworkResponseMessage
|
||||
CmdSubmitBlockRequestMessage
|
||||
CmdSubmitBlockResponseMessage
|
||||
CmdGetBlockTemplateRequestMessage
|
||||
CmdGetBlockTemplateResponseMessage
|
||||
CmdGetBlockTemplateTransactionMessage
|
||||
CmdNotifyBlockAddedRequestMessage
|
||||
CmdNotifyBlockAddedResponseMessage
|
||||
CmdBlockAddedNotificationMessage
|
||||
CmdGetPeerAddressesRequestMessage
|
||||
CmdGetPeerAddressesResponseMessage
|
||||
CmdGetSelectedTipHashRequestMessage
|
||||
CmdGetSelectedTipHashResponseMessage
|
||||
CmdGetMempoolEntryRequestMessage
|
||||
CmdGetMempoolEntryResponseMessage
|
||||
CmdGetConnectedPeerInfoRequestMessage
|
||||
CmdGetConnectedPeerInfoResponseMessage
|
||||
CmdAddPeerRequestMessage
|
||||
CmdAddPeerResponseMessage
|
||||
CmdSubmitTransactionRequestMessage
|
||||
CmdSubmitTransactionResponseMessage
|
||||
CmdNotifyChainChangedRequestMessage
|
||||
CmdNotifyChainChangedResponseMessage
|
||||
CmdChainChangedNotificationMessage
|
||||
CmdGetBlockRequestMessage
|
||||
CmdGetBlockResponseMessage
|
||||
CmdGetSubnetworkRequestMessage
|
||||
CmdGetSubnetworkResponseMessage
|
||||
CmdGetChainFromBlockRequestMessage
|
||||
CmdGetChainFromBlockResponseMessage
|
||||
CmdGetBlocksRequestMessage
|
||||
CmdGetBlocksResponseMessage
|
||||
CmdGetBlockCountRequestMessage
|
||||
CmdGetBlockCountResponseMessage
|
||||
CmdGetBlockDAGInfoRequestMessage
|
||||
CmdGetBlockDAGInfoResponseMessage
|
||||
CmdResolveFinalityConflictRequestMessage
|
||||
CmdResolveFinalityConflictResponseMessage
|
||||
CmdNotifyFinalityConflictsRequestMessage
|
||||
CmdNotifyFinalityConflictsResponseMessage
|
||||
CmdFinalityConflictNotificationMessage
|
||||
CmdFinalityConflictResolvedNotificationMessage
|
||||
CmdGetMempoolEntriesRequestMessage
|
||||
CmdGetMempoolEntriesResponseMessage
|
||||
CmdShutDownRequestMessage
|
||||
CmdShutDownResponseMessage
|
||||
CmdGetHeadersRequestMessage
|
||||
CmdGetHeadersResponseMessage
|
||||
)
|
||||
|
||||
// ProtocolMessageCommandToString maps all MessageCommands to their string representation
|
||||
var ProtocolMessageCommandToString = map[MessageCommand]string{
|
||||
CmdVersion: "Version",
|
||||
CmdVerAck: "VerAck",
|
||||
CmdRequestAddresses: "RequestAddresses",
|
||||
CmdAddresses: "Addresses",
|
||||
CmdRequestIBDBlocks: "RequestBlocks",
|
||||
CmdBlock: "Block",
|
||||
CmdTx: "Tx",
|
||||
CmdPing: "Ping",
|
||||
CmdPong: "Pong",
|
||||
CmdRequestBlockLocator: "RequestBlockLocator",
|
||||
CmdBlockLocator: "BlockLocator",
|
||||
CmdSelectedTip: "SelectedTip",
|
||||
CmdRequestSelectedTip: "RequestSelectedTip",
|
||||
CmdInvRelayBlock: "InvRelayBlock",
|
||||
CmdRequestRelayBlocks: "RequestRelayBlocks",
|
||||
CmdInvTransaction: "InvTransaction",
|
||||
CmdRequestTransactions: "RequestTransactions",
|
||||
CmdIBDBlock: "IBDBlock",
|
||||
CmdRequestNextIBDBlocks: "RequestNextIBDBlocks",
|
||||
CmdDoneIBDBlocks: "DoneIBDBlocks",
|
||||
CmdTransactionNotFound: "TransactionNotFound",
|
||||
CmdReject: "Reject",
|
||||
}
|
||||
|
||||
// RPCMessageCommandToString maps all MessageCommands to their string representation
|
||||
var RPCMessageCommandToString = map[MessageCommand]string{
|
||||
CmdGetCurrentNetworkRequestMessage: "GetCurrentNetworkRequest",
|
||||
CmdGetCurrentNetworkResponseMessage: "GetCurrentNetworkResponse",
|
||||
CmdSubmitBlockRequestMessage: "SubmitBlockRequest",
|
||||
CmdSubmitBlockResponseMessage: "SubmitBlockResponse",
|
||||
CmdGetBlockTemplateRequestMessage: "GetBlockTemplateRequest",
|
||||
CmdGetBlockTemplateResponseMessage: "GetBlockTemplateResponse",
|
||||
CmdGetBlockTemplateTransactionMessage: "CmdGetBlockTemplateTransaction",
|
||||
CmdNotifyBlockAddedRequestMessage: "NotifyBlockAddedRequest",
|
||||
CmdNotifyBlockAddedResponseMessage: "NotifyBlockAddedResponse",
|
||||
CmdBlockAddedNotificationMessage: "BlockAddedNotification",
|
||||
CmdGetPeerAddressesRequestMessage: "GetPeerAddressesRequest",
|
||||
CmdGetPeerAddressesResponseMessage: "GetPeerAddressesResponse",
|
||||
CmdGetSelectedTipHashRequestMessage: "GetSelectedTipHashRequest",
|
||||
CmdGetSelectedTipHashResponseMessage: "GetSelectedTipHashResponse",
|
||||
CmdGetMempoolEntryRequestMessage: "GetMempoolEntryRequest",
|
||||
CmdGetMempoolEntryResponseMessage: "GetMempoolEntryResponse",
|
||||
CmdGetConnectedPeerInfoRequestMessage: "GetConnectedPeerInfoRequest",
|
||||
CmdGetConnectedPeerInfoResponseMessage: "GetConnectedPeerInfoResponse",
|
||||
CmdAddPeerRequestMessage: "AddPeerRequest",
|
||||
CmdAddPeerResponseMessage: "AddPeerResponse",
|
||||
CmdSubmitTransactionRequestMessage: "SubmitTransactionRequest",
|
||||
CmdSubmitTransactionResponseMessage: "SubmitTransactionResponse",
|
||||
CmdNotifyChainChangedRequestMessage: "NotifyChainChangedRequest",
|
||||
CmdNotifyChainChangedResponseMessage: "NotifyChainChangedResponse",
|
||||
CmdChainChangedNotificationMessage: "ChainChangedNotification",
|
||||
CmdGetBlockRequestMessage: "GetBlockRequest",
|
||||
CmdGetBlockResponseMessage: "GetBlockResponse",
|
||||
CmdGetSubnetworkRequestMessage: "GetSubnetworkRequest",
|
||||
CmdGetSubnetworkResponseMessage: "GetSubnetworkResponse",
|
||||
CmdGetChainFromBlockRequestMessage: "GetChainFromBlockRequest",
|
||||
CmdGetChainFromBlockResponseMessage: "GetChainFromBlockResponse",
|
||||
CmdGetBlocksRequestMessage: "GetBlocksRequest",
|
||||
CmdGetBlocksResponseMessage: "GetBlocksResponse",
|
||||
CmdGetBlockCountRequestMessage: "GetBlockCountRequest",
|
||||
CmdGetBlockCountResponseMessage: "GetBlockCountResponse",
|
||||
CmdGetBlockDAGInfoRequestMessage: "GetBlockDAGInfoRequest",
|
||||
CmdGetBlockDAGInfoResponseMessage: "GetBlockDAGInfoResponse",
|
||||
CmdResolveFinalityConflictRequestMessage: "ResolveFinalityConflictRequest",
|
||||
CmdResolveFinalityConflictResponseMessage: "ResolveFinalityConflictResponse",
|
||||
CmdNotifyFinalityConflictsRequestMessage: "NotifyFinalityConflictsRequest",
|
||||
CmdNotifyFinalityConflictsResponseMessage: "NotifyFinalityConflictsResponse",
|
||||
CmdFinalityConflictNotificationMessage: "FinalityConflictNotification",
|
||||
CmdFinalityConflictResolvedNotificationMessage: "FinalityConflictResolvedNotification",
|
||||
CmdGetMempoolEntriesRequestMessage: "GetMempoolEntriesRequestMessage",
|
||||
CmdGetMempoolEntriesResponseMessage: "GetMempoolEntriesResponseMessage",
|
||||
CmdGetHeadersRequestMessage: "GetHeadersRequest",
|
||||
CmdGetHeadersResponseMessage: "GetHeadersResponse",
|
||||
}
|
||||
|
||||
// Message is an interface that describes a kaspa message. A type that
|
||||
// implements Message has complete control over the representation of its data
|
||||
// and may therefore contain additional or fewer fields than those which
|
||||
// are used directly in the protocol encoded message.
|
||||
type Message interface {
|
||||
Command() MessageCommand
|
||||
MessageNumber() uint64
|
||||
SetMessageNumber(index uint64)
|
||||
ReceivedAt() time.Time
|
||||
SetReceivedAt(receivedAt time.Time)
|
||||
}
|
||||
@@ -2,13 +2,15 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
"github.com/kaspanet/kaspad/util/mstime"
|
||||
"github.com/pkg/errors"
|
||||
"io"
|
||||
"math"
|
||||
)
|
||||
|
||||
// BaseBlockHeaderPayload is the base number of bytes a block header can be,
|
||||
@@ -59,19 +61,28 @@ type BlockHeader struct {
|
||||
|
||||
// NumParentBlocks return the number of entries in ParentHashes
|
||||
func (h *BlockHeader) NumParentBlocks() byte {
|
||||
return byte(len(h.ParentHashes))
|
||||
numParents := len(h.ParentHashes)
|
||||
if numParents > math.MaxUint8 {
|
||||
panic(errors.Errorf("number of parents is %d, which is more than one byte can fit", numParents))
|
||||
}
|
||||
return byte(numParents)
|
||||
}
|
||||
|
||||
// BlockHash computes the block identifier hash for the given block header.
|
||||
func (h *BlockHeader) BlockHash() *daghash.Hash {
|
||||
// Encode the header and double sha256 everything prior to the number of
|
||||
// transactions. Ignore the error returns since there is no way the
|
||||
// encode could fail except being out of memory which would cause a
|
||||
// run-time panic.
|
||||
buf := bytes.NewBuffer(make([]byte, 0, BaseBlockHeaderPayload+h.NumParentBlocks()))
|
||||
_ = writeBlockHeader(buf, 0, h)
|
||||
// transactions.
|
||||
writer := daghash.NewDoubleHashWriter()
|
||||
err := writeBlockHeader(writer, 0, h)
|
||||
if err != nil {
|
||||
// It seems like this could only happen if the writer returned an error.
|
||||
// and this writer should never return an error (no allocations or possible failures)
|
||||
// the only non-writer error path here is unknown types in `WriteElement`
|
||||
panic(fmt.Sprintf("BlockHash() failed. this should never fail unless BlockHeader was changed. err: %+v", err))
|
||||
}
|
||||
|
||||
return daghash.DoubleHashP(buf.Bytes())
|
||||
res := writer.Finalize()
|
||||
return &res
|
||||
}
|
||||
|
||||
// IsGenesis returns true iff this block is a genesis block
|
||||
@@ -82,7 +93,7 @@ func (h *BlockHeader) IsGenesis() bool {
|
||||
// KaspaDecode decodes r using the kaspa protocol encoding into the receiver.
|
||||
// This is part of the Message interface implementation.
|
||||
// See Deserialize for decoding block headers stored to disk, such as in a
|
||||
// database, as opposed to decoding block headers from the domainmessage.
|
||||
// database, as opposed to decoding block headers from the appmessage.
|
||||
func (h *BlockHeader) KaspaDecode(r io.Reader, pver uint32) error {
|
||||
return readBlockHeader(r, pver, h)
|
||||
}
|
||||
@@ -90,7 +101,7 @@ func (h *BlockHeader) KaspaDecode(r io.Reader, pver uint32) error {
|
||||
// KaspaEncode encodes the receiver to w using the kaspa protocol encoding.
|
||||
// This is part of the Message interface implementation.
|
||||
// See Serialize for encoding block headers to be stored to disk, such as in a
|
||||
// database, as opposed to encoding block headers for the domainmessage.
|
||||
// database, as opposed to encoding block headers for the appmessage.
|
||||
func (h *BlockHeader) KaspaEncode(w io.Writer, pver uint32) error {
|
||||
return writeBlockHeader(w, pver, h)
|
||||
}
|
||||
@@ -99,7 +110,7 @@ func (h *BlockHeader) KaspaEncode(w io.Writer, pver uint32) error {
|
||||
// that is suitable for long-term storage such as a database while respecting
|
||||
// the Version field.
|
||||
func (h *BlockHeader) Deserialize(r io.Reader) error {
|
||||
// At the current time, there is no difference between the domainmessage encoding
|
||||
// At the current time, there is no difference between the appmessage encoding
|
||||
// at protocol version 0 and the stable long-term storage format. As
|
||||
// a result, make use of readBlockHeader.
|
||||
return readBlockHeader(r, 0, h)
|
||||
@@ -109,7 +120,7 @@ func (h *BlockHeader) Deserialize(r io.Reader) error {
|
||||
// that is suitable for long-term storage such as a database while respecting
|
||||
// the Version field.
|
||||
func (h *BlockHeader) Serialize(w io.Writer) error {
|
||||
// At the current time, there is no difference between the domainmessage encoding
|
||||
// At the current time, there is no difference between the appmessage encoding
|
||||
// at protocol version 0 and the stable long-term storage format. As
|
||||
// a result, make use of writeBlockHeader.
|
||||
return writeBlockHeader(w, 0, h)
|
||||
@@ -143,7 +154,7 @@ func NewBlockHeader(version int32, parentHashes []*daghash.Hash, hashMerkleRoot
|
||||
|
||||
// readBlockHeader reads a kaspa block header from r. See Deserialize for
|
||||
// decoding block headers stored to disk, such as in a database, as opposed to
|
||||
// decoding from the domainmessage.
|
||||
// decoding from the appmessage.
|
||||
func readBlockHeader(r io.Reader, pver uint32, bh *BlockHeader) error {
|
||||
var numParentBlocks byte
|
||||
err := readElements(r, &bh.Version, &numParentBlocks)
|
||||
@@ -169,7 +180,7 @@ func readBlockHeader(r io.Reader, pver uint32, bh *BlockHeader) error {
|
||||
|
||||
// writeBlockHeader writes a kaspa block header to w. See Serialize for
|
||||
// encoding block headers to be stored to disk, such as in a database, as
|
||||
// opposed to encoding for the domainmessage.
|
||||
// opposed to encoding for the appmessage.
|
||||
func writeBlockHeader(w io.Writer, pver uint32, bh *BlockHeader) error {
|
||||
timestamp := bh.Timestamp.UnixMilliseconds()
|
||||
if err := writeElements(w, bh.Version, bh.NumParentBlocks()); err != nil {
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -47,7 +47,7 @@ func TestBlockHeader(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestBlockHeaderEncoding tests the BlockHeader domainmessage encode and decode for various
|
||||
// TestBlockHeaderEncoding tests the BlockHeader appmessage encode and decode for various
|
||||
// protocol versions.
|
||||
func TestBlockHeaderEncoding(t *testing.T) {
|
||||
nonce := uint64(123123) // 0x000000000001e0f3
|
||||
@@ -66,7 +66,7 @@ func TestBlockHeaderEncoding(t *testing.T) {
|
||||
Nonce: nonce,
|
||||
}
|
||||
|
||||
// baseBlockHdrEncoded is the domainmessage encoded bytes of baseBlockHdr.
|
||||
// baseBlockHdrEncoded is the appmessage encoded bytes of baseBlockHdr.
|
||||
baseBlockHdrEncoded := []byte{
|
||||
0x01, 0x00, 0x00, 0x00, // Version 1
|
||||
0x02, // NumParentBlocks
|
||||
@@ -92,14 +92,14 @@ func TestBlockHeaderEncoding(t *testing.T) {
|
||||
0x65, 0x9C, 0x79, 0x3C, 0xE3, 0x70, 0xD9, 0x5F,
|
||||
0x99, 0x0f, 0xed, 0x15, 0x73, 0x01, 0x00, 0x00, // Timestamp
|
||||
0xff, 0xff, 0x00, 0x1d, // Bits
|
||||
0xf3, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // Fake Nonce. TODO: (Ori) Replace to a real nonce
|
||||
0xf3, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // Fake Nonce
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
in *BlockHeader // Data to encode
|
||||
out *BlockHeader // Expected decoded data
|
||||
buf []byte // Encoded data
|
||||
pver uint32 // Protocol version for domainmessage encoding
|
||||
pver uint32 // Protocol version for appmessage encoding
|
||||
}{
|
||||
// Latest protocol version.
|
||||
{
|
||||
@@ -112,7 +112,7 @@ func TestBlockHeaderEncoding(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
// Encode to domainmessage format.
|
||||
// Encode to appmessage format.
|
||||
var buf bytes.Buffer
|
||||
err := writeBlockHeader(&buf, test.pver, test.in)
|
||||
if err != nil {
|
||||
@@ -137,7 +137,7 @@ func TestBlockHeaderEncoding(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Decode the block header from domainmessage format.
|
||||
// Decode the block header from appmessage format.
|
||||
var bh BlockHeader
|
||||
rbuf := bytes.NewReader(test.buf)
|
||||
err = readBlockHeader(rbuf, test.pver, &bh)
|
||||
@@ -182,7 +182,7 @@ func TestBlockHeaderSerialize(t *testing.T) {
|
||||
Nonce: nonce,
|
||||
}
|
||||
|
||||
// baseBlockHdrEncoded is the domainmessage encoded bytes of baseBlockHdr.
|
||||
// baseBlockHdrEncoded is the appmessage encoded bytes of baseBlockHdr.
|
||||
baseBlockHdrEncoded := []byte{
|
||||
0x01, 0x00, 0x00, 0x00, // Version 1
|
||||
0x02, // NumParentBlocks
|
||||
@@ -208,7 +208,7 @@ func TestBlockHeaderSerialize(t *testing.T) {
|
||||
0x65, 0x9C, 0x79, 0x3C, 0xE3, 0x70, 0xD9, 0x5F,
|
||||
0x99, 0x0f, 0xed, 0x15, 0x73, 0x01, 0x00, 0x00, // Timestamp
|
||||
0xff, 0xff, 0x00, 0x1d, // Bits
|
||||
0xf3, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // Fake Nonce. TODO: (Ori) Replace to a real nonce
|
||||
0xf3, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, // Fake Nonce
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -24,6 +24,7 @@ const MaxAddressesPerMsg = 1000
|
||||
// Use the AddAddress function to build up the list of known addresses when
|
||||
// sending an Addresses message to another peer.
|
||||
type MsgAddresses struct {
|
||||
baseMessage
|
||||
IncludeAllSubnetworks bool
|
||||
SubnetworkID *subnetworkid.SubnetworkID
|
||||
AddrList []*NetAddress
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"net"
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -21,15 +21,18 @@ import (
|
||||
// backing array multiple times.
|
||||
const defaultTransactionAlloc = 2048
|
||||
|
||||
// MaxMassPerBlock is the maximum total transaction mass a block may have.
|
||||
const MaxMassPerBlock = 10000000
|
||||
// MaxMassAcceptedByBlock is the maximum total transaction mass a block may accept.
|
||||
const MaxMassAcceptedByBlock = 10000000
|
||||
|
||||
// MaxMassPerTx is the maximum total mass a transaction may have.
|
||||
const MaxMassPerTx = MaxMassPerBlock / 2
|
||||
const MaxMassPerTx = MaxMassAcceptedByBlock / 2
|
||||
|
||||
// MaxTxPerBlock is the maximum number of transactions that could
|
||||
// possibly fit into a block.
|
||||
const MaxTxPerBlock = (MaxMassPerBlock / minTxPayload) + 1
|
||||
const MaxTxPerBlock = (MaxMassAcceptedByBlock / minTxPayload) + 1
|
||||
|
||||
// MaxBlockParents is the maximum allowed number of parents for block.
|
||||
const MaxBlockParents = 10
|
||||
|
||||
// TxLoc holds locator data for the offset and length of where a transaction is
|
||||
// located within a MsgBlock data buffer.
|
||||
@@ -42,6 +45,7 @@ type TxLoc struct {
|
||||
// block message. It is used to deliver block and transaction information in
|
||||
// response to a getdata message (MsgGetData) for a given block hash.
|
||||
type MsgBlock struct {
|
||||
baseMessage
|
||||
Header BlockHeader
|
||||
Transactions []*MsgTx
|
||||
}
|
||||
@@ -59,7 +63,7 @@ func (msg *MsgBlock) ClearTransactions() {
|
||||
// KaspaDecode decodes r using the kaspa protocol encoding into the receiver.
|
||||
// This is part of the Message interface implementation.
|
||||
// See Deserialize for decoding blocks stored to disk, such as in a database, as
|
||||
// opposed to decoding blocks from the domainmessage.
|
||||
// opposed to decoding blocks from the appmessage.
|
||||
func (msg *MsgBlock) KaspaDecode(r io.Reader, pver uint32) error {
|
||||
err := readBlockHeader(r, pver, &msg.Header)
|
||||
if err != nil {
|
||||
@@ -96,14 +100,14 @@ func (msg *MsgBlock) KaspaDecode(r io.Reader, pver uint32) error {
|
||||
// Deserialize decodes a block from r into the receiver using a format that is
|
||||
// suitable for long-term storage such as a database while respecting the
|
||||
// Version field in the block. This function differs from KaspaDecode in that
|
||||
// KaspaDecode decodes from the kaspa domainmessage protocol as it was sent across the
|
||||
// network. The domainmessage encoding can technically differ depending on the protocol
|
||||
// KaspaDecode decodes from the kaspa appmessage protocol as it was sent across the
|
||||
// network. The appmessage encoding can technically differ depending on the protocol
|
||||
// version and doesn't even really need to match the format of a stored block at
|
||||
// all. As of the time this comment was written, the encoded block is the same
|
||||
// in both instances, but there is a distinct difference and separating the two
|
||||
// allows the API to be flexible enough to deal with changes.
|
||||
func (msg *MsgBlock) Deserialize(r io.Reader) error {
|
||||
// At the current time, there is no difference between the domainmessage encoding
|
||||
// At the current time, there is no difference between the appmessage encoding
|
||||
// at protocol version 0 and the stable long-term storage format. As
|
||||
// a result, make use of KaspaDecode.
|
||||
return msg.KaspaDecode(r, 0)
|
||||
@@ -116,9 +120,9 @@ func (msg *MsgBlock) Deserialize(r io.Reader) error {
|
||||
func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, error) {
|
||||
fullLen := r.Len()
|
||||
|
||||
// At the current time, there is no difference between the domainmessage encoding
|
||||
// At the current time, there is no difference between the appmessage encoding
|
||||
// at protocol version 0 and the stable long-term storage format. As
|
||||
// a result, make use of existing domainmessage protocol functions.
|
||||
// a result, make use of existing appmessage protocol functions.
|
||||
err := readBlockHeader(r, 0, &msg.Header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -159,7 +163,7 @@ func (msg *MsgBlock) DeserializeTxLoc(r *bytes.Buffer) ([]TxLoc, error) {
|
||||
// KaspaEncode encodes the receiver to w using the kaspa protocol encoding.
|
||||
// This is part of the Message interface implementation.
|
||||
// See Serialize for encoding blocks to be stored to disk, such as in a
|
||||
// database, as opposed to encoding blocks for the domainmessage.
|
||||
// database, as opposed to encoding blocks for the appmessage.
|
||||
func (msg *MsgBlock) KaspaEncode(w io.Writer, pver uint32) error {
|
||||
err := writeBlockHeader(w, pver, &msg.Header)
|
||||
if err != nil {
|
||||
@@ -184,14 +188,14 @@ func (msg *MsgBlock) KaspaEncode(w io.Writer, pver uint32) error {
|
||||
// Serialize encodes the block to w using a format that suitable for long-term
|
||||
// storage such as a database while respecting the Version field in the block.
|
||||
// This function differs from KaspaEncode in that KaspaEncode encodes the block to
|
||||
// the kaspa domainmessage protocol in order to be sent across the network. The domainmessage
|
||||
// the kaspa appmessage protocol in order to be sent across the network. The appmessage
|
||||
// encoding can technically differ depending on the protocol version and doesn't
|
||||
// even really need to match the format of a stored block at all. As of the
|
||||
// time this comment was written, the encoded block is the same in both
|
||||
// instances, but there is a distinct difference and separating the two allows
|
||||
// the API to be flexible enough to deal with changes.
|
||||
func (msg *MsgBlock) Serialize(w io.Writer) error {
|
||||
// At the current time, there is no difference between the domainmessage encoding
|
||||
// At the current time, there is no difference between the appmessage encoding
|
||||
// at protocol version 0 and the stable long-term storage format. As
|
||||
// a result, make use of KaspaEncode.
|
||||
return msg.KaspaEncode(w, 0)
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -144,7 +144,7 @@ func TestConvertToPartial(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestBlockEncoding tests the MsgBlock domainmessage encode and decode for various numbers
|
||||
// TestBlockEncoding tests the MsgBlock appmessage encode and decode for various numbers
|
||||
// of transaction inputs and outputs and protocol versions.
|
||||
func TestBlockEncoding(t *testing.T) {
|
||||
tests := []struct {
|
||||
@@ -152,7 +152,7 @@ func TestBlockEncoding(t *testing.T) {
|
||||
out *MsgBlock // Expected decoded message
|
||||
buf []byte // Encoded value
|
||||
txLocs []TxLoc // Expected transaction locations
|
||||
pver uint32 // Protocol version for domainmessage encoding
|
||||
pver uint32 // Protocol version for appmessage encoding
|
||||
}{
|
||||
// Latest protocol version.
|
||||
{
|
||||
@@ -166,7 +166,7 @@ func TestBlockEncoding(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
// Encode the message to domainmessage format.
|
||||
// Encode the message to appmessage format.
|
||||
var buf bytes.Buffer
|
||||
err := test.in.KaspaEncode(&buf, test.pver)
|
||||
if err != nil {
|
||||
@@ -179,7 +179,7 @@ func TestBlockEncoding(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Decode the message from domainmessage format.
|
||||
// Decode the message from appmessage format.
|
||||
var msg MsgBlock
|
||||
rbuf := bytes.NewReader(test.buf)
|
||||
err = msg.KaspaDecode(rbuf, test.pver)
|
||||
@@ -195,7 +195,7 @@ func TestBlockEncoding(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestBlockEncodingErrors performs negative tests against domainmessage encode and decode
|
||||
// TestBlockEncodingErrors performs negative tests against appmessage encode and decode
|
||||
// of MsgBlock to confirm error paths work correctly.
|
||||
func TestBlockEncodingErrors(t *testing.T) {
|
||||
pver := ProtocolVersion
|
||||
@@ -203,7 +203,7 @@ func TestBlockEncodingErrors(t *testing.T) {
|
||||
tests := []struct {
|
||||
in *MsgBlock // Value to encode
|
||||
buf []byte // Encoded value
|
||||
pver uint32 // Protocol version for domainmessage encoding
|
||||
pver uint32 // Protocol version for appmessage encoding
|
||||
max int // Max size of fixed buffer to induce errors
|
||||
writeErr error // Expected write error
|
||||
readErr error // Expected read error
|
||||
@@ -236,7 +236,7 @@ func TestBlockEncodingErrors(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
// Encode to domainmessage format.
|
||||
// Encode to appmessage format.
|
||||
w := newFixedWriter(test.max)
|
||||
err := test.in.KaspaEncode(w, test.pver)
|
||||
if !errors.Is(err, test.writeErr) {
|
||||
@@ -245,7 +245,7 @@ func TestBlockEncodingErrors(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Decode from domainmessage format.
|
||||
// Decode from appmessage format.
|
||||
var msg MsgBlock
|
||||
r := newFixedReader(test.max, test.buf)
|
||||
err = msg.KaspaDecode(r, test.pver)
|
||||
@@ -324,7 +324,7 @@ func TestBlockSerialize(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestBlockSerializeErrors performs negative tests against domainmessage encode and
|
||||
// TestBlockSerializeErrors performs negative tests against appmessage encode and
|
||||
// decode of MsgBlock to confirm error paths work correctly.
|
||||
func TestBlockSerializeErrors(t *testing.T) {
|
||||
tests := []struct {
|
||||
@@ -401,7 +401,7 @@ func TestBlockOverflowErrors(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
buf []byte // Encoded value
|
||||
pver uint32 // Protocol version for domainmessage encoding
|
||||
pver uint32 // Protocol version for appmessage encoding
|
||||
err error // Expected error
|
||||
}{
|
||||
// Block that claims to have ~uint64(0) transactions.
|
||||
@@ -431,7 +431,7 @@ func TestBlockOverflowErrors(t *testing.T) {
|
||||
0x65, 0x9C, 0x79, 0x3C, 0xE3, 0x70, 0xD9, 0x5F,
|
||||
0x61, 0xbc, 0x66, 0x49, 0x00, 0x00, 0x00, 0x00, // Timestamp
|
||||
0xff, 0xff, 0x00, 0x1d, // Bits
|
||||
0x01, 0xe3, 0x62, 0x99, 0x00, 0x00, 0x00, 0x00, // Fake Nonce. TODO: (Ori) Replace to a real nonce
|
||||
0x01, 0xe3, 0x62, 0x99, 0x00, 0x00, 0x00, 0x00, // Fake Nonce
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, // TxnCount
|
||||
}, pver, &MessageError{},
|
||||
@@ -440,7 +440,7 @@ func TestBlockOverflowErrors(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
// Decode from domainmessage format.
|
||||
// Decode from appmessage format.
|
||||
var msg MsgBlock
|
||||
r := bytes.NewReader(test.buf)
|
||||
err := msg.KaspaDecode(r, test.pver)
|
||||
@@ -450,7 +450,7 @@ func TestBlockOverflowErrors(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Deserialize from domainmessage format.
|
||||
// Deserialize from appmessage format.
|
||||
r = bytes.NewReader(test.buf)
|
||||
err = msg.Deserialize(r)
|
||||
if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
|
||||
@@ -459,7 +459,7 @@ func TestBlockOverflowErrors(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Deserialize with transaction location info from domainmessage format.
|
||||
// Deserialize with transaction location info from appmessage format.
|
||||
br := bytes.NewBuffer(test.buf)
|
||||
_, err = msg.DeserializeTxLoc(br)
|
||||
if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
|
||||
@@ -572,7 +572,7 @@ var blockOneBytes = []byte{
|
||||
0x65, 0x9C, 0x79, 0x3C, 0xE3, 0x70, 0xD9, 0x5F,
|
||||
0x99, 0x0f, 0xed, 0x15, 0x73, 0x01, 0x00, 0x00, // Timestamp
|
||||
0xff, 0xff, 0x00, 0x1d, // Bits
|
||||
0x01, 0xe3, 0x62, 0x99, 0x00, 0x00, 0x00, 0x00, // Fake Nonce. TODO: (Ori) Replace to a real nonce
|
||||
0x01, 0xe3, 0x62, 0x99, 0x00, 0x00, 0x00, 0x00, // Fake Nonce
|
||||
0x01, // TxnCount
|
||||
0x01, 0x00, 0x00, 0x00, // Version
|
||||
0x01, // Varint for number of transaction inputs
|
||||
@@ -1,4 +1,4 @@
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
@@ -12,6 +12,7 @@ const MaxBlockLocatorsPerMsg = 500
|
||||
// locator message. It is used to find the blockLocator of a peer that is
|
||||
// syncing with you.
|
||||
type MsgBlockLocator struct {
|
||||
baseMessage
|
||||
BlockLocatorHashes []*daghash.Hash
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -1,11 +1,13 @@
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
// MsgDoneIBDBlocks implements the Message interface and represents a kaspa
|
||||
// DoneIBDBlocks message. It is used to notify the IBD syncing peer that the
|
||||
// syncer sent all the requested blocks.
|
||||
//
|
||||
// This message has no payload.
|
||||
type MsgDoneIBDBlocks struct{}
|
||||
type MsgDoneIBDBlocks struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
@@ -2,12 +2,13 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
// MsgIBDBlock implements the Message interface and represents a kaspa
|
||||
// ibdblock message. It is used to deliver block and transaction information in
|
||||
// response to a RequestIBDBlocks message (MsgRequestIBDBlocks).
|
||||
type MsgIBDBlock struct {
|
||||
baseMessage
|
||||
*MsgBlock
|
||||
}
|
||||
|
||||
@@ -26,5 +27,5 @@ func (msg *MsgIBDBlock) MaxPayloadLength(pver uint32) uint32 {
|
||||
// NewMsgIBDBlock returns a new kaspa ibdblock message that conforms to the
|
||||
// Message interface. See MsgIBDBlock for details.
|
||||
func NewMsgIBDBlock(msgBlock *MsgBlock) *MsgIBDBlock {
|
||||
return &MsgIBDBlock{msgBlock}
|
||||
return &MsgIBDBlock{MsgBlock: msgBlock}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -65,7 +65,7 @@ func TestIBDBlock(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestIBDBlockEncoding tests the MsgIBDBlock domainmessage encode and decode for various numbers
|
||||
// TestIBDBlockEncoding tests the MsgIBDBlock appmessage encode and decode for various numbers
|
||||
// of transaction inputs and outputs and protocol versions.
|
||||
func TestIBDBlockEncoding(t *testing.T) {
|
||||
tests := []struct {
|
||||
@@ -73,12 +73,12 @@ func TestIBDBlockEncoding(t *testing.T) {
|
||||
out *MsgIBDBlock // Expected decoded message
|
||||
buf []byte // Encoded value
|
||||
txLocs []TxLoc // Expected transaction locations
|
||||
pver uint32 // Protocol version for domainmessage encoding
|
||||
pver uint32 // Protocol version for appmessage encoding
|
||||
}{
|
||||
// Latest protocol version.
|
||||
{
|
||||
&MsgIBDBlock{&blockOne},
|
||||
&MsgIBDBlock{&blockOne},
|
||||
&MsgIBDBlock{MsgBlock: &blockOne},
|
||||
&MsgIBDBlock{MsgBlock: &blockOne},
|
||||
blockOneBytes,
|
||||
blockOneTxLocs,
|
||||
ProtocolVersion,
|
||||
@@ -87,7 +87,7 @@ func TestIBDBlockEncoding(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
// Encode the message to domainmessage format.
|
||||
// Encode the message to appmessage format.
|
||||
var buf bytes.Buffer
|
||||
err := test.in.KaspaEncode(&buf, test.pver)
|
||||
if err != nil {
|
||||
@@ -100,7 +100,7 @@ func TestIBDBlockEncoding(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Decode the message from domainmessage format.
|
||||
// Decode the message from appmessage format.
|
||||
var msg MsgIBDBlock
|
||||
msg.MsgBlock = new(MsgBlock)
|
||||
rbuf := bytes.NewReader(test.buf)
|
||||
@@ -1,4 +1,4 @@
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
// block inventory message. It is used to notify the network about new block
|
||||
// by sending their hash, and let the receiving node decide if it needs it.
|
||||
type MsgInvRelayBlock struct {
|
||||
baseMessage
|
||||
Hash *daghash.Hash
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
@@ -12,6 +12,7 @@ const MaxInvPerTxInvMsg = MaxInvPerMsg
|
||||
// TxInv message. It is used to notify the network about new transactions
|
||||
// by sending their ID, and let the receiving node decide if it needs it.
|
||||
type MsgInvTransaction struct {
|
||||
baseMessage
|
||||
TxIDs []*daghash.TxID
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
// MsgPing implements the Message interface and represents a kaspa ping
|
||||
// message.
|
||||
@@ -16,6 +16,7 @@ package domainmessage
|
||||
// The payload for this message just consists of a nonce used for identifying
|
||||
// it later.
|
||||
type MsgPing struct {
|
||||
baseMessage
|
||||
// Unique value associated with message that is used to identify
|
||||
// specific ping message.
|
||||
Nonce uint64
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
// MsgPong implements the Message interface and represents a kaspa pong
|
||||
// message which is used primarily to confirm that a connection is still valid
|
||||
@@ -10,6 +10,7 @@ package domainmessage
|
||||
//
|
||||
// This message was not added until protocol versions AFTER BIP0031Version.
|
||||
type MsgPong struct {
|
||||
baseMessage
|
||||
// Unique value associated with message that is used to identify
|
||||
// specific ping message.
|
||||
Nonce uint64
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"testing"
|
||||
22
app/appmessage/p2p_msgreject.go
Normal file
22
app/appmessage/p2p_msgreject.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package appmessage
|
||||
|
||||
// MsgReject implements the Message interface and represents a kaspa
|
||||
// Reject message. It is used to notify peers why they are banned.
|
||||
type MsgReject struct {
|
||||
baseMessage
|
||||
Reason string
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgReject) Command() MessageCommand {
|
||||
return CmdReject
|
||||
}
|
||||
|
||||
// NewMsgReject returns a new kaspa Reject message that conforms to the
|
||||
// Message interface.
|
||||
func NewMsgReject(reason string) *MsgReject {
|
||||
return &MsgReject{
|
||||
Reason: reason,
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/util/subnetworkid"
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
//
|
||||
// This message has no payload.
|
||||
type MsgRequestAddresses struct {
|
||||
baseMessage
|
||||
IncludeAllSubnetworks bool
|
||||
SubnetworkID *subnetworkid.SubnetworkID
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -1,4 +1,4 @@
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
// and low hash.
|
||||
// The locator is returned via a locator message (MsgBlockLocator).
|
||||
type MsgRequestBlockLocator struct {
|
||||
baseMessage
|
||||
HighHash *daghash.Hash
|
||||
LowHash *daghash.Hash
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
// RequestIBDBlocks message. It is used to request a list of blocks starting after the
|
||||
// low hash and until the high hash.
|
||||
type MsgRequestIBDBlocks struct {
|
||||
baseMessage
|
||||
LowHash *daghash.Hash
|
||||
HighHash *daghash.Hash
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -18,7 +18,7 @@ func TestRequstIBDBlocks(t *testing.T) {
|
||||
t.Errorf("NewHashFromStr: %v", err)
|
||||
}
|
||||
|
||||
hashStr = "3ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
|
||||
hashStr = "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
|
||||
highHash, err := daghash.NewHashFromStr(hashStr)
|
||||
if err != nil {
|
||||
t.Errorf("NewHashFromStr: %v", err)
|
||||
@@ -1,11 +1,13 @@
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
// MsgRequestNextIBDBlocks implements the Message interface and represents a kaspa
|
||||
// RequestNextIBDBlocks message. It is used to notify the IBD syncer peer to send
|
||||
// more blocks.
|
||||
//
|
||||
// This message has no payload.
|
||||
type MsgRequestNextIBDBlocks struct{}
|
||||
type MsgRequestNextIBDBlocks struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
@@ -1,4 +1,4 @@
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
@@ -12,6 +12,7 @@ const MsgRequestRelayBlocksHashes = MaxInvPerMsg
|
||||
// RequestRelayBlocks message. It is used to request blocks as part of the block
|
||||
// relay protocol.
|
||||
type MsgRequestRelayBlocks struct {
|
||||
baseMessage
|
||||
Hashes []*daghash.Hash
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
// MsgRequestSelectedTip implements the Message interface and represents a kaspa
|
||||
// RequestSelectedTip message. It is used to request the selected tip of another peer.
|
||||
//
|
||||
// This message has no payload.
|
||||
type MsgRequestSelectedTip struct{}
|
||||
type MsgRequestSelectedTip struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -1,4 +1,4 @@
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
@@ -12,6 +12,7 @@ const MaxInvPerRequestTransactionsMsg = MaxInvPerMsg
|
||||
// RequestTransactions message. It is used to request transactions as part of the
|
||||
// transactions relay protocol.
|
||||
type MsgRequestTransactions struct {
|
||||
baseMessage
|
||||
IDs []*daghash.TxID
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
// selectedtip message. It is used to answer getseltip messages and tell
|
||||
// the asking peer what is the selected tip of this peer.
|
||||
type MsgSelectedTip struct {
|
||||
baseMessage
|
||||
// The selected tip hash of the generator of the message.
|
||||
SelectedTipHash *daghash.Hash
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
// MsgTransactionNotFound defines a kaspa TransactionNotFound message which is sent in response to
|
||||
// a RequestTransactions message if any of the requested data in not available on the peer.
|
||||
type MsgTransactionNotFound struct {
|
||||
baseMessage
|
||||
ID *daghash.TxID
|
||||
}
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -84,7 +83,7 @@ const (
|
||||
minTxPayload = 10
|
||||
|
||||
// freeListMaxScriptSize is the size of each buffer in the free list
|
||||
// that is used for deserializing scripts from the domainmessage before they are
|
||||
// that is used for deserializing scripts from the appmessage before they are
|
||||
// concatenated into a single contiguous buffers. This value was chosen
|
||||
// because it is slightly more than twice the size of the vast majority
|
||||
// of all "standard" scripts. Larger scripts are still deserialized
|
||||
@@ -268,6 +267,7 @@ func NewTxOut(value uint64, scriptPubKey []byte) *TxOut {
|
||||
// Use the AddTxIn and AddTxOut functions to build up the list of transaction
|
||||
// inputs and outputs.
|
||||
type MsgTx struct {
|
||||
baseMessage
|
||||
Version int32
|
||||
TxIn []*TxIn
|
||||
TxOut []*TxOut
|
||||
@@ -301,29 +301,34 @@ func (msg *MsgTx) IsCoinBase() bool {
|
||||
// TxHash generates the Hash for the transaction.
|
||||
func (msg *MsgTx) TxHash() *daghash.Hash {
|
||||
// Encode the transaction and calculate double sha256 on the result.
|
||||
// Ignore the error returns since the only way the encode could fail
|
||||
// is being out of memory or due to nil pointers, both of which would
|
||||
// cause a run-time panic.
|
||||
buf := bytes.NewBuffer(make([]byte, 0, msg.serializeSize(txEncodingExcludePayload)))
|
||||
_ = msg.serialize(buf, txEncodingExcludePayload)
|
||||
writer := daghash.NewDoubleHashWriter()
|
||||
err := msg.serialize(writer, txEncodingExcludePayload)
|
||||
if err != nil {
|
||||
// this writer never return errors (no allocations or possible failures) so errors can only come from validity checks,
|
||||
// and we assume we never construct malformed transactions.
|
||||
panic(fmt.Sprintf("TxHash() failed. this should never fail for structurally-valid transactions. err: %+v", err))
|
||||
}
|
||||
|
||||
hash := daghash.Hash(daghash.DoubleHashH(buf.Bytes()))
|
||||
hash := writer.Finalize()
|
||||
return &hash
|
||||
}
|
||||
|
||||
// TxID generates the Hash for the transaction without the signature script, gas and payload fields.
|
||||
func (msg *MsgTx) TxID() *daghash.TxID {
|
||||
// Encode the transaction, replace signature script with zeroes, cut off
|
||||
// payload and calculate double sha256 on the result. Ignore the error
|
||||
// returns since the only way the encode could fail is being out of memory or
|
||||
// due to nil pointers, both of which would cause a run-time panic.
|
||||
// payload and calculate double sha256 on the result.
|
||||
var encodingFlags txEncoding
|
||||
if !msg.IsCoinBase() {
|
||||
encodingFlags = txEncodingExcludeSignatureScript | txEncodingExcludePayload
|
||||
}
|
||||
buf := bytes.NewBuffer(make([]byte, 0, msg.serializeSize(encodingFlags)))
|
||||
_ = msg.serialize(buf, encodingFlags)
|
||||
txID := daghash.TxID(daghash.DoubleHashH(buf.Bytes()))
|
||||
writer := daghash.NewDoubleHashWriter()
|
||||
err := msg.serialize(writer, encodingFlags)
|
||||
if err != nil {
|
||||
// this writer never return errors (no allocations or possible failures) so errors can only come from validity checks,
|
||||
// and we assume we never construct malformed transactions.
|
||||
panic(fmt.Sprintf("TxID() failed. this should never fail for structurally-valid transactions. err: %+v", err))
|
||||
}
|
||||
txID := daghash.TxID(writer.Finalize())
|
||||
return &txID
|
||||
}
|
||||
|
||||
@@ -401,7 +406,7 @@ func (msg *MsgTx) Copy() *MsgTx {
|
||||
// KaspaDecode decodes r using the kaspa protocol encoding into the receiver.
|
||||
// This is part of the Message interface implementation.
|
||||
// See Deserialize for decoding transactions stored to disk, such as in a
|
||||
// database, as opposed to decoding transactions from the domainmessage.
|
||||
// database, as opposed to decoding transactions from the appmessage.
|
||||
func (msg *MsgTx) KaspaDecode(r io.Reader, pver uint32) error {
|
||||
version, err := binaryserializer.Uint32(r, littleEndian)
|
||||
if err != nil {
|
||||
@@ -591,15 +596,15 @@ func (msg *MsgTx) KaspaDecode(r io.Reader, pver uint32) error {
|
||||
// Deserialize decodes a transaction from r into the receiver using a format
|
||||
// that is suitable for long-term storage such as a database while respecting
|
||||
// the Version field in the transaction. This function differs from KaspaDecode
|
||||
// in that KaspaDecode decodes from the kaspa domainmessage protocol as it was sent
|
||||
// across the network. The domainmessage encoding can technically differ depending on
|
||||
// in that KaspaDecode decodes from the kaspa appmessage protocol as it was sent
|
||||
// across the network. The appmessage encoding can technically differ depending on
|
||||
// the protocol version and doesn't even really need to match the format of a
|
||||
// stored transaction at all. As of the time this comment was written, the
|
||||
// encoded transaction is the same in both instances, but there is a distinct
|
||||
// difference and separating the two allows the API to be flexible enough to
|
||||
// deal with changes.
|
||||
func (msg *MsgTx) Deserialize(r io.Reader) error {
|
||||
// At the current time, there is no difference between the domainmessage encoding
|
||||
// At the current time, there is no difference between the appmessage encoding
|
||||
// at protocol version 0 and the stable long-term storage format. As
|
||||
// a result, make use of KaspaDecode.
|
||||
return msg.KaspaDecode(r, 0)
|
||||
@@ -608,7 +613,7 @@ func (msg *MsgTx) Deserialize(r io.Reader) error {
|
||||
// KaspaEncode encodes the receiver to w using the kaspa protocol encoding.
|
||||
// This is part of the Message interface implementation.
|
||||
// See Serialize for encoding transactions to be stored to disk, such as in a
|
||||
// database, as opposed to encoding transactions for the domainmessage.
|
||||
// database, as opposed to encoding transactions for the appmessage.
|
||||
func (msg *MsgTx) KaspaEncode(w io.Writer, pver uint32) error {
|
||||
return msg.encode(w, pver, txEncodingFull)
|
||||
}
|
||||
@@ -697,22 +702,22 @@ func (msg *MsgTx) encode(w io.Writer, pver uint32, encodingFlags txEncoding) err
|
||||
// Serialize encodes the transaction to w using a format that suitable for
|
||||
// long-term storage such as a database while respecting the Version field in
|
||||
// the transaction. This function differs from KaspaEncode in that KaspaEncode
|
||||
// encodes the transaction to the kaspa domainmessage protocol in order to be sent
|
||||
// across the network. The domainmessage encoding can technically differ depending on
|
||||
// encodes the transaction to the kaspa appmessage protocol in order to be sent
|
||||
// across the network. The appmessage encoding can technically differ depending on
|
||||
// the protocol version and doesn't even really need to match the format of a
|
||||
// stored transaction at all. As of the time this comment was written, the
|
||||
// encoded transaction is the same in both instances, but there is a distinct
|
||||
// difference and separating the two allows the API to be flexible enough to
|
||||
// deal with changes.
|
||||
func (msg *MsgTx) Serialize(w io.Writer) error {
|
||||
// At the current time, there is no difference between the domainmessage encoding
|
||||
// At the current time, there is no difference between the appmessage encoding
|
||||
// at protocol version 0 and the stable long-term storage format. As
|
||||
// a result, make use of KaspaEncode.
|
||||
return msg.KaspaEncode(w, 0)
|
||||
}
|
||||
|
||||
func (msg *MsgTx) serialize(w io.Writer, encodingFlags txEncoding) error {
|
||||
// At the current time, there is no difference between the domainmessage encoding
|
||||
// At the current time, there is no difference between the appmessage encoding
|
||||
// at protocol version 0 and the stable long-term storage format. As
|
||||
// a result, make use of `encode`.
|
||||
return msg.encode(w, 0, encodingFlags)
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
func TestTx(t *testing.T) {
|
||||
pver := ProtocolVersion
|
||||
|
||||
txIDStr := "3ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
|
||||
txIDStr := "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
|
||||
txID, err := daghash.NewTxIDFromStr(txIDStr)
|
||||
if err != nil {
|
||||
t.Errorf("NewTxIDFromStr: %v", err)
|
||||
@@ -253,7 +253,7 @@ func TestTxHashAndID(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestTxEncoding tests the MsgTx domainmessage encode and decode for various numbers
|
||||
// TestTxEncoding tests the MsgTx appmessage encode and decode for various numbers
|
||||
// of transaction inputs and outputs and protocol versions.
|
||||
func TestTxEncoding(t *testing.T) {
|
||||
// Empty tx message.
|
||||
@@ -272,7 +272,7 @@ func TestTxEncoding(t *testing.T) {
|
||||
in *MsgTx // Message to encode
|
||||
out *MsgTx // Expected decoded message
|
||||
buf []byte // Encoded value
|
||||
pver uint32 // Protocol version for domainmessage encoding
|
||||
pver uint32 // Protocol version for appmessage encoding
|
||||
}{
|
||||
// Latest protocol version with no transactions.
|
||||
{
|
||||
@@ -293,7 +293,7 @@ func TestTxEncoding(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
// Encode the message to domainmessage format.
|
||||
// Encode the message to appmessage format.
|
||||
var buf bytes.Buffer
|
||||
err := test.in.KaspaEncode(&buf, test.pver)
|
||||
if err != nil {
|
||||
@@ -306,7 +306,7 @@ func TestTxEncoding(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Decode the message from domainmessage format.
|
||||
// Decode the message from appmessage format.
|
||||
var msg MsgTx
|
||||
rbuf := bytes.NewReader(test.buf)
|
||||
err = msg.KaspaDecode(rbuf, test.pver)
|
||||
@@ -322,7 +322,7 @@ func TestTxEncoding(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestTxEncodingErrors performs negative tests against domainmessage encode and decode
|
||||
// TestTxEncodingErrors performs negative tests against appmessage encode and decode
|
||||
// of MsgTx to confirm error paths work correctly.
|
||||
func TestTxEncodingErrors(t *testing.T) {
|
||||
pver := ProtocolVersion
|
||||
@@ -330,7 +330,7 @@ func TestTxEncodingErrors(t *testing.T) {
|
||||
tests := []struct {
|
||||
in *MsgTx // Value to encode
|
||||
buf []byte // Encoded value
|
||||
pver uint32 // Protocol version for domainmessage encoding
|
||||
pver uint32 // Protocol version for appmessage encoding
|
||||
max int // Max size of fixed buffer to induce errors
|
||||
writeErr error // Expected write error
|
||||
readErr error // Expected read error
|
||||
@@ -363,7 +363,7 @@ func TestTxEncodingErrors(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
// Encode to domainmessage format.
|
||||
// Encode to appmessage format.
|
||||
w := newFixedWriter(test.max)
|
||||
err := test.in.KaspaEncode(w, test.pver)
|
||||
if !errors.Is(err, test.writeErr) {
|
||||
@@ -372,7 +372,7 @@ func TestTxEncodingErrors(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Decode from domainmessage format.
|
||||
// Decode from appmessage format.
|
||||
var msg MsgTx
|
||||
r := newFixedReader(test.max, test.buf)
|
||||
err = msg.KaspaDecode(r, test.pver)
|
||||
@@ -528,7 +528,7 @@ func TestTxSerialize(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestTxSerializeErrors performs negative tests against domainmessage encode and decode
|
||||
// TestTxSerializeErrors performs negative tests against appmessage encode and decode
|
||||
// of MsgTx to confirm error paths work correctly.
|
||||
func TestTxSerializeErrors(t *testing.T) {
|
||||
tests := []struct {
|
||||
@@ -629,7 +629,7 @@ func TestTxOverflowErrors(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
buf []byte // Encoded value
|
||||
pver uint32 // Protocol version for domainmessage encoding
|
||||
pver uint32 // Protocol version for appmessage encoding
|
||||
version uint32 // Transaction version
|
||||
err error // Expected error
|
||||
}{
|
||||
@@ -691,7 +691,7 @@ func TestTxOverflowErrors(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
// Decode from domainmessage format.
|
||||
// Decode from appmessage format.
|
||||
var msg MsgTx
|
||||
r := bytes.NewReader(test.buf)
|
||||
err := msg.KaspaDecode(r, test.pver)
|
||||
@@ -701,7 +701,7 @@ func TestTxOverflowErrors(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Decode from domainmessage format.
|
||||
// Decode from appmessage format.
|
||||
r = bytes.NewReader(test.buf)
|
||||
err = msg.Deserialize(r)
|
||||
if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
|
||||
@@ -891,7 +891,7 @@ var multiTxOuts = []*TxOut{
|
||||
}
|
||||
var multiTx = NewNativeMsgTx(1, multiTxIns, multiTxOuts)
|
||||
|
||||
// multiTxEncoded is the domainmessage encoded bytes for multiTx using protocol version
|
||||
// multiTxEncoded is the appmessage encoded bytes for multiTx using protocol version
|
||||
// 60002 and is used in the various tests.
|
||||
var multiTxEncoded = []byte{
|
||||
0x01, 0x00, 0x00, 0x00, // Version
|
||||
@@ -2,14 +2,16 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
// MsgVerAck defines a kaspa verack message which is used for a peer to
|
||||
// acknowledge a version message (MsgVersion) after it has used the information
|
||||
// to negotiate parameters. It implements the Message interface.
|
||||
//
|
||||
// This message has no payload.
|
||||
type MsgVerAck struct{}
|
||||
type MsgVerAck struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -2,15 +2,15 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/kaspanet/kaspad/version"
|
||||
"strings"
|
||||
|
||||
"github.com/kaspanet/kaspad/netadapter/id"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/id"
|
||||
"github.com/kaspanet/kaspad/util/mstime"
|
||||
"github.com/kaspanet/kaspad/version"
|
||||
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
"github.com/kaspanet/kaspad/util/subnetworkid"
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
// version message (MsgVersion).
|
||||
const MaxUserAgentLen = 256
|
||||
|
||||
// DefaultUserAgent for domainmessage in the stack
|
||||
// DefaultUserAgent for appmessage in the stack
|
||||
var DefaultUserAgent = fmt.Sprintf("/kaspad:%s/", version.Version())
|
||||
|
||||
// MsgVersion implements the Message interface and represents a kaspa version
|
||||
@@ -31,13 +31,17 @@ var DefaultUserAgent = fmt.Sprintf("/kaspad:%s/", version.Version())
|
||||
// message (MsgVerAck). This exchange must take place before any further
|
||||
// communication is allowed to proceed.
|
||||
type MsgVersion struct {
|
||||
baseMessage
|
||||
// Version of the protocol the node is using.
|
||||
ProtocolVersion uint32
|
||||
|
||||
// The peer's network (mainnet, testnet, etc.)
|
||||
Network string
|
||||
|
||||
// Bitfield which identifies the enabled services.
|
||||
Services ServiceFlag
|
||||
|
||||
// Time the message was generated. This is encoded as an int64 on the domainmessage.
|
||||
// Time the message was generated. This is encoded as an int64 on the appmessage.
|
||||
Timestamp mstime.Time
|
||||
|
||||
// Address of the local peer.
|
||||
@@ -47,7 +51,7 @@ type MsgVersion struct {
|
||||
ID *id.ID
|
||||
|
||||
// The user agent that generated messsage. This is a encoded as a varString
|
||||
// on the domainmessage. This has a max length of MaxUserAgentLen.
|
||||
// on the appmessage. This has a max length of MaxUserAgentLen.
|
||||
UserAgent string
|
||||
|
||||
// The selected tip hash of the generator of the version message.
|
||||
@@ -81,13 +85,14 @@ func (msg *MsgVersion) Command() MessageCommand {
|
||||
// NewMsgVersion returns a new kaspa version message that conforms to the
|
||||
// Message interface using the passed parameters and defaults for the remaining
|
||||
// fields.
|
||||
func NewMsgVersion(addr *NetAddress, id *id.ID,
|
||||
func NewMsgVersion(addr *NetAddress, id *id.ID, network string,
|
||||
selectedTipHash *daghash.Hash, subnetworkID *subnetworkid.SubnetworkID) *MsgVersion {
|
||||
|
||||
// Limit the timestamp to one millisecond precision since the protocol
|
||||
// doesn't support better.
|
||||
return &MsgVersion{
|
||||
ProtocolVersion: ProtocolVersion,
|
||||
Network: network,
|
||||
Services: 0,
|
||||
Timestamp: mstime.Now(),
|
||||
Address: addr,
|
||||
@@ -2,11 +2,11 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
id "github.com/kaspanet/kaspad/netadapter/id"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/id"
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
"net"
|
||||
"reflect"
|
||||
@@ -27,7 +27,7 @@ func TestVersion(t *testing.T) {
|
||||
}
|
||||
|
||||
// Ensure we get the correct data back out.
|
||||
msg := NewMsgVersion(me, generatedID, selectedTipHash, nil)
|
||||
msg := NewMsgVersion(me, generatedID, "mainnet", selectedTipHash, nil)
|
||||
if msg.ProtocolVersion != pver {
|
||||
t.Errorf("NewMsgVersion: wrong protocol version - got %v, want %v",
|
||||
msg.ProtocolVersion, pver)
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/util/mstime"
|
||||
@@ -21,7 +21,7 @@ type NetAddress struct {
|
||||
// IP address of the peer.
|
||||
IP net.IP
|
||||
|
||||
// Port the peer is using. This is encoded in big endian on the domainmessage
|
||||
// Port the peer is using. This is encoded in big endian on the appmessage
|
||||
// which differs from most everything else.
|
||||
Port uint16
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"net"
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -10,10 +10,13 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// XXX pedro: we will probably need to bump this.
|
||||
const (
|
||||
// ProtocolVersion is the latest protocol version this package supports.
|
||||
ProtocolVersion uint32 = 1
|
||||
|
||||
// DefaultServices describes the default services that are supported by
|
||||
// the server.
|
||||
DefaultServices = SFNodeNetwork | SFNodeBloom | SFNodeCF
|
||||
)
|
||||
|
||||
// ServiceFlag identifies services supported by a kaspa peer.
|
||||
@@ -103,9 +106,6 @@ const (
|
||||
// Testnet represents the test network.
|
||||
Testnet KaspaNet = 0xddb8af8f
|
||||
|
||||
// Regtest represents the regression test network.
|
||||
Regtest KaspaNet = 0xf396cdd6
|
||||
|
||||
// Simnet represents the simulation test network.
|
||||
Simnet KaspaNet = 0x374dcf1c
|
||||
|
||||
@@ -118,7 +118,6 @@ const (
|
||||
var bnStrings = map[KaspaNet]string{
|
||||
Mainnet: "Mainnet",
|
||||
Testnet: "Testnet",
|
||||
Regtest: "Regtest",
|
||||
Simnet: "Simnet",
|
||||
Devnet: "Devnet",
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package domainmessage
|
||||
package appmessage
|
||||
|
||||
import "testing"
|
||||
|
||||
@@ -40,7 +40,6 @@ func TestKaspaNetStringer(t *testing.T) {
|
||||
want string
|
||||
}{
|
||||
{Mainnet, "Mainnet"},
|
||||
{Regtest, "Regtest"},
|
||||
{Testnet, "Testnet"},
|
||||
{Simnet, "Simnet"},
|
||||
{0xffffffff, "Unknown KaspaNet (4294967295)"},
|
||||
39
app/appmessage/rpc_add_peer.go
Normal file
39
app/appmessage/rpc_add_peer.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package appmessage
|
||||
|
||||
// AddPeerRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type AddPeerRequestMessage struct {
|
||||
baseMessage
|
||||
Address string
|
||||
IsPermanent bool
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *AddPeerRequestMessage) Command() MessageCommand {
|
||||
return CmdAddPeerRequestMessage
|
||||
}
|
||||
|
||||
// NewAddPeerRequestMessage returns a instance of the message
|
||||
func NewAddPeerRequestMessage(address string, isPermanent bool) *AddPeerRequestMessage {
|
||||
return &AddPeerRequestMessage{
|
||||
Address: address,
|
||||
IsPermanent: isPermanent,
|
||||
}
|
||||
}
|
||||
|
||||
// AddPeerResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type AddPeerResponseMessage struct {
|
||||
baseMessage
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *AddPeerResponseMessage) Command() MessageCommand {
|
||||
return CmdAddPeerResponseMessage
|
||||
}
|
||||
|
||||
// NewAddPeerResponseMessage returns a instance of the message
|
||||
func NewAddPeerResponseMessage() *AddPeerResponseMessage {
|
||||
return &AddPeerResponseMessage{}
|
||||
}
|
||||
123
app/appmessage/rpc_get_block.go
Normal file
123
app/appmessage/rpc_get_block.go
Normal file
@@ -0,0 +1,123 @@
|
||||
package appmessage
|
||||
|
||||
// GetBlockRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBlockRequestMessage struct {
|
||||
baseMessage
|
||||
Hash string
|
||||
SubnetworkID string
|
||||
IncludeBlockHex bool
|
||||
IncludeBlockVerboseData bool
|
||||
IncludeTransactionVerboseData bool
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetBlockRequestMessage) Command() MessageCommand {
|
||||
return CmdGetBlockRequestMessage
|
||||
}
|
||||
|
||||
// NewGetBlockRequestMessage returns a instance of the message
|
||||
func NewGetBlockRequestMessage(hash string, subnetworkID string, includeBlockHex bool,
|
||||
includeBlockVerboseData bool, includeTransactionVerboseData bool) *GetBlockRequestMessage {
|
||||
return &GetBlockRequestMessage{
|
||||
Hash: hash,
|
||||
SubnetworkID: subnetworkID,
|
||||
IncludeBlockHex: includeBlockHex,
|
||||
IncludeBlockVerboseData: includeBlockVerboseData,
|
||||
IncludeTransactionVerboseData: includeTransactionVerboseData,
|
||||
}
|
||||
}
|
||||
|
||||
// GetBlockResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBlockResponseMessage struct {
|
||||
baseMessage
|
||||
BlockHex string
|
||||
BlockVerboseData *BlockVerboseData
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetBlockResponseMessage) Command() MessageCommand {
|
||||
return CmdGetBlockResponseMessage
|
||||
}
|
||||
|
||||
// NewGetBlockResponseMessage returns a instance of the message
|
||||
func NewGetBlockResponseMessage() *GetBlockResponseMessage {
|
||||
return &GetBlockResponseMessage{}
|
||||
}
|
||||
|
||||
// BlockVerboseData holds verbose data about a block
|
||||
type BlockVerboseData struct {
|
||||
Hash string
|
||||
Confirmations uint64
|
||||
Size int32
|
||||
BlueScore uint64
|
||||
IsChainBlock bool
|
||||
Version int32
|
||||
VersionHex string
|
||||
HashMerkleRoot string
|
||||
AcceptedIDMerkleRoot string
|
||||
UTXOCommitment string
|
||||
TxIDs []string
|
||||
TransactionVerboseData []*TransactionVerboseData
|
||||
Time int64
|
||||
Nonce uint64
|
||||
Bits string
|
||||
Difficulty float64
|
||||
ParentHashes []string
|
||||
SelectedParentHash string
|
||||
ChildHashes []string
|
||||
AcceptedBlockHashes []string
|
||||
}
|
||||
|
||||
// TransactionVerboseData holds verbose data about a transaction
|
||||
type TransactionVerboseData struct {
|
||||
Hex string
|
||||
TxID string
|
||||
Hash string
|
||||
Size int32
|
||||
Version int32
|
||||
LockTime uint64
|
||||
SubnetworkID string
|
||||
Gas uint64
|
||||
PayloadHash string
|
||||
Payload string
|
||||
TransactionVerboseInputs []*TransactionVerboseInput
|
||||
TransactionVerboseOutputs []*TransactionVerboseOutput
|
||||
BlockHash string
|
||||
AcceptedBy string
|
||||
IsInMempool bool
|
||||
Time uint64
|
||||
BlockTime uint64
|
||||
}
|
||||
|
||||
// TransactionVerboseInput holds data about a transaction input
|
||||
type TransactionVerboseInput struct {
|
||||
TxID string
|
||||
OutputIndex uint32
|
||||
ScriptSig *ScriptSig
|
||||
Sequence uint64
|
||||
}
|
||||
|
||||
// ScriptSig holds data about a script signature
|
||||
type ScriptSig struct {
|
||||
Asm string
|
||||
Hex string
|
||||
}
|
||||
|
||||
// TransactionVerboseOutput holds data about a transaction output
|
||||
type TransactionVerboseOutput struct {
|
||||
Value uint64
|
||||
Index uint32
|
||||
ScriptPubKey *ScriptPubKeyResult
|
||||
}
|
||||
|
||||
// ScriptPubKeyResult holds data about a script public key
|
||||
type ScriptPubKeyResult struct {
|
||||
Asm string
|
||||
Hex string
|
||||
Type string
|
||||
Address string
|
||||
}
|
||||
38
app/appmessage/rpc_get_block_count.go
Normal file
38
app/appmessage/rpc_get_block_count.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package appmessage
|
||||
|
||||
// GetBlockCountRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBlockCountRequestMessage struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetBlockCountRequestMessage) Command() MessageCommand {
|
||||
return CmdGetBlockCountRequestMessage
|
||||
}
|
||||
|
||||
// NewGetBlockCountRequestMessage returns a instance of the message
|
||||
func NewGetBlockCountRequestMessage() *GetBlockCountRequestMessage {
|
||||
return &GetBlockCountRequestMessage{}
|
||||
}
|
||||
|
||||
// GetBlockCountResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBlockCountResponseMessage struct {
|
||||
baseMessage
|
||||
BlockCount uint64
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetBlockCountResponseMessage) Command() MessageCommand {
|
||||
return CmdGetBlockCountResponseMessage
|
||||
}
|
||||
|
||||
// NewGetBlockCountResponseMessage returns a instance of the message
|
||||
func NewGetBlockCountResponseMessage(blockCount uint64) *GetBlockCountResponseMessage {
|
||||
return &GetBlockCountResponseMessage{
|
||||
BlockCount: blockCount,
|
||||
}
|
||||
}
|
||||
41
app/appmessage/rpc_get_block_dag_info.go
Normal file
41
app/appmessage/rpc_get_block_dag_info.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package appmessage
|
||||
|
||||
// GetBlockDAGInfoRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBlockDAGInfoRequestMessage struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetBlockDAGInfoRequestMessage) Command() MessageCommand {
|
||||
return CmdGetBlockDAGInfoRequestMessage
|
||||
}
|
||||
|
||||
// NewGetBlockDAGInfoRequestMessage returns a instance of the message
|
||||
func NewGetBlockDAGInfoRequestMessage() *GetBlockDAGInfoRequestMessage {
|
||||
return &GetBlockDAGInfoRequestMessage{}
|
||||
}
|
||||
|
||||
// GetBlockDAGInfoResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBlockDAGInfoResponseMessage struct {
|
||||
baseMessage
|
||||
NetworkName string
|
||||
BlockCount uint64
|
||||
TipHashes []string
|
||||
VirtualParentHashes []string
|
||||
Difficulty float64
|
||||
PastMedianTime int64
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetBlockDAGInfoResponseMessage) Command() MessageCommand {
|
||||
return CmdGetBlockDAGInfoResponseMessage
|
||||
}
|
||||
|
||||
// NewGetBlockDAGInfoResponseMessage returns a instance of the message
|
||||
func NewGetBlockDAGInfoResponseMessage() *GetBlockDAGInfoResponseMessage {
|
||||
return &GetBlockDAGInfoResponseMessage{}
|
||||
}
|
||||
78
app/appmessage/rpc_get_block_template.go
Normal file
78
app/appmessage/rpc_get_block_template.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package appmessage
|
||||
|
||||
// GetBlockTemplateRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBlockTemplateRequestMessage struct {
|
||||
baseMessage
|
||||
PayAddress string
|
||||
LongPollID string
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetBlockTemplateRequestMessage) Command() MessageCommand {
|
||||
return CmdGetBlockTemplateRequestMessage
|
||||
}
|
||||
|
||||
// NewGetBlockTemplateRequestMessage returns a instance of the message
|
||||
func NewGetBlockTemplateRequestMessage(payAddress string, longPollID string) *GetBlockTemplateRequestMessage {
|
||||
return &GetBlockTemplateRequestMessage{
|
||||
PayAddress: payAddress,
|
||||
LongPollID: longPollID,
|
||||
}
|
||||
}
|
||||
|
||||
// GetBlockTemplateResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBlockTemplateResponseMessage struct {
|
||||
baseMessage
|
||||
Bits string
|
||||
CurrentTime int64
|
||||
ParentHashes []string
|
||||
MassLimit int
|
||||
Transactions []GetBlockTemplateTransactionMessage
|
||||
HashMerkleRoot string
|
||||
AcceptedIDMerkleRoot string
|
||||
UTXOCommitment string
|
||||
Version int32
|
||||
LongPollID string
|
||||
TargetDifficulty string
|
||||
MinTime int64
|
||||
MaxTime int64
|
||||
MutableFields []string
|
||||
NonceRange string
|
||||
IsSynced bool
|
||||
IsConnected bool
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetBlockTemplateResponseMessage) Command() MessageCommand {
|
||||
return CmdGetBlockTemplateResponseMessage
|
||||
}
|
||||
|
||||
// NewGetBlockTemplateResponseMessage returns a instance of the message
|
||||
func NewGetBlockTemplateResponseMessage() *GetBlockTemplateResponseMessage {
|
||||
return &GetBlockTemplateResponseMessage{}
|
||||
}
|
||||
|
||||
// GetBlockTemplateTransactionMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBlockTemplateTransactionMessage struct {
|
||||
baseMessage
|
||||
Data string
|
||||
ID string
|
||||
Depends []int64
|
||||
Mass uint64
|
||||
Fee uint64
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetBlockTemplateTransactionMessage) Command() MessageCommand {
|
||||
return CmdGetBlockTemplateTransactionMessage
|
||||
}
|
||||
|
||||
// NewGetBlockTemplateTransactionMessage returns a instance of the message
|
||||
func NewGetBlockTemplateTransactionMessage() *GetBlockTemplateTransactionMessage {
|
||||
return &GetBlockTemplateTransactionMessage{}
|
||||
}
|
||||
51
app/appmessage/rpc_get_blocks.go
Normal file
51
app/appmessage/rpc_get_blocks.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package appmessage
|
||||
|
||||
// GetBlocksRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBlocksRequestMessage struct {
|
||||
baseMessage
|
||||
LowHash string
|
||||
IncludeBlockHexes bool
|
||||
IncludeBlockVerboseData bool
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetBlocksRequestMessage) Command() MessageCommand {
|
||||
return CmdGetBlocksRequestMessage
|
||||
}
|
||||
|
||||
// NewGetBlocksRequestMessage returns a instance of the message
|
||||
func NewGetBlocksRequestMessage(lowHash string, includeBlockHexes bool, includeBlockVerboseData bool) *GetBlocksRequestMessage {
|
||||
return &GetBlocksRequestMessage{
|
||||
LowHash: lowHash,
|
||||
IncludeBlockHexes: includeBlockHexes,
|
||||
IncludeBlockVerboseData: includeBlockVerboseData,
|
||||
}
|
||||
}
|
||||
|
||||
// GetBlocksResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBlocksResponseMessage struct {
|
||||
baseMessage
|
||||
BlockHashes []string
|
||||
BlockHexes []string
|
||||
BlockVerboseData []*BlockVerboseData
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetBlocksResponseMessage) Command() MessageCommand {
|
||||
return CmdGetBlocksResponseMessage
|
||||
}
|
||||
|
||||
// NewGetBlocksResponseMessage returns a instance of the message
|
||||
func NewGetBlocksResponseMessage(blockHashes []string, blockHexes []string,
|
||||
blockVerboseData []*BlockVerboseData) *GetBlocksResponseMessage {
|
||||
|
||||
return &GetBlocksResponseMessage{
|
||||
BlockHashes: blockHashes,
|
||||
BlockHexes: blockHexes,
|
||||
BlockVerboseData: blockVerboseData,
|
||||
}
|
||||
}
|
||||
49
app/appmessage/rpc_get_chain_from_block.go
Normal file
49
app/appmessage/rpc_get_chain_from_block.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package appmessage
|
||||
|
||||
// GetChainFromBlockRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetChainFromBlockRequestMessage struct {
|
||||
baseMessage
|
||||
StartHash string
|
||||
IncludeBlockVerboseData bool
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetChainFromBlockRequestMessage) Command() MessageCommand {
|
||||
return CmdGetChainFromBlockRequestMessage
|
||||
}
|
||||
|
||||
// NewGetChainFromBlockRequestMessage returns a instance of the message
|
||||
func NewGetChainFromBlockRequestMessage(startHash string, includeBlockVerboseData bool) *GetChainFromBlockRequestMessage {
|
||||
return &GetChainFromBlockRequestMessage{
|
||||
StartHash: startHash,
|
||||
IncludeBlockVerboseData: includeBlockVerboseData,
|
||||
}
|
||||
}
|
||||
|
||||
// GetChainFromBlockResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetChainFromBlockResponseMessage struct {
|
||||
baseMessage
|
||||
RemovedChainBlockHashes []string
|
||||
AddedChainBlocks []*ChainBlock
|
||||
BlockVerboseData []*BlockVerboseData
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetChainFromBlockResponseMessage) Command() MessageCommand {
|
||||
return CmdGetChainFromBlockResponseMessage
|
||||
}
|
||||
|
||||
// NewGetChainFromBlockResponseMessage returns a instance of the message
|
||||
func NewGetChainFromBlockResponseMessage(removedChainBlockHashes []string,
|
||||
addedChainBlocks []*ChainBlock, blockVerboseData []*BlockVerboseData) *GetChainFromBlockResponseMessage {
|
||||
|
||||
return &GetChainFromBlockResponseMessage{
|
||||
RemovedChainBlockHashes: removedChainBlockHashes,
|
||||
AddedChainBlocks: addedChainBlocks,
|
||||
BlockVerboseData: blockVerboseData,
|
||||
}
|
||||
}
|
||||
51
app/appmessage/rpc_get_connected_peer_info.go
Normal file
51
app/appmessage/rpc_get_connected_peer_info.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package appmessage
|
||||
|
||||
// GetConnectedPeerInfoRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetConnectedPeerInfoRequestMessage struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetConnectedPeerInfoRequestMessage) Command() MessageCommand {
|
||||
return CmdGetConnectedPeerInfoRequestMessage
|
||||
}
|
||||
|
||||
// NewGetConnectedPeerInfoRequestMessage returns a instance of the message
|
||||
func NewGetConnectedPeerInfoRequestMessage() *GetConnectedPeerInfoRequestMessage {
|
||||
return &GetConnectedPeerInfoRequestMessage{}
|
||||
}
|
||||
|
||||
// GetConnectedPeerInfoResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetConnectedPeerInfoResponseMessage struct {
|
||||
baseMessage
|
||||
Infos []*GetConnectedPeerInfoMessage
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetConnectedPeerInfoResponseMessage) Command() MessageCommand {
|
||||
return CmdGetConnectedPeerInfoResponseMessage
|
||||
}
|
||||
|
||||
// NewGetConnectedPeerInfoResponseMessage returns a instance of the message
|
||||
func NewGetConnectedPeerInfoResponseMessage(infos []*GetConnectedPeerInfoMessage) *GetConnectedPeerInfoResponseMessage {
|
||||
return &GetConnectedPeerInfoResponseMessage{
|
||||
Infos: infos,
|
||||
}
|
||||
}
|
||||
|
||||
// GetConnectedPeerInfoMessage holds information about a connected peer
|
||||
type GetConnectedPeerInfoMessage struct {
|
||||
ID string
|
||||
Address string
|
||||
LastPingDuration int64
|
||||
SelectedTipHash string
|
||||
IsSyncNode bool
|
||||
IsOutbound bool
|
||||
TimeOffset int64
|
||||
UserAgent string
|
||||
AdvertisedProtocolVersion uint32
|
||||
TimeConnected int64
|
||||
}
|
||||
38
app/appmessage/rpc_get_current_network.go
Normal file
38
app/appmessage/rpc_get_current_network.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package appmessage
|
||||
|
||||
// GetCurrentNetworkRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetCurrentNetworkRequestMessage struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetCurrentNetworkRequestMessage) Command() MessageCommand {
|
||||
return CmdGetCurrentNetworkRequestMessage
|
||||
}
|
||||
|
||||
// NewGetCurrentNetworkRequestMessage returns a instance of the message
|
||||
func NewGetCurrentNetworkRequestMessage() *GetCurrentNetworkRequestMessage {
|
||||
return &GetCurrentNetworkRequestMessage{}
|
||||
}
|
||||
|
||||
// GetCurrentNetworkResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetCurrentNetworkResponseMessage struct {
|
||||
baseMessage
|
||||
CurrentNetwork string
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetCurrentNetworkResponseMessage) Command() MessageCommand {
|
||||
return CmdGetCurrentNetworkResponseMessage
|
||||
}
|
||||
|
||||
// NewGetCurrentNetworkResponseMessage returns a instance of the message
|
||||
func NewGetCurrentNetworkResponseMessage(currentNetwork string) *GetCurrentNetworkResponseMessage {
|
||||
return &GetCurrentNetworkResponseMessage{
|
||||
CurrentNetwork: currentNetwork,
|
||||
}
|
||||
}
|
||||
45
app/appmessage/rpc_get_headers.go
Normal file
45
app/appmessage/rpc_get_headers.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package appmessage
|
||||
|
||||
// GetHeadersRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetHeadersRequestMessage struct {
|
||||
baseMessage
|
||||
StartHash string
|
||||
Limit uint64
|
||||
IsAscending bool
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetHeadersRequestMessage) Command() MessageCommand {
|
||||
return CmdGetHeadersRequestMessage
|
||||
}
|
||||
|
||||
// NewGetHeadersRequestMessage returns a instance of the message
|
||||
func NewGetHeadersRequestMessage(startHash string, limit uint64, isAscending bool) *GetHeadersRequestMessage {
|
||||
return &GetHeadersRequestMessage{
|
||||
StartHash: startHash,
|
||||
Limit: limit,
|
||||
IsAscending: isAscending,
|
||||
}
|
||||
}
|
||||
|
||||
// GetHeadersResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetHeadersResponseMessage struct {
|
||||
baseMessage
|
||||
Headers []string
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetHeadersResponseMessage) Command() MessageCommand {
|
||||
return CmdGetHeadersResponseMessage
|
||||
}
|
||||
|
||||
// NewGetHeadersResponseMessage returns a instance of the message
|
||||
func NewGetHeadersResponseMessage(headers []string) *GetHeadersResponseMessage {
|
||||
return &GetHeadersResponseMessage{
|
||||
Headers: headers,
|
||||
}
|
||||
}
|
||||
38
app/appmessage/rpc_get_mempool_entries.go
Normal file
38
app/appmessage/rpc_get_mempool_entries.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package appmessage
|
||||
|
||||
// GetMempoolEntriesRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetMempoolEntriesRequestMessage struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetMempoolEntriesRequestMessage) Command() MessageCommand {
|
||||
return CmdGetMempoolEntriesRequestMessage
|
||||
}
|
||||
|
||||
// NewGetMempoolEntriesRequestMessage returns a instance of the message
|
||||
func NewGetMempoolEntriesRequestMessage() *GetMempoolEntriesRequestMessage {
|
||||
return &GetMempoolEntriesRequestMessage{}
|
||||
}
|
||||
|
||||
// GetMempoolEntriesResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetMempoolEntriesResponseMessage struct {
|
||||
baseMessage
|
||||
Entries []*MempoolEntry
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetMempoolEntriesResponseMessage) Command() MessageCommand {
|
||||
return CmdGetMempoolEntriesResponseMessage
|
||||
}
|
||||
|
||||
// NewGetMempoolEntriesResponseMessage returns a instance of the message
|
||||
func NewGetMempoolEntriesResponseMessage(entries []*MempoolEntry) *GetMempoolEntriesResponseMessage {
|
||||
return &GetMempoolEntriesResponseMessage{
|
||||
Entries: entries,
|
||||
}
|
||||
}
|
||||
48
app/appmessage/rpc_get_mempool_entry.go
Normal file
48
app/appmessage/rpc_get_mempool_entry.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package appmessage
|
||||
|
||||
// GetMempoolEntryRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetMempoolEntryRequestMessage struct {
|
||||
baseMessage
|
||||
TxID string
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetMempoolEntryRequestMessage) Command() MessageCommand {
|
||||
return CmdGetMempoolEntryRequestMessage
|
||||
}
|
||||
|
||||
// NewGetMempoolEntryRequestMessage returns a instance of the message
|
||||
func NewGetMempoolEntryRequestMessage(txID string) *GetMempoolEntryRequestMessage {
|
||||
return &GetMempoolEntryRequestMessage{TxID: txID}
|
||||
}
|
||||
|
||||
// GetMempoolEntryResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetMempoolEntryResponseMessage struct {
|
||||
baseMessage
|
||||
Entry *MempoolEntry
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// MempoolEntry represents a transaction in the mempool.
|
||||
type MempoolEntry struct {
|
||||
Fee uint64
|
||||
TransactionVerboseData *TransactionVerboseData
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetMempoolEntryResponseMessage) Command() MessageCommand {
|
||||
return CmdGetMempoolEntryResponseMessage
|
||||
}
|
||||
|
||||
// NewGetMempoolEntryResponseMessage returns a instance of the message
|
||||
func NewGetMempoolEntryResponseMessage(fee uint64, transactionVerboseData *TransactionVerboseData) *GetMempoolEntryResponseMessage {
|
||||
return &GetMempoolEntryResponseMessage{
|
||||
Entry: &MempoolEntry{
|
||||
Fee: fee,
|
||||
TransactionVerboseData: transactionVerboseData,
|
||||
},
|
||||
}
|
||||
}
|
||||
46
app/appmessage/rpc_get_peer_addresses.go
Normal file
46
app/appmessage/rpc_get_peer_addresses.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package appmessage
|
||||
|
||||
// GetPeerAddressesRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetPeerAddressesRequestMessage struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetPeerAddressesRequestMessage) Command() MessageCommand {
|
||||
return CmdGetPeerAddressesRequestMessage
|
||||
}
|
||||
|
||||
// NewGetPeerAddressesRequestMessage returns a instance of the message
|
||||
func NewGetPeerAddressesRequestMessage() *GetPeerAddressesRequestMessage {
|
||||
return &GetPeerAddressesRequestMessage{}
|
||||
}
|
||||
|
||||
// GetPeerAddressesResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetPeerAddressesResponseMessage struct {
|
||||
baseMessage
|
||||
Addresses []*GetPeerAddressesKnownAddressMessage
|
||||
BannedAddresses []*GetPeerAddressesKnownAddressMessage
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetPeerAddressesResponseMessage) Command() MessageCommand {
|
||||
return CmdGetPeerAddressesResponseMessage
|
||||
}
|
||||
|
||||
// NewGetPeerAddressesResponseMessage returns a instance of the message
|
||||
func NewGetPeerAddressesResponseMessage(addresses []*GetPeerAddressesKnownAddressMessage, bannedAddresses []*GetPeerAddressesKnownAddressMessage) *GetPeerAddressesResponseMessage {
|
||||
return &GetPeerAddressesResponseMessage{
|
||||
Addresses: addresses,
|
||||
BannedAddresses: bannedAddresses,
|
||||
}
|
||||
}
|
||||
|
||||
// GetPeerAddressesKnownAddressMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetPeerAddressesKnownAddressMessage struct {
|
||||
Addr string
|
||||
}
|
||||
38
app/appmessage/rpc_get_selected_tip_hash.go
Normal file
38
app/appmessage/rpc_get_selected_tip_hash.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package appmessage
|
||||
|
||||
// GetSelectedTipHashRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetSelectedTipHashRequestMessage struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetSelectedTipHashRequestMessage) Command() MessageCommand {
|
||||
return CmdGetSelectedTipHashRequestMessage
|
||||
}
|
||||
|
||||
// NewGetSelectedTipHashRequestMessage returns a instance of the message
|
||||
func NewGetSelectedTipHashRequestMessage() *GetSelectedTipHashRequestMessage {
|
||||
return &GetSelectedTipHashRequestMessage{}
|
||||
}
|
||||
|
||||
// GetSelectedTipHashResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetSelectedTipHashResponseMessage struct {
|
||||
baseMessage
|
||||
SelectedTipHash string
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetSelectedTipHashResponseMessage) Command() MessageCommand {
|
||||
return CmdGetSelectedTipHashResponseMessage
|
||||
}
|
||||
|
||||
// NewGetSelectedTipHashResponseMessage returns a instance of the message
|
||||
func NewGetSelectedTipHashResponseMessage(selectedTipHash string) *GetSelectedTipHashResponseMessage {
|
||||
return &GetSelectedTipHashResponseMessage{
|
||||
SelectedTipHash: selectedTipHash,
|
||||
}
|
||||
}
|
||||
41
app/appmessage/rpc_get_subnetwork.go
Normal file
41
app/appmessage/rpc_get_subnetwork.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package appmessage
|
||||
|
||||
// GetSubnetworkRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetSubnetworkRequestMessage struct {
|
||||
baseMessage
|
||||
SubnetworkID string
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetSubnetworkRequestMessage) Command() MessageCommand {
|
||||
return CmdGetSubnetworkRequestMessage
|
||||
}
|
||||
|
||||
// NewGetSubnetworkRequestMessage returns a instance of the message
|
||||
func NewGetSubnetworkRequestMessage(subnetworkID string) *GetSubnetworkRequestMessage {
|
||||
return &GetSubnetworkRequestMessage{
|
||||
SubnetworkID: subnetworkID,
|
||||
}
|
||||
}
|
||||
|
||||
// GetSubnetworkResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetSubnetworkResponseMessage struct {
|
||||
baseMessage
|
||||
GasLimit uint64
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetSubnetworkResponseMessage) Command() MessageCommand {
|
||||
return CmdGetSubnetworkResponseMessage
|
||||
}
|
||||
|
||||
// NewGetSubnetworkResponseMessage returns a instance of the message
|
||||
func NewGetSubnetworkResponseMessage(gasLimit uint64) *GetSubnetworkResponseMessage {
|
||||
return &GetSubnetworkResponseMessage{
|
||||
GasLimit: gasLimit,
|
||||
}
|
||||
}
|
||||
53
app/appmessage/rpc_notify_block_added.go
Normal file
53
app/appmessage/rpc_notify_block_added.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package appmessage
|
||||
|
||||
// NotifyBlockAddedRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type NotifyBlockAddedRequestMessage struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *NotifyBlockAddedRequestMessage) Command() MessageCommand {
|
||||
return CmdNotifyBlockAddedRequestMessage
|
||||
}
|
||||
|
||||
// NewNotifyBlockAddedRequestMessage returns a instance of the message
|
||||
func NewNotifyBlockAddedRequestMessage() *NotifyBlockAddedRequestMessage {
|
||||
return &NotifyBlockAddedRequestMessage{}
|
||||
}
|
||||
|
||||
// NotifyBlockAddedResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type NotifyBlockAddedResponseMessage struct {
|
||||
baseMessage
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *NotifyBlockAddedResponseMessage) Command() MessageCommand {
|
||||
return CmdNotifyBlockAddedResponseMessage
|
||||
}
|
||||
|
||||
// NewNotifyBlockAddedResponseMessage returns a instance of the message
|
||||
func NewNotifyBlockAddedResponseMessage() *NotifyBlockAddedResponseMessage {
|
||||
return &NotifyBlockAddedResponseMessage{}
|
||||
}
|
||||
|
||||
// BlockAddedNotificationMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type BlockAddedNotificationMessage struct {
|
||||
baseMessage
|
||||
Block *MsgBlock
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *BlockAddedNotificationMessage) Command() MessageCommand {
|
||||
return CmdBlockAddedNotificationMessage
|
||||
}
|
||||
|
||||
// NewBlockAddedNotificationMessage returns a instance of the message
|
||||
func NewBlockAddedNotificationMessage(block *MsgBlock) *BlockAddedNotificationMessage {
|
||||
return &BlockAddedNotificationMessage{
|
||||
Block: block,
|
||||
}
|
||||
}
|
||||
69
app/appmessage/rpc_notify_chain_changed.go
Normal file
69
app/appmessage/rpc_notify_chain_changed.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package appmessage
|
||||
|
||||
// NotifyChainChangedRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type NotifyChainChangedRequestMessage struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *NotifyChainChangedRequestMessage) Command() MessageCommand {
|
||||
return CmdNotifyChainChangedRequestMessage
|
||||
}
|
||||
|
||||
// NewNotifyChainChangedRequestMessage returns a instance of the message
|
||||
func NewNotifyChainChangedRequestMessage() *NotifyChainChangedRequestMessage {
|
||||
return &NotifyChainChangedRequestMessage{}
|
||||
}
|
||||
|
||||
// NotifyChainChangedResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type NotifyChainChangedResponseMessage struct {
|
||||
baseMessage
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *NotifyChainChangedResponseMessage) Command() MessageCommand {
|
||||
return CmdNotifyChainChangedResponseMessage
|
||||
}
|
||||
|
||||
// NewNotifyChainChangedResponseMessage returns a instance of the message
|
||||
func NewNotifyChainChangedResponseMessage() *NotifyChainChangedResponseMessage {
|
||||
return &NotifyChainChangedResponseMessage{}
|
||||
}
|
||||
|
||||
// ChainChangedNotificationMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type ChainChangedNotificationMessage struct {
|
||||
baseMessage
|
||||
RemovedChainBlockHashes []string
|
||||
AddedChainBlocks []*ChainBlock
|
||||
}
|
||||
|
||||
// ChainBlock represents a DAG chain-block
|
||||
type ChainBlock struct {
|
||||
Hash string
|
||||
AcceptedBlocks []*AcceptedBlock
|
||||
}
|
||||
|
||||
// AcceptedBlock represents a block accepted into the DAG
|
||||
type AcceptedBlock struct {
|
||||
Hash string
|
||||
AcceptedTxIDs []string
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *ChainChangedNotificationMessage) Command() MessageCommand {
|
||||
return CmdChainChangedNotificationMessage
|
||||
}
|
||||
|
||||
// NewChainChangedNotificationMessage returns a instance of the message
|
||||
func NewChainChangedNotificationMessage(removedChainBlockHashes []string,
|
||||
addedChainBlocks []*ChainBlock) *ChainChangedNotificationMessage {
|
||||
|
||||
return &ChainChangedNotificationMessage{
|
||||
RemovedChainBlockHashes: removedChainBlockHashes,
|
||||
AddedChainBlocks: addedChainBlocks,
|
||||
}
|
||||
}
|
||||
72
app/appmessage/rpc_notify_finality_conflicts.go
Normal file
72
app/appmessage/rpc_notify_finality_conflicts.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package appmessage
|
||||
|
||||
// NotifyFinalityConflictsRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type NotifyFinalityConflictsRequestMessage struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *NotifyFinalityConflictsRequestMessage) Command() MessageCommand {
|
||||
return CmdNotifyFinalityConflictsRequestMessage
|
||||
}
|
||||
|
||||
// NewNotifyFinalityConflictsRequestMessage returns a instance of the message
|
||||
func NewNotifyFinalityConflictsRequestMessage() *NotifyFinalityConflictsRequestMessage {
|
||||
return &NotifyFinalityConflictsRequestMessage{}
|
||||
}
|
||||
|
||||
// NotifyFinalityConflictsResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type NotifyFinalityConflictsResponseMessage struct {
|
||||
baseMessage
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *NotifyFinalityConflictsResponseMessage) Command() MessageCommand {
|
||||
return CmdNotifyFinalityConflictsResponseMessage
|
||||
}
|
||||
|
||||
// NewNotifyFinalityConflictsResponseMessage returns a instance of the message
|
||||
func NewNotifyFinalityConflictsResponseMessage() *NotifyFinalityConflictsResponseMessage {
|
||||
return &NotifyFinalityConflictsResponseMessage{}
|
||||
}
|
||||
|
||||
// FinalityConflictNotificationMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type FinalityConflictNotificationMessage struct {
|
||||
baseMessage
|
||||
ViolatingBlockHash string
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *FinalityConflictNotificationMessage) Command() MessageCommand {
|
||||
return CmdFinalityConflictNotificationMessage
|
||||
}
|
||||
|
||||
// NewFinalityConflictNotificationMessage returns a instance of the message
|
||||
func NewFinalityConflictNotificationMessage(violatingBlockHash string) *FinalityConflictNotificationMessage {
|
||||
return &FinalityConflictNotificationMessage{
|
||||
ViolatingBlockHash: violatingBlockHash,
|
||||
}
|
||||
}
|
||||
|
||||
// FinalityConflictResolvedNotificationMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type FinalityConflictResolvedNotificationMessage struct {
|
||||
baseMessage
|
||||
FinalityBlockHash string
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *FinalityConflictResolvedNotificationMessage) Command() MessageCommand {
|
||||
return CmdFinalityConflictResolvedNotificationMessage
|
||||
}
|
||||
|
||||
// NewFinalityConflictResolvedNotificationMessage returns a instance of the message
|
||||
func NewFinalityConflictResolvedNotificationMessage(finalityBlockHash string) *FinalityConflictResolvedNotificationMessage {
|
||||
return &FinalityConflictResolvedNotificationMessage{
|
||||
FinalityBlockHash: finalityBlockHash,
|
||||
}
|
||||
}
|
||||
37
app/appmessage/rpc_resolve_finality_conflict.go
Normal file
37
app/appmessage/rpc_resolve_finality_conflict.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package appmessage
|
||||
|
||||
// ResolveFinalityConflictRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type ResolveFinalityConflictRequestMessage struct {
|
||||
baseMessage
|
||||
FinalityBlockHash string
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *ResolveFinalityConflictRequestMessage) Command() MessageCommand {
|
||||
return CmdResolveFinalityConflictRequestMessage
|
||||
}
|
||||
|
||||
// NewResolveFinalityConflictRequestMessage returns a instance of the message
|
||||
func NewResolveFinalityConflictRequestMessage(finalityBlockHash string) *ResolveFinalityConflictRequestMessage {
|
||||
return &ResolveFinalityConflictRequestMessage{
|
||||
FinalityBlockHash: finalityBlockHash,
|
||||
}
|
||||
}
|
||||
|
||||
// ResolveFinalityConflictResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type ResolveFinalityConflictResponseMessage struct {
|
||||
baseMessage
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *ResolveFinalityConflictResponseMessage) Command() MessageCommand {
|
||||
return CmdResolveFinalityConflictResponseMessage
|
||||
}
|
||||
|
||||
// NewResolveFinalityConflictResponseMessage returns a instance of the message
|
||||
func NewResolveFinalityConflictResponseMessage() *ResolveFinalityConflictResponseMessage {
|
||||
return &ResolveFinalityConflictResponseMessage{}
|
||||
}
|
||||
34
app/appmessage/rpc_shut_down.go
Normal file
34
app/appmessage/rpc_shut_down.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package appmessage
|
||||
|
||||
// ShutDownRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type ShutDownRequestMessage struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *ShutDownRequestMessage) Command() MessageCommand {
|
||||
return CmdShutDownRequestMessage
|
||||
}
|
||||
|
||||
// NewShutDownRequestMessage returns a instance of the message
|
||||
func NewShutDownRequestMessage() *ShutDownRequestMessage {
|
||||
return &ShutDownRequestMessage{}
|
||||
}
|
||||
|
||||
// ShutDownResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type ShutDownResponseMessage struct {
|
||||
baseMessage
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *ShutDownResponseMessage) Command() MessageCommand {
|
||||
return CmdShutDownResponseMessage
|
||||
}
|
||||
|
||||
// NewShutDownResponseMessage returns a instance of the message
|
||||
func NewShutDownResponseMessage() *ShutDownResponseMessage {
|
||||
return &ShutDownResponseMessage{}
|
||||
}
|
||||
37
app/appmessage/rpc_submit_block.go
Normal file
37
app/appmessage/rpc_submit_block.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package appmessage
|
||||
|
||||
// SubmitBlockRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type SubmitBlockRequestMessage struct {
|
||||
baseMessage
|
||||
BlockHex string
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *SubmitBlockRequestMessage) Command() MessageCommand {
|
||||
return CmdSubmitBlockRequestMessage
|
||||
}
|
||||
|
||||
// NewSubmitBlockRequestMessage returns a instance of the message
|
||||
func NewSubmitBlockRequestMessage(blockHex string) *SubmitBlockRequestMessage {
|
||||
return &SubmitBlockRequestMessage{
|
||||
BlockHex: blockHex,
|
||||
}
|
||||
}
|
||||
|
||||
// SubmitBlockResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type SubmitBlockResponseMessage struct {
|
||||
baseMessage
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *SubmitBlockResponseMessage) Command() MessageCommand {
|
||||
return CmdSubmitBlockResponseMessage
|
||||
}
|
||||
|
||||
// NewSubmitBlockResponseMessage returns a instance of the message
|
||||
func NewSubmitBlockResponseMessage() *SubmitBlockResponseMessage {
|
||||
return &SubmitBlockResponseMessage{}
|
||||
}
|
||||
41
app/appmessage/rpc_submit_transaction.go
Normal file
41
app/appmessage/rpc_submit_transaction.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package appmessage
|
||||
|
||||
// SubmitTransactionRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type SubmitTransactionRequestMessage struct {
|
||||
baseMessage
|
||||
TransactionHex string
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *SubmitTransactionRequestMessage) Command() MessageCommand {
|
||||
return CmdSubmitTransactionRequestMessage
|
||||
}
|
||||
|
||||
// NewSubmitTransactionRequestMessage returns a instance of the message
|
||||
func NewSubmitTransactionRequestMessage(transactionHex string) *SubmitTransactionRequestMessage {
|
||||
return &SubmitTransactionRequestMessage{
|
||||
TransactionHex: transactionHex,
|
||||
}
|
||||
}
|
||||
|
||||
// SubmitTransactionResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type SubmitTransactionResponseMessage struct {
|
||||
baseMessage
|
||||
TxID string
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *SubmitTransactionResponseMessage) Command() MessageCommand {
|
||||
return CmdSubmitTransactionResponseMessage
|
||||
}
|
||||
|
||||
// NewSubmitTransactionResponseMessage returns a instance of the message
|
||||
func NewSubmitTransactionResponseMessage(txID string) *SubmitTransactionResponseMessage {
|
||||
return &SubmitTransactionResponseMessage{
|
||||
TxID: txID,
|
||||
}
|
||||
}
|
||||
259
app/component_manager.go
Normal file
259
app/component_manager.go
Normal file
@@ -0,0 +1,259 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/addressmanager"
|
||||
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/id"
|
||||
|
||||
"github.com/kaspanet/kaspad/app/appmessage"
|
||||
"github.com/kaspanet/kaspad/app/protocol"
|
||||
"github.com/kaspanet/kaspad/app/rpc"
|
||||
"github.com/kaspanet/kaspad/domain/blockdag"
|
||||
"github.com/kaspanet/kaspad/domain/blockdag/indexers"
|
||||
"github.com/kaspanet/kaspad/domain/mempool"
|
||||
"github.com/kaspanet/kaspad/domain/mining"
|
||||
"github.com/kaspanet/kaspad/domain/txscript"
|
||||
"github.com/kaspanet/kaspad/infrastructure/config"
|
||||
"github.com/kaspanet/kaspad/infrastructure/db/dbaccess"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/connmanager"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/dnsseed"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter"
|
||||
"github.com/kaspanet/kaspad/util/panics"
|
||||
)
|
||||
|
||||
// ComponentManager is a wrapper for all the kaspad services
|
||||
type ComponentManager struct {
|
||||
cfg *config.Config
|
||||
addressManager *addressmanager.AddressManager
|
||||
protocolManager *protocol.Manager
|
||||
rpcManager *rpc.Manager
|
||||
connectionManager *connmanager.ConnectionManager
|
||||
netAdapter *netadapter.NetAdapter
|
||||
|
||||
started, shutdown int32
|
||||
}
|
||||
|
||||
// Start launches all the kaspad services.
|
||||
func (a *ComponentManager) Start() {
|
||||
// Already started?
|
||||
if atomic.AddInt32(&a.started, 1) != 1 {
|
||||
return
|
||||
}
|
||||
|
||||
log.Trace("Starting kaspad")
|
||||
|
||||
err := a.netAdapter.Start()
|
||||
if err != nil {
|
||||
panics.Exit(log, fmt.Sprintf("Error starting the net adapter: %+v", err))
|
||||
}
|
||||
|
||||
a.maybeSeedFromDNS()
|
||||
|
||||
a.connectionManager.Start()
|
||||
}
|
||||
|
||||
// Stop gracefully shuts down all the kaspad services.
|
||||
func (a *ComponentManager) Stop() {
|
||||
// Make sure this only happens once.
|
||||
if atomic.AddInt32(&a.shutdown, 1) != 1 {
|
||||
log.Infof("Kaspad is already in the process of shutting down")
|
||||
return
|
||||
}
|
||||
|
||||
log.Warnf("Kaspad shutting down")
|
||||
|
||||
a.connectionManager.Stop()
|
||||
|
||||
err := a.netAdapter.Stop()
|
||||
if err != nil {
|
||||
log.Errorf("Error stopping the net adapter: %+v", err)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// NewComponentManager returns a new ComponentManager instance.
|
||||
// Use Start() to begin all services within this ComponentManager
|
||||
func NewComponentManager(cfg *config.Config, databaseContext *dbaccess.DatabaseContext, interrupt chan<- struct{}) (*ComponentManager, error) {
|
||||
indexManager, acceptanceIndex := setupIndexes(cfg)
|
||||
|
||||
sigCache := txscript.NewSigCache(cfg.SigCacheMaxSize)
|
||||
|
||||
// Create a new block DAG instance with the appropriate configuration.
|
||||
dag, err := setupDAG(cfg, databaseContext, sigCache, indexManager)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
txMempool := setupMempool(cfg, dag, sigCache)
|
||||
|
||||
netAdapter, err := netadapter.NewNetAdapter(cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addressManager, err := addressmanager.New(addressmanager.NewConfig(cfg))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
connectionManager, err := connmanager.New(cfg, netAdapter, addressManager)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
protocolManager, err := protocol.NewManager(cfg, dag, netAdapter, addressManager, txMempool, connectionManager)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rpcManager := setupRPC(cfg, txMempool, dag, sigCache, netAdapter, protocolManager, connectionManager, addressManager, acceptanceIndex, interrupt)
|
||||
|
||||
return &ComponentManager{
|
||||
cfg: cfg,
|
||||
protocolManager: protocolManager,
|
||||
rpcManager: rpcManager,
|
||||
connectionManager: connectionManager,
|
||||
netAdapter: netAdapter,
|
||||
addressManager: addressManager,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
func setupRPC(
|
||||
cfg *config.Config,
|
||||
txMempool *mempool.TxPool,
|
||||
dag *blockdag.BlockDAG,
|
||||
sigCache *txscript.SigCache,
|
||||
netAdapter *netadapter.NetAdapter,
|
||||
protocolManager *protocol.Manager,
|
||||
connectionManager *connmanager.ConnectionManager,
|
||||
addressManager *addressmanager.AddressManager,
|
||||
acceptanceIndex *indexers.AcceptanceIndex,
|
||||
shutDownChan chan<- struct{},
|
||||
) *rpc.Manager {
|
||||
|
||||
blockTemplateGenerator := mining.NewBlkTmplGenerator(&mining.Policy{BlockMaxMass: cfg.BlockMaxMass}, txMempool, dag, sigCache)
|
||||
rpcManager := rpc.NewManager(cfg, netAdapter, dag, protocolManager, connectionManager, blockTemplateGenerator, txMempool, addressManager, acceptanceIndex, shutDownChan)
|
||||
protocolManager.SetOnBlockAddedToDAGHandler(rpcManager.NotifyBlockAddedToDAG)
|
||||
protocolManager.SetOnTransactionAddedToMempoolHandler(rpcManager.NotifyTransactionAddedToMempool)
|
||||
dag.Subscribe(func(notification *blockdag.Notification) {
|
||||
err := handleBlockDAGNotifications(notification, acceptanceIndex, rpcManager)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
})
|
||||
return rpcManager
|
||||
}
|
||||
|
||||
func handleBlockDAGNotifications(notification *blockdag.Notification,
|
||||
acceptanceIndex *indexers.AcceptanceIndex, rpcManager *rpc.Manager) error {
|
||||
|
||||
switch notification.Type {
|
||||
case blockdag.NTChainChanged:
|
||||
if acceptanceIndex == nil {
|
||||
return nil
|
||||
}
|
||||
chainChangedNotificationData := notification.Data.(*blockdag.ChainChangedNotificationData)
|
||||
err := rpcManager.NotifyChainChanged(chainChangedNotificationData.RemovedChainBlockHashes,
|
||||
chainChangedNotificationData.AddedChainBlockHashes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case blockdag.NTFinalityConflict:
|
||||
finalityConflictNotificationData := notification.Data.(*blockdag.FinalityConflictNotificationData)
|
||||
err := rpcManager.NotifyFinalityConflict(finalityConflictNotificationData.ViolatingBlockHash.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case blockdag.NTFinalityConflictResolved:
|
||||
finalityConflictResolvedNotificationData := notification.Data.(*blockdag.FinalityConflictResolvedNotificationData)
|
||||
err := rpcManager.NotifyFinalityConflictResolved(finalityConflictResolvedNotificationData.FinalityBlockHash.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *ComponentManager) maybeSeedFromDNS() {
|
||||
if !a.cfg.DisableDNSSeed {
|
||||
dnsseed.SeedFromDNS(a.cfg.NetParams(), a.cfg.DNSSeed, appmessage.SFNodeNetwork, false, nil,
|
||||
a.cfg.Lookup, func(addresses []*appmessage.NetAddress) {
|
||||
// Kaspad uses a lookup of the dns seeder here. Since seeder returns
|
||||
// IPs of nodes and not its own IP, we can not know real IP of
|
||||
// source. So we'll take first returned address as source.
|
||||
a.addressManager.AddAddresses(addresses...)
|
||||
})
|
||||
}
|
||||
|
||||
if a.cfg.GRPCSeed != "" {
|
||||
dnsseed.SeedFromGRPC(a.cfg.NetParams(), a.cfg.GRPCSeed, appmessage.SFNodeNetwork, false, nil,
|
||||
func(addresses []*appmessage.NetAddress) {
|
||||
a.addressManager.AddAddresses(addresses...)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func setupDAG(cfg *config.Config, databaseContext *dbaccess.DatabaseContext,
|
||||
sigCache *txscript.SigCache, indexManager blockdag.IndexManager) (*blockdag.BlockDAG, error) {
|
||||
|
||||
dag, err := blockdag.New(&blockdag.Config{
|
||||
DatabaseContext: databaseContext,
|
||||
DAGParams: cfg.NetParams(),
|
||||
TimeSource: blockdag.NewTimeSource(),
|
||||
SigCache: sigCache,
|
||||
IndexManager: indexManager,
|
||||
SubnetworkID: cfg.SubnetworkID,
|
||||
MaxUTXOCacheSize: cfg.MaxUTXOCacheSize,
|
||||
})
|
||||
return dag, err
|
||||
}
|
||||
|
||||
func setupIndexes(cfg *config.Config) (blockdag.IndexManager, *indexers.AcceptanceIndex) {
|
||||
// Create indexes if needed.
|
||||
var indexes []indexers.Indexer
|
||||
var acceptanceIndex *indexers.AcceptanceIndex
|
||||
if cfg.AcceptanceIndex {
|
||||
log.Info("acceptance index is enabled")
|
||||
acceptanceIndex = indexers.NewAcceptanceIndex()
|
||||
indexes = append(indexes, acceptanceIndex)
|
||||
}
|
||||
|
||||
// Create an index manager if any of the optional indexes are enabled.
|
||||
if len(indexes) < 0 {
|
||||
return nil, nil
|
||||
}
|
||||
indexManager := indexers.NewManager(indexes)
|
||||
return indexManager, acceptanceIndex
|
||||
}
|
||||
|
||||
func setupMempool(cfg *config.Config, dag *blockdag.BlockDAG, sigCache *txscript.SigCache) *mempool.TxPool {
|
||||
mempoolConfig := mempool.Config{
|
||||
Policy: mempool.Policy{
|
||||
AcceptNonStd: cfg.RelayNonStd,
|
||||
MaxOrphanTxs: cfg.MaxOrphanTxs,
|
||||
MaxOrphanTxSize: config.DefaultMaxOrphanTxSize,
|
||||
MinRelayTxFee: cfg.MinRelayTxFee,
|
||||
MaxTxVersion: 1,
|
||||
},
|
||||
CalcTxSequenceLockFromReferencedUTXOEntries: dag.CalcTxSequenceLockFromReferencedUTXOEntries,
|
||||
SigCache: sigCache,
|
||||
DAG: dag,
|
||||
}
|
||||
|
||||
return mempool.New(&mempoolConfig)
|
||||
}
|
||||
|
||||
// P2PNodeID returns the network ID associated with this ComponentManager
|
||||
func (a *ComponentManager) P2PNodeID() *id.ID {
|
||||
return a.netAdapter.ID()
|
||||
}
|
||||
|
||||
// AddressManager returns the AddressManager associated with this ComponentManager
|
||||
func (a *ComponentManager) AddressManager() *addressmanager.AddressManager {
|
||||
return a.addressManager
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/logger"
|
||||
"github.com/kaspanet/kaspad/infrastructure/logger"
|
||||
"github.com/kaspanet/kaspad/util/panics"
|
||||
)
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
package blocklogger
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/logger"
|
||||
"github.com/kaspanet/kaspad/infrastructure/logger"
|
||||
)
|
||||
|
||||
var log, _ = logger.Get(logger.SubsystemTags.PROT)
|
||||
@@ -1,7 +1,7 @@
|
||||
package flowcontext
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/addressmanager"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/addressmanager"
|
||||
)
|
||||
|
||||
// AddressManager returns the address manager associated to the flow context.
|
||||
@@ -3,9 +3,9 @@ package flowcontext
|
||||
import (
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/kaspanet/kaspad/blockdag"
|
||||
"github.com/kaspanet/kaspad/domainmessage"
|
||||
"github.com/kaspanet/kaspad/protocol/flows/blockrelay"
|
||||
"github.com/kaspanet/kaspad/app/appmessage"
|
||||
"github.com/kaspanet/kaspad/app/protocol/flows/blockrelay"
|
||||
"github.com/kaspanet/kaspad/domain/blockdag"
|
||||
"github.com/kaspanet/kaspad/util"
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
)
|
||||
@@ -18,8 +18,12 @@ func (f *FlowContext) OnNewBlock(block *util.Block) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO(libp2p) Notify transactionsAcceptedToMempool to RPC
|
||||
if f.onBlockAddedToDAGHandler != nil {
|
||||
err := f.onBlockAddedToDAGHandler(block)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return f.broadcastTransactionsAfterBlockAdded(block, transactionsAcceptedToMempool)
|
||||
}
|
||||
@@ -41,16 +45,18 @@ func (f *FlowContext) broadcastTransactionsAfterBlockAdded(block *util.Block, tr
|
||||
for i, tx := range transactionsAcceptedToMempool {
|
||||
txIDsToBroadcast[i] = tx.ID()
|
||||
}
|
||||
|
||||
copy(txIDsToBroadcast[len(transactionsAcceptedToMempool):], txIDsToBroadcast)
|
||||
offset := len(transactionsAcceptedToMempool)
|
||||
for i, txID := range txIDsToRebroadcast {
|
||||
txIDsToBroadcast[offset+i] = txID
|
||||
}
|
||||
|
||||
if len(txIDsToBroadcast) == 0 {
|
||||
return nil
|
||||
}
|
||||
if len(txIDsToBroadcast) > domainmessage.MaxInvPerTxInvMsg {
|
||||
txIDsToBroadcast = txIDsToBroadcast[:domainmessage.MaxInvPerTxInvMsg]
|
||||
if len(txIDsToBroadcast) > appmessage.MaxInvPerTxInvMsg {
|
||||
txIDsToBroadcast = txIDsToBroadcast[:appmessage.MaxInvPerTxInvMsg]
|
||||
}
|
||||
inv := domainmessage.NewMsgInvTransaction(txIDsToBroadcast)
|
||||
inv := appmessage.NewMsgInvTransaction(txIDsToBroadcast)
|
||||
return f.Broadcast(inv)
|
||||
}
|
||||
|
||||
@@ -66,5 +72,9 @@ func (f *FlowContext) AddBlock(block *util.Block, flags blockdag.BehaviorFlags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return f.Broadcast(domainmessage.NewMsgInvBlock(block.Hash()))
|
||||
err = f.OnNewBlock(block)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return f.Broadcast(appmessage.NewMsgInvBlock(block.Hash()))
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package flowcontext
|
||||
|
||||
import "github.com/kaspanet/kaspad/config"
|
||||
import "github.com/kaspanet/kaspad/infrastructure/config"
|
||||
|
||||
// Config returns an instance of *config.Config associated to the flow context.
|
||||
func (f *FlowContext) Config() *config.Config {
|
||||
@@ -1,6 +1,6 @@
|
||||
package flowcontext
|
||||
|
||||
import "github.com/kaspanet/kaspad/blockdag"
|
||||
import "github.com/kaspanet/kaspad/domain/blockdag"
|
||||
|
||||
// DAG returns the DAG associated to the flow context.
|
||||
func (f *FlowContext) DAG() *blockdag.BlockDAG {
|
||||
31
app/protocol/flowcontext/errors.go
Normal file
31
app/protocol/flowcontext/errors.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package flowcontext
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
||||
|
||||
"github.com/kaspanet/kaspad/app/protocol/protocolerrors"
|
||||
)
|
||||
|
||||
// HandleError handles an error from a flow,
|
||||
// It sends the error to errChan if isStopping == 0 and increments isStopping
|
||||
//
|
||||
// If this is ErrRouteClosed - forward it to errChan
|
||||
// If this is ProtocolError - logs the error, and forward it to errChan
|
||||
// Otherwise - panics
|
||||
func (*FlowContext) HandleError(err error, flowName string, isStopping *uint32, errChan chan<- error) {
|
||||
isErrRouteClosed := errors.Is(err, router.ErrRouteClosed)
|
||||
if !isErrRouteClosed {
|
||||
if protocolErr := &(protocolerrors.ProtocolError{}); !errors.As(err, &protocolErr) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
log.Errorf("error from %s: %+v", flowName, err)
|
||||
}
|
||||
|
||||
if atomic.AddUint32(isStopping, 1) == 1 {
|
||||
errChan <- err
|
||||
}
|
||||
}
|
||||
@@ -4,20 +4,28 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/kaspanet/kaspad/addressmanager"
|
||||
"github.com/kaspanet/kaspad/blockdag"
|
||||
"github.com/kaspanet/kaspad/config"
|
||||
"github.com/kaspanet/kaspad/connmanager"
|
||||
"github.com/kaspanet/kaspad/mempool"
|
||||
"github.com/kaspanet/kaspad/netadapter"
|
||||
"github.com/kaspanet/kaspad/netadapter/id"
|
||||
"github.com/kaspanet/kaspad/protocol/flows/blockrelay"
|
||||
"github.com/kaspanet/kaspad/protocol/flows/relaytransactions"
|
||||
peerpkg "github.com/kaspanet/kaspad/protocol/peer"
|
||||
"github.com/kaspanet/kaspad/app/protocol/flows/blockrelay"
|
||||
"github.com/kaspanet/kaspad/app/protocol/flows/relaytransactions"
|
||||
peerpkg "github.com/kaspanet/kaspad/app/protocol/peer"
|
||||
"github.com/kaspanet/kaspad/domain/blockdag"
|
||||
"github.com/kaspanet/kaspad/domain/mempool"
|
||||
"github.com/kaspanet/kaspad/infrastructure/config"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/addressmanager"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/connmanager"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/id"
|
||||
"github.com/kaspanet/kaspad/util"
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
)
|
||||
|
||||
// OnBlockAddedToDAGHandler is a handler function that's triggered
|
||||
// when a block is added to the DAG
|
||||
type OnBlockAddedToDAGHandler func(block *util.Block) error
|
||||
|
||||
// OnTransactionAddedToMempoolHandler is a handler function that's triggered
|
||||
// when a transaction is added to the mempool
|
||||
type OnTransactionAddedToMempoolHandler func()
|
||||
|
||||
// FlowContext holds state that is relevant to more than one flow or one peer, and allows communication between
|
||||
// different flows that can be associated to different peers.
|
||||
type FlowContext struct {
|
||||
@@ -28,6 +36,9 @@ type FlowContext struct {
|
||||
addressManager *addressmanager.AddressManager
|
||||
connectionManager *connmanager.ConnectionManager
|
||||
|
||||
onBlockAddedToDAGHandler OnBlockAddedToDAGHandler
|
||||
onTransactionAddedToMempoolHandler OnTransactionAddedToMempoolHandler
|
||||
|
||||
transactionsToRebroadcastLock sync.Mutex
|
||||
transactionsToRebroadcast map[daghash.TxID]*util.Tx
|
||||
lastRebroadcastTime time.Time
|
||||
@@ -39,7 +50,7 @@ type FlowContext struct {
|
||||
startIBDMutex sync.Mutex
|
||||
ibdPeer *peerpkg.Peer
|
||||
|
||||
peers map[*id.ID]*peerpkg.Peer
|
||||
peers map[id.ID]*peerpkg.Peer
|
||||
peersMutex sync.RWMutex
|
||||
}
|
||||
|
||||
@@ -57,7 +68,17 @@ func New(cfg *config.Config, dag *blockdag.BlockDAG, addressManager *addressmana
|
||||
txPool: txPool,
|
||||
sharedRequestedTransactions: relaytransactions.NewSharedRequestedTransactions(),
|
||||
sharedRequestedBlocks: blockrelay.NewSharedRequestedBlocks(),
|
||||
peers: make(map[*id.ID]*peerpkg.Peer),
|
||||
peers: make(map[id.ID]*peerpkg.Peer),
|
||||
transactionsToRebroadcast: make(map[daghash.TxID]*util.Tx),
|
||||
}
|
||||
}
|
||||
|
||||
// SetOnBlockAddedToDAGHandler sets the onBlockAddedToDAG handler
|
||||
func (f *FlowContext) SetOnBlockAddedToDAGHandler(onBlockAddedToDAGHandler OnBlockAddedToDAGHandler) {
|
||||
f.onBlockAddedToDAGHandler = onBlockAddedToDAGHandler
|
||||
}
|
||||
|
||||
// SetOnTransactionAddedToMempoolHandler sets the onTransactionAddedToMempool handler
|
||||
func (f *FlowContext) SetOnTransactionAddedToMempoolHandler(onTransactionAddedToMempoolHandler OnTransactionAddedToMempoolHandler) {
|
||||
f.onTransactionAddedToMempoolHandler = onTransactionAddedToMempoolHandler
|
||||
}
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/kaspanet/kaspad/blockdag"
|
||||
peerpkg "github.com/kaspanet/kaspad/protocol/peer"
|
||||
peerpkg "github.com/kaspanet/kaspad/app/protocol/peer"
|
||||
"github.com/kaspanet/kaspad/domain/blockdag"
|
||||
)
|
||||
|
||||
// StartIBDIfRequired selects a peer and starts IBD against it
|
||||
@@ -37,6 +37,9 @@ func (f *FlowContext) IsInIBD() bool {
|
||||
// selectPeerForIBD returns the first peer whose selected tip
|
||||
// hash is not in our DAG
|
||||
func (f *FlowContext) selectPeerForIBD(dag *blockdag.BlockDAG) *peerpkg.Peer {
|
||||
f.peersMutex.RLock()
|
||||
defer f.peersMutex.RUnlock()
|
||||
|
||||
for _, peer := range f.peers {
|
||||
peerSelectedTipHash := peer.SelectedTipHash()
|
||||
if !dag.IsInDAG(peerSelectedTipHash) {
|
||||
@@ -59,6 +62,9 @@ func (f *FlowContext) isDAGTimeCurrent() bool {
|
||||
}
|
||||
|
||||
func (f *FlowContext) requestSelectedTips() {
|
||||
f.peersMutex.RLock()
|
||||
defer f.peersMutex.RUnlock()
|
||||
|
||||
for _, peer := range f.peers {
|
||||
peer.RequestSelectedTipIfRequired()
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package flowcontext
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/logger"
|
||||
"github.com/kaspanet/kaspad/infrastructure/logger"
|
||||
"github.com/kaspanet/kaspad/util/panics"
|
||||
)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package flowcontext
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/connmanager"
|
||||
"github.com/kaspanet/kaspad/domainmessage"
|
||||
"github.com/kaspanet/kaspad/netadapter"
|
||||
"github.com/kaspanet/kaspad/protocol/common"
|
||||
peerpkg "github.com/kaspanet/kaspad/protocol/peer"
|
||||
"github.com/kaspanet/kaspad/app/appmessage"
|
||||
"github.com/kaspanet/kaspad/app/protocol/common"
|
||||
peerpkg "github.com/kaspanet/kaspad/app/protocol/peer"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/connmanager"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -24,15 +24,23 @@ func (f *FlowContext) AddToPeers(peer *peerpkg.Peer) error {
|
||||
f.peersMutex.Lock()
|
||||
defer f.peersMutex.Unlock()
|
||||
|
||||
if _, ok := f.peers[peer.ID()]; ok {
|
||||
if _, ok := f.peers[*peer.ID()]; ok {
|
||||
return errors.Wrapf(common.ErrPeerWithSameIDExists, "peer with ID %s already exists", peer.ID())
|
||||
}
|
||||
|
||||
f.peers[peer.ID()] = peer
|
||||
f.peers[*peer.ID()] = peer
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveFromPeers remove this peer from the peers list.
|
||||
func (f *FlowContext) RemoveFromPeers(peer *peerpkg.Peer) {
|
||||
f.peersMutex.Lock()
|
||||
defer f.peersMutex.Unlock()
|
||||
|
||||
delete(f.peers, *peer.ID())
|
||||
}
|
||||
|
||||
// readyPeerConnections returns the NetConnections of all the ready peers.
|
||||
func (f *FlowContext) readyPeerConnections() []*netadapter.NetConnection {
|
||||
f.peersMutex.RLock()
|
||||
@@ -47,8 +55,8 @@ func (f *FlowContext) readyPeerConnections() []*netadapter.NetConnection {
|
||||
}
|
||||
|
||||
// Broadcast broadcast the given message to all the ready peers.
|
||||
func (f *FlowContext) Broadcast(message domainmessage.Message) error {
|
||||
return f.netAdapter.Broadcast(f.readyPeerConnections(), message)
|
||||
func (f *FlowContext) Broadcast(message appmessage.Message) error {
|
||||
return f.netAdapter.P2PBroadcast(f.readyPeerConnections(), message)
|
||||
}
|
||||
|
||||
// Peers returns the currently active peers
|
||||
@@ -1,9 +1,9 @@
|
||||
package flowcontext
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domainmessage"
|
||||
"github.com/kaspanet/kaspad/mempool"
|
||||
"github.com/kaspanet/kaspad/protocol/flows/relaytransactions"
|
||||
"github.com/kaspanet/kaspad/app/appmessage"
|
||||
"github.com/kaspanet/kaspad/app/protocol/flows/relaytransactions"
|
||||
"github.com/kaspanet/kaspad/domain/mempool"
|
||||
"github.com/kaspanet/kaspad/util"
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
"github.com/pkg/errors"
|
||||
@@ -15,7 +15,7 @@ func (f *FlowContext) AddTransaction(tx *util.Tx) error {
|
||||
f.transactionsToRebroadcastLock.Lock()
|
||||
defer f.transactionsToRebroadcastLock.Unlock()
|
||||
|
||||
transactionsAcceptedToMempool, err := f.txPool.ProcessTransaction(tx, false, 0)
|
||||
transactionsAcceptedToMempool, err := f.txPool.ProcessTransaction(tx, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -25,7 +25,7 @@ func (f *FlowContext) AddTransaction(tx *util.Tx) error {
|
||||
}
|
||||
|
||||
f.transactionsToRebroadcast[*tx.ID()] = tx
|
||||
inv := domainmessage.NewMsgInvTransaction([]*daghash.TxID{tx.ID()})
|
||||
inv := appmessage.NewMsgInvTransaction([]*daghash.TxID{tx.ID()})
|
||||
return f.Broadcast(inv)
|
||||
}
|
||||
|
||||
@@ -68,3 +68,11 @@ func (f *FlowContext) SharedRequestedTransactions() *relaytransactions.SharedReq
|
||||
func (f *FlowContext) TxPool() *mempool.TxPool {
|
||||
return f.txPool
|
||||
}
|
||||
|
||||
// OnTransactionAddedToMempool notifies the handler function that a transaction
|
||||
// has been added to the mempool
|
||||
func (f *FlowContext) OnTransactionAddedToMempool() {
|
||||
if f.onTransactionAddedToMempoolHandler != nil {
|
||||
f.onTransactionAddedToMempoolHandler()
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
package addressexchange
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/addressmanager"
|
||||
"github.com/kaspanet/kaspad/config"
|
||||
"github.com/kaspanet/kaspad/domainmessage"
|
||||
"github.com/kaspanet/kaspad/netadapter/router"
|
||||
"github.com/kaspanet/kaspad/protocol/common"
|
||||
peerpkg "github.com/kaspanet/kaspad/protocol/peer"
|
||||
"github.com/kaspanet/kaspad/protocol/protocolerrors"
|
||||
"github.com/kaspanet/kaspad/app/appmessage"
|
||||
"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/infrastructure/config"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/addressmanager"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
||||
)
|
||||
|
||||
// ReceiveAddressesContext is the interface for the context needed for the ReceiveAddresses flow.
|
||||
@@ -20,12 +20,8 @@ type ReceiveAddressesContext interface {
|
||||
func ReceiveAddresses(context ReceiveAddressesContext, incomingRoute *router.Route, outgoingRoute *router.Route,
|
||||
peer *peerpkg.Peer) error {
|
||||
|
||||
if !context.AddressManager().NeedMoreAddresses() {
|
||||
return nil
|
||||
}
|
||||
|
||||
subnetworkID := peer.SubnetworkID()
|
||||
msgGetAddresses := domainmessage.NewMsgRequestAddresses(false, subnetworkID)
|
||||
msgGetAddresses := appmessage.NewMsgRequestAddresses(false, subnetworkID)
|
||||
err := outgoingRoute.Enqueue(msgGetAddresses)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -36,9 +32,9 @@ func ReceiveAddresses(context ReceiveAddressesContext, incomingRoute *router.Rou
|
||||
return err
|
||||
}
|
||||
|
||||
msgAddresses := message.(*domainmessage.MsgAddresses)
|
||||
msgAddresses := message.(*appmessage.MsgAddresses)
|
||||
if len(msgAddresses.AddrList) > addressmanager.GetAddressesMax {
|
||||
return protocolerrors.Errorf(true, "address count excceeded %d", addressmanager.GetAddressesMax)
|
||||
return protocolerrors.Errorf(true, "address count exceeded %d", addressmanager.GetAddressesMax)
|
||||
}
|
||||
|
||||
if msgAddresses.IncludeAllSubnetworks {
|
||||
@@ -51,9 +47,6 @@ func ReceiveAddresses(context ReceiveAddressesContext, incomingRoute *router.Rou
|
||||
context.Config().SubnetworkID, msgAddresses.Command(), msgAddresses.SubnetworkID)
|
||||
}
|
||||
|
||||
// TODO(libp2p) Consider adding to peer known addresses set
|
||||
// TODO(libp2p) Replace with real peer IP
|
||||
fakeSourceAddress := new(domainmessage.NetAddress)
|
||||
context.AddressManager().AddAddresses(msgAddresses.AddrList, fakeSourceAddress, msgAddresses.SubnetworkID)
|
||||
context.AddressManager().AddAddresses(msgAddresses.AddrList...)
|
||||
return nil
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
package addressexchange
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/addressmanager"
|
||||
"github.com/kaspanet/kaspad/domainmessage"
|
||||
"github.com/kaspanet/kaspad/netadapter/router"
|
||||
"math/rand"
|
||||
|
||||
"github.com/kaspanet/kaspad/app/appmessage"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/addressmanager"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
||||
)
|
||||
|
||||
// SendAddressesContext is the interface for the context needed for the SendAddresses flow.
|
||||
@@ -14,16 +15,14 @@ type SendAddressesContext interface {
|
||||
|
||||
// SendAddresses sends addresses to a peer that requests it.
|
||||
func SendAddresses(context SendAddressesContext, incomingRoute *router.Route, outgoingRoute *router.Route) error {
|
||||
|
||||
message, err := incomingRoute.Dequeue()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
msgGetAddresses := message.(*domainmessage.MsgRequestAddresses)
|
||||
addresses := context.AddressManager().AddressCache(msgGetAddresses.IncludeAllSubnetworks,
|
||||
msgGetAddresses.SubnetworkID)
|
||||
msgAddresses := domainmessage.NewMsgAddresses(msgGetAddresses.IncludeAllSubnetworks, msgGetAddresses.SubnetworkID)
|
||||
msgGetAddresses := message.(*appmessage.MsgRequestAddresses)
|
||||
addresses := context.AddressManager().Addresses()
|
||||
msgAddresses := appmessage.NewMsgAddresses(msgGetAddresses.IncludeAllSubnetworks, msgGetAddresses.SubnetworkID)
|
||||
err = msgAddresses.AddAddresses(shuffleAddresses(addresses)...)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -33,14 +32,14 @@ func SendAddresses(context SendAddressesContext, incomingRoute *router.Route, ou
|
||||
}
|
||||
|
||||
// shuffleAddresses randomizes the given addresses sent if there are more than the maximum allowed in one message.
|
||||
func shuffleAddresses(addresses []*domainmessage.NetAddress) []*domainmessage.NetAddress {
|
||||
func shuffleAddresses(addresses []*appmessage.NetAddress) []*appmessage.NetAddress {
|
||||
addressCount := len(addresses)
|
||||
|
||||
if addressCount < domainmessage.MaxAddressesPerMsg {
|
||||
if addressCount < appmessage.MaxAddressesPerMsg {
|
||||
return addresses
|
||||
}
|
||||
|
||||
shuffleAddresses := make([]*domainmessage.NetAddress, addressCount)
|
||||
shuffleAddresses := make([]*appmessage.NetAddress, addressCount)
|
||||
copy(shuffleAddresses, addresses)
|
||||
|
||||
rand.Shuffle(addressCount, func(i, j int) {
|
||||
@@ -48,6 +47,6 @@ func shuffleAddresses(addresses []*domainmessage.NetAddress) []*domainmessage.Ne
|
||||
})
|
||||
|
||||
// Truncate it to the maximum size.
|
||||
shuffleAddresses = shuffleAddresses[:domainmessage.MaxAddressesPerMsg]
|
||||
shuffleAddresses = shuffleAddresses[:appmessage.MaxAddressesPerMsg]
|
||||
return shuffleAddresses
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
package blockrelay
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/blockdag"
|
||||
"github.com/kaspanet/kaspad/domainmessage"
|
||||
"github.com/kaspanet/kaspad/netadapter/router"
|
||||
peerpkg "github.com/kaspanet/kaspad/protocol/peer"
|
||||
"github.com/kaspanet/kaspad/protocol/protocolerrors"
|
||||
"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/blockdag"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -14,7 +14,7 @@ type RelayBlockRequestsContext interface {
|
||||
DAG() *blockdag.BlockDAG
|
||||
}
|
||||
|
||||
// HandleRelayBlockRequests listens to domainmessage.MsgRequestRelayBlocks messages and sends
|
||||
// HandleRelayBlockRequests listens to appmessage.MsgRequestRelayBlocks messages and sends
|
||||
// their corresponding blocks to the requesting peer.
|
||||
func HandleRelayBlockRequests(context RelayBlockRequestsContext, incomingRoute *router.Route,
|
||||
outgoingRoute *router.Route, peer *peerpkg.Peer) error {
|
||||
@@ -24,7 +24,7 @@ func HandleRelayBlockRequests(context RelayBlockRequestsContext, incomingRoute *
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
getRelayBlocksMessage := message.(*domainmessage.MsgRequestRelayBlocks)
|
||||
getRelayBlocksMessage := message.(*appmessage.MsgRequestRelayBlocks)
|
||||
for _, hash := range getRelayBlocksMessage.Hashes {
|
||||
// Fetch the block from the database.
|
||||
block, err := context.DAG().BlockByHash(hash)
|
||||
@@ -1,14 +1,14 @@
|
||||
package blockrelay
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/blockdag"
|
||||
"github.com/kaspanet/kaspad/domainmessage"
|
||||
"github.com/kaspanet/kaspad/netadapter"
|
||||
"github.com/kaspanet/kaspad/netadapter/router"
|
||||
"github.com/kaspanet/kaspad/protocol/blocklogger"
|
||||
"github.com/kaspanet/kaspad/protocol/common"
|
||||
peerpkg "github.com/kaspanet/kaspad/protocol/peer"
|
||||
"github.com/kaspanet/kaspad/protocol/protocolerrors"
|
||||
"github.com/kaspanet/kaspad/app/appmessage"
|
||||
"github.com/kaspanet/kaspad/app/protocol/blocklogger"
|
||||
"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/domain/blockdag"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
|
||||
"github.com/kaspanet/kaspad/util"
|
||||
"github.com/kaspanet/kaspad/util/daghash"
|
||||
mathUtil "github.com/kaspanet/kaspad/util/math"
|
||||
@@ -23,17 +23,17 @@ type RelayInvsContext interface {
|
||||
SharedRequestedBlocks() *SharedRequestedBlocks
|
||||
StartIBDIfRequired()
|
||||
IsInIBD() bool
|
||||
Broadcast(message domainmessage.Message) error
|
||||
Broadcast(message appmessage.Message) error
|
||||
}
|
||||
|
||||
type handleRelayInvsFlow struct {
|
||||
RelayInvsContext
|
||||
incomingRoute, outgoingRoute *router.Route
|
||||
peer *peerpkg.Peer
|
||||
invsQueue []*domainmessage.MsgInvRelayBlock
|
||||
invsQueue []*appmessage.MsgInvRelayBlock
|
||||
}
|
||||
|
||||
// HandleRelayInvs listens to domainmessage.MsgInvRelayBlock messages, requests their corresponding blocks if they
|
||||
// HandleRelayInvs listens to appmessage.MsgInvRelayBlock messages, requests their corresponding blocks if they
|
||||
// are missing, adds them to the DAG and propagates them to the rest of the network.
|
||||
func HandleRelayInvs(context RelayInvsContext, incomingRoute *router.Route, outgoingRoute *router.Route,
|
||||
peer *peerpkg.Peer) error {
|
||||
@@ -43,7 +43,7 @@ func HandleRelayInvs(context RelayInvsContext, incomingRoute *router.Route, outg
|
||||
incomingRoute: incomingRoute,
|
||||
outgoingRoute: outgoingRoute,
|
||||
peer: peer,
|
||||
invsQueue: make([]*domainmessage.MsgInvRelayBlock, 0),
|
||||
invsQueue: make([]*appmessage.MsgInvRelayBlock, 0),
|
||||
}
|
||||
return flow.start()
|
||||
}
|
||||
@@ -55,6 +55,8 @@ func (flow *handleRelayInvsFlow) start() error {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugf("Got relay inv for block %s", inv.Hash)
|
||||
|
||||
if flow.DAG().IsKnownBlock(inv.Hash) {
|
||||
if flow.DAG().IsKnownInvalid(inv.Hash) {
|
||||
return protocolerrors.Errorf(true, "sent inv of an invalid block %s",
|
||||
@@ -81,10 +83,10 @@ func (flow *handleRelayInvsFlow) start() error {
|
||||
}
|
||||
}
|
||||
|
||||
func (flow *handleRelayInvsFlow) readInv() (*domainmessage.MsgInvRelayBlock, error) {
|
||||
func (flow *handleRelayInvsFlow) readInv() (*appmessage.MsgInvRelayBlock, error) {
|
||||
|
||||
if len(flow.invsQueue) > 0 {
|
||||
var inv *domainmessage.MsgInvRelayBlock
|
||||
var inv *appmessage.MsgInvRelayBlock
|
||||
inv, flow.invsQueue = flow.invsQueue[0], flow.invsQueue[1:]
|
||||
return inv, nil
|
||||
}
|
||||
@@ -94,7 +96,7 @@ func (flow *handleRelayInvsFlow) readInv() (*domainmessage.MsgInvRelayBlock, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
inv, ok := msg.(*domainmessage.MsgInvRelayBlock)
|
||||
inv, ok := msg.(*appmessage.MsgInvRelayBlock)
|
||||
if !ok {
|
||||
return nil, protocolerrors.Errorf(true, "unexpected %s message in the block relay handleRelayInvsFlow while "+
|
||||
"expecting an inv message", msg.Command())
|
||||
@@ -103,7 +105,7 @@ func (flow *handleRelayInvsFlow) readInv() (*domainmessage.MsgInvRelayBlock, err
|
||||
}
|
||||
|
||||
func (flow *handleRelayInvsFlow) requestBlocks(requestQueue *hashesQueueSet) error {
|
||||
numHashesToRequest := mathUtil.MinInt(domainmessage.MsgRequestRelayBlocksHashes, requestQueue.len())
|
||||
numHashesToRequest := mathUtil.MinInt(appmessage.MsgRequestRelayBlocksHashes, requestQueue.len())
|
||||
hashesToRequest := requestQueue.dequeue(numHashesToRequest)
|
||||
|
||||
pendingBlocks := map[daghash.Hash]struct{}{}
|
||||
@@ -114,6 +116,11 @@ func (flow *handleRelayInvsFlow) requestBlocks(requestQueue *hashesQueueSet) err
|
||||
continue
|
||||
}
|
||||
|
||||
// The block can become known from another peer in the process of orphan resolution
|
||||
if flow.DAG().IsKnownBlock(hash) {
|
||||
continue
|
||||
}
|
||||
|
||||
pendingBlocks[*hash] = struct{}{}
|
||||
filteredHashesToRequest = append(filteredHashesToRequest, hash)
|
||||
}
|
||||
@@ -127,7 +134,7 @@ func (flow *handleRelayInvsFlow) requestBlocks(requestQueue *hashesQueueSet) err
|
||||
// clean from any pending blocks.
|
||||
defer flow.SharedRequestedBlocks().removeSet(pendingBlocks)
|
||||
|
||||
getRelayBlocksMsg := domainmessage.NewMsgRequestRelayBlocks(filteredHashesToRequest)
|
||||
getRelayBlocksMsg := appmessage.NewMsgRequestRelayBlocks(filteredHashesToRequest)
|
||||
err := flow.outgoingRoute.Enqueue(getRelayBlocksMsg)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -153,16 +160,15 @@ func (flow *handleRelayInvsFlow) requestBlocks(requestQueue *hashesQueueSet) err
|
||||
|
||||
delete(pendingBlocks, *blockHash)
|
||||
flow.SharedRequestedBlocks().remove(blockHash)
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// readMsgBlock returns the next msgBlock in msgChan, and populates invsQueue with any inv messages that meanwhile arrive.
|
||||
//
|
||||
// Note: this function assumes msgChan can contain only domainmessage.MsgInvRelayBlock and domainmessage.MsgBlock messages.
|
||||
// Note: this function assumes msgChan can contain only appmessage.MsgInvRelayBlock and appmessage.MsgBlock messages.
|
||||
func (flow *handleRelayInvsFlow) readMsgBlock() (
|
||||
msgBlock *domainmessage.MsgBlock, err error) {
|
||||
msgBlock *appmessage.MsgBlock, err error) {
|
||||
|
||||
for {
|
||||
message, err := flow.incomingRoute.DequeueWithTimeout(common.DefaultTimeout)
|
||||
@@ -171,9 +177,9 @@ func (flow *handleRelayInvsFlow) readMsgBlock() (
|
||||
}
|
||||
|
||||
switch message := message.(type) {
|
||||
case *domainmessage.MsgInvRelayBlock:
|
||||
case *appmessage.MsgInvRelayBlock:
|
||||
flow.invsQueue = append(flow.invsQueue, message)
|
||||
case *domainmessage.MsgBlock:
|
||||
case *appmessage.MsgBlock:
|
||||
return message, nil
|
||||
default:
|
||||
return nil, errors.Errorf("unexpected message %s", message.Command())
|
||||
@@ -190,7 +196,7 @@ func (flow *handleRelayInvsFlow) processAndRelayBlock(requestQueue *hashesQueueS
|
||||
}
|
||||
log.Infof("Rejected block %s from %s: %s", blockHash, flow.peer, err)
|
||||
|
||||
return protocolerrors.Wrap(true, err, "got invalid block")
|
||||
return protocolerrors.Wrapf(true, err, "got invalid block %s from relay", blockHash)
|
||||
}
|
||||
|
||||
if isDelayed {
|
||||
@@ -224,13 +230,7 @@ func (flow *handleRelayInvsFlow) processAndRelayBlock(requestQueue *hashesQueueS
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//TODO(libp2p)
|
||||
//// When the block is not an orphan, log information about it and
|
||||
//// update the DAG state.
|
||||
// sm.restartSyncIfNeeded()
|
||||
//// Clear the rejected transactions.
|
||||
//sm.rejectedTxns = make(map[daghash.TxID]struct{})
|
||||
err = flow.Broadcast(domainmessage.NewMsgInvBlock(blockHash))
|
||||
err = flow.Broadcast(appmessage.NewMsgInvBlock(blockHash))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user