mirror of
https://github.com/kaspanet/kaspad.git
synced 2026-02-26 21:23:15 +00:00
Compare commits
448 Commits
v0.6.2-dev
...
optimize-u
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5f2495522 | ||
|
|
8588774837 | ||
|
|
94c3f4b80c | ||
|
|
a5a84e9215 | ||
|
|
1cec4c91cf | ||
|
|
3c0b74208a | ||
|
|
08d983b84a | ||
|
|
c9b591f2d3 | ||
|
|
8d6e71d490 | ||
|
|
2823461fe2 | ||
|
|
2075c585da | ||
|
|
01aee62cb0 | ||
|
|
a6ee871f7e | ||
|
|
6393a8186a | ||
|
|
3916534a7e | ||
|
|
0561347ff1 | ||
|
|
fb11981da1 | ||
|
|
1742e76af7 | ||
|
|
ddfe376388 | ||
|
|
52da65077a | ||
|
|
ed85f09742 | ||
|
|
819ec9f2a7 | ||
|
|
7ea8a72a9e | ||
|
|
ca04c049ab | ||
|
|
9a17198e7d | ||
|
|
756f40c59a | ||
|
|
6a03d31f98 | ||
|
|
319ab6cfcd | ||
|
|
abef96e3de | ||
|
|
2e0bc0f8c4 | ||
|
|
acf5423c63 | ||
|
|
effb545d20 | ||
|
|
ad9c213a06 | ||
|
|
a4adbabf96 | ||
|
|
799eb7515c | ||
|
|
0769705b37 | ||
|
|
189e3b6be9 | ||
|
|
e8dfbc8367 | ||
|
|
d70740331a | ||
|
|
9a81b1328a | ||
|
|
d4f3a252ff | ||
|
|
f14527de4c | ||
|
|
dd57e6abe6 | ||
|
|
67be4d82bf | ||
|
|
a1381d6768 | ||
|
|
10b519a3e2 | ||
|
|
a35f8269ea | ||
|
|
15af6641fc | ||
|
|
1b97cfb302 | ||
|
|
61be80a60c | ||
|
|
83134cc2b5 | ||
|
|
4988817da1 | ||
|
|
68bd8330ac | ||
|
|
192dd2ba8f | ||
|
|
cc49b1826a | ||
|
|
ce348373c6 | ||
|
|
8ad5725421 | ||
|
|
23a2fbf401 | ||
|
|
c1361e5b3e | ||
|
|
53744ceb45 | ||
|
|
bcf2302460 | ||
|
|
6101e6bdb6 | ||
|
|
d9b97afb92 | ||
|
|
b8ca33d91d | ||
|
|
c7deda41c6 | ||
|
|
434cf45112 | ||
|
|
2cc0bf1639 | ||
|
|
0f2d0d45b5 | ||
|
|
09e1a73340 | ||
|
|
c6d20c1f6f | ||
|
|
49e0a2a2e7 | ||
|
|
285ae5cd40 | ||
|
|
541205904e | ||
|
|
256b7f25f1 | ||
|
|
82d95c59a3 | ||
|
|
79c5d4595e | ||
|
|
b195301a99 | ||
|
|
4ad89056c2 | ||
|
|
64f6cd2178 | ||
|
|
26368cd674 | ||
|
|
9ea4c0fa38 | ||
|
|
a04a5462ae | ||
|
|
4577023e44 | ||
|
|
d8293ef635 | ||
|
|
2059d6ba56 | ||
|
|
3ec1cbe236 | ||
|
|
741e0962be | ||
|
|
6279db2bf1 | ||
|
|
e24bc527f3 | ||
|
|
8a309a7d2a | ||
|
|
70d515a5a9 | ||
|
|
72a7ca53e6 | ||
|
|
119e7374e1 | ||
|
|
e509cb1597 | ||
|
|
0fb97a4f37 | ||
|
|
789a7379bd | ||
|
|
778375c4af | ||
|
|
acef311fb4 | ||
|
|
e8cad2b2f3 | ||
|
|
97fddeff4b | ||
|
|
d6fe9a3017 | ||
|
|
1abffd472c | ||
|
|
8c8da3b01f | ||
|
|
51625e7967 | ||
|
|
6fa3aa1dca | ||
|
|
23304a4977 | ||
|
|
b473a09111 | ||
|
|
dd35669861 | ||
|
|
9401b77a4f | ||
|
|
e87368157d | ||
|
|
7dd0188838 | ||
|
|
6172e48adc | ||
|
|
739cffd918 | ||
|
|
bd89ca2125 | ||
|
|
d917a1fc1e | ||
|
|
9b12b9c58a | ||
|
|
533fa8c00e | ||
|
|
0f93189c16 | ||
|
|
52427cb953 | ||
|
|
d72f70fabe | ||
|
|
49b6cc6038 | ||
|
|
c10a087696 | ||
|
|
02d5fb29cf | ||
|
|
48278bd1c0 | ||
|
|
d91afbfe3b | ||
|
|
5f22632836 | ||
|
|
4aafe8a630 | ||
|
|
7e379028f3 | ||
|
|
af1b8c8490 | ||
|
|
c7c8b25c09 | ||
|
|
b0251fe1a6 | ||
|
|
cfe013eca7 | ||
|
|
50e74bf412 | ||
|
|
12f1c3dfab | ||
|
|
a231ec7214 | ||
|
|
8aecf961bc | ||
|
|
0dea766373 | ||
|
|
830ddf4735 | ||
|
|
9d0f513e49 | ||
|
|
bd97075e07 | ||
|
|
05941a76e7 | ||
|
|
7cbda3b018 | ||
|
|
a0b93e1230 | ||
|
|
b749b2db0b | ||
|
|
717914319a | ||
|
|
6ef8eaf133 | ||
|
|
273c271771 | ||
|
|
729e3db145 | ||
|
|
43c00f5e7f | ||
|
|
90d4dbcba1 | ||
|
|
cb9d7e313d | ||
|
|
c2cec2f170 | ||
|
|
e7edfaceb7 | ||
|
|
5632bee49d | ||
|
|
21a459c0f4 | ||
|
|
45edacfbfa | ||
|
|
9f8f0fd747 | ||
|
|
053bb351b5 | ||
|
|
843edc4ba5 | ||
|
|
bd5f4e8c6a | ||
|
|
6b1e691a57 | ||
|
|
bf67c6351e | ||
|
|
99a14c5999 | ||
|
|
b510fc08a7 | ||
|
|
dc3ae4d3ac | ||
|
|
1ebda36b17 | ||
|
|
12379bedb6 | ||
|
|
f90d7d796a | ||
|
|
fddda46d4f | ||
|
|
77adb6c99f | ||
|
|
48e1a2c396 | ||
|
|
6926a7ab81 | ||
|
|
a9e0c33e5c | ||
|
|
2c1688909d | ||
|
|
6714e084e9 | ||
|
|
3354ac67c8 | ||
|
|
0d8f7bba40 | ||
|
|
e04f76b800 | ||
|
|
82fa8e6831 | ||
|
|
b7ca3f4461 | ||
|
|
37bf261da1 | ||
|
|
d90e18ec51 | ||
|
|
9962527793 | ||
|
|
78550d3639 | ||
|
|
7f899b0d09 | ||
|
|
4886425caf | ||
|
|
c3902ed7a8 | ||
|
|
33eaf9edac | ||
|
|
f97b8f7580 | ||
|
|
05979de705 | ||
|
|
32a04d1811 | ||
|
|
a585f32763 | ||
|
|
9866abb75a | ||
|
|
ab3c81c552 | ||
|
|
9756d64f28 | ||
|
|
21fc2d4219 | ||
|
|
f1c6df48c9 | ||
|
|
80c445c78b | ||
|
|
3b6eb73e53 | ||
|
|
f407c44a8d | ||
|
|
a1af992d15 | ||
|
|
048caebda3 | ||
|
|
baa4311a34 | ||
|
|
f6dfce8180 | ||
|
|
0e91b44fc6 | ||
|
|
f7fa823f17 | ||
|
|
546ea83123 | ||
|
|
f9c2137344 | ||
|
|
0fa13357c3 | ||
|
|
5b2fae0457 | ||
|
|
3bad9ec1eb | ||
|
|
45d9b63572 | ||
|
|
afc634d871 | ||
|
|
2334f8b4eb | ||
|
|
d65f382c80 | ||
|
|
2096a28d1c | ||
|
|
96d9e5800f | ||
|
|
8264369c81 | ||
|
|
bb2d7f72ac | ||
|
|
c1505b4748 | ||
|
|
dec9ef5f75 | ||
|
|
5211727206 | ||
|
|
fafe1d534f | ||
|
|
c56a5336f3 | ||
|
|
b3a3121725 | ||
|
|
950dd0cc8d | ||
|
|
bb244706ea | ||
|
|
ed386bbc8f | ||
|
|
75d21d39cc | ||
|
|
3f92ddd827 | ||
|
|
8500acd86b | ||
|
|
5b037950d8 | ||
|
|
184911f76e | ||
|
|
7479f5f5e8 | ||
|
|
891095563e | ||
|
|
60c24d8dea | ||
|
|
d4993c1d06 | ||
|
|
c785ca0e52 | ||
|
|
9eb5c4a0ed | ||
|
|
9d5d1b02dc | ||
|
|
213be67c47 | ||
|
|
14d7ab5fc6 | ||
|
|
7224d58940 | ||
|
|
b2188f5993 | ||
|
|
dbd15aecf5 | ||
|
|
66f5a5bd7d | ||
|
|
c994200878 | ||
|
|
7050ebeac9 | ||
|
|
f2df48139f | ||
|
|
48d8137604 | ||
|
|
310cf0bb9b | ||
|
|
b6c47fdd21 | ||
|
|
e6a2b7366f | ||
|
|
d8f72e2b27 | ||
|
|
08749deaeb | ||
|
|
83a88d9989 | ||
|
|
151910c27a | ||
|
|
fca8ed57bd | ||
|
|
56679818be | ||
|
|
f07f2edad2 | ||
|
|
2dcfe90850 | ||
|
|
dc80a39c54 | ||
|
|
34be898491 | ||
|
|
f4a2fbf64f | ||
|
|
a0c6076ccc | ||
|
|
fddce00d08 | ||
|
|
ae682d59f7 | ||
|
|
347f3de15c | ||
|
|
a34091991a | ||
|
|
efe1986a56 | ||
|
|
3ab507b66f | ||
|
|
afbad73c0b | ||
|
|
a1fa17d872 | ||
|
|
b50421beee | ||
|
|
aeded07815 | ||
|
|
7d14f24b84 | ||
|
|
c52b8100c6 | ||
|
|
f52cddc25c | ||
|
|
fc5e39f6cc | ||
|
|
8ccf381fc7 | ||
|
|
f320887bff | ||
|
|
eef5e3768c | ||
|
|
7a7821e1c8 | ||
|
|
37fbdcb453 | ||
|
|
135ffbd4f2 | ||
|
|
4736213ba4 | ||
|
|
8290fadd3a | ||
|
|
23c1ea6c31 | ||
|
|
31c5264430 | ||
|
|
32da4440ba | ||
|
|
e7a61c7edf | ||
|
|
6db337c8c5 | ||
|
|
2282e36196 | ||
|
|
72b5832f30 | ||
|
|
9a344152aa | ||
|
|
281944762d | ||
|
|
e3be67c3c7 | ||
|
|
215ab512cd | ||
|
|
d0fc728c23 | ||
|
|
1c710daf98 | ||
|
|
5566aaf95a | ||
|
|
52c73d3a08 | ||
|
|
baf8d25656 | ||
|
|
2eb0d946e5 | ||
|
|
ce95c6dc9d | ||
|
|
6a46cb2be6 | ||
|
|
f06dc7ea90 | ||
|
|
7f2ef708a6 | ||
|
|
4ab2e0d498 | ||
|
|
ca9161024f | ||
|
|
8dc246a2a7 | ||
|
|
c7f2de73df | ||
|
|
3f979399b1 | ||
|
|
2abd4a274b | ||
|
|
c5707f64dc | ||
|
|
62bb841e89 | ||
|
|
23cccb6396 | ||
|
|
87ad9dfc59 | ||
|
|
c59adaa4db | ||
|
|
14fbe50636 | ||
|
|
d3ede3a46f | ||
|
|
01c7c67aed | ||
|
|
971d50b684 | ||
|
|
9cf1557c37 | ||
|
|
126e2e49bb | ||
|
|
c88266afed | ||
|
|
7402f3fb0e | ||
|
|
eae8bce941 | ||
|
|
8c0275421a | ||
|
|
a436b30ebf | ||
|
|
a132f55302 | ||
|
|
be56fb7e8b | ||
|
|
4fbe130592 | ||
|
|
ed6d8243ef | ||
|
|
03790ad8a2 | ||
|
|
97b5b0b875 | ||
|
|
f62183473c | ||
|
|
aeb4b96560 | ||
|
|
b413760136 | ||
|
|
45882343e6 | ||
|
|
4c1f24da82 | ||
|
|
8c63835971 | ||
|
|
a96a5fd2ef | ||
|
|
9a62fae012 | ||
|
|
81a10e9f89 | ||
|
|
db475bd511 | ||
|
|
eef5f27a87 | ||
|
|
790dc74581 | ||
|
|
4f36accd81 | ||
|
|
04ead57731 | ||
|
|
e9951bc34a | ||
|
|
74d13e271e | ||
|
|
9181481fc8 | ||
|
|
62ddd8fe1c | ||
|
|
7891f73cb0 | ||
|
|
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 | ||
|
|
a361d62945 | ||
|
|
1927e81202 | ||
|
|
8a4ece1101 | ||
|
|
0bf1052abf | ||
|
|
2af03c1ccf | ||
|
|
a2aa58c8a4 | ||
|
|
7e74fc0b2b | ||
|
|
0653e59e16 | ||
|
|
32463ce906 | ||
|
|
23a3594c18 | ||
|
|
ca3172dad0 | ||
|
|
22dc3f998f | ||
|
|
aac173ed72 | ||
|
|
5f3fb0bf9f | ||
|
|
61f383a713 | ||
|
|
c62bdb2fa1 | ||
|
|
c88869778d | ||
|
|
3fd647b291 | ||
|
|
2f255952b7 |
9
.codecov.yml
Normal file
9
.codecov.yml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
coverage:
|
||||||
|
status:
|
||||||
|
patch: off
|
||||||
|
|
||||||
|
project:
|
||||||
|
default:
|
||||||
|
informational: true
|
||||||
|
ignore:
|
||||||
|
- "**/*.pb.go" # Ignore all auto generated protobuf structures.
|
||||||
196
.github/workflows/SetPageFileSize.ps1
vendored
Normal file
196
.github/workflows/SetPageFileSize.ps1
vendored
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
<#
|
||||||
|
# MIT License (MIT) Copyright (c) 2020 Maxim Lobanov and contributors
|
||||||
|
# Source: https://github.com/al-cheb/configure-pagefile-action/blob/master/scripts/SetPageFileSize.ps1
|
||||||
|
.SYNOPSIS
|
||||||
|
Configure Pagefile on Windows machine
|
||||||
|
.NOTES
|
||||||
|
Author: Aleksandr Chebotov
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
SetPageFileSize.ps1 -MinimumSize 4GB -MaximumSize 8GB -DiskRoot "D:"
|
||||||
|
#>
|
||||||
|
|
||||||
|
param(
|
||||||
|
[System.UInt64] $MinimumSize = 8gb ,
|
||||||
|
[System.UInt64] $MaximumSize = 8gb ,
|
||||||
|
[System.String] $DiskRoot = "D:"
|
||||||
|
)
|
||||||
|
|
||||||
|
# https://referencesource.microsoft.com/#System.IdentityModel/System/IdentityModel/NativeMethods.cs,619688d876febbe1
|
||||||
|
# https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/mm/modwrite/create.htm
|
||||||
|
# https://referencesource.microsoft.com/#mscorlib/microsoft/win32/safehandles/safefilehandle.cs,9b08210f3be75520
|
||||||
|
# https://referencesource.microsoft.com/#mscorlib/system/security/principal/tokenaccesslevels.cs,6eda91f498a38586
|
||||||
|
# https://www.autoitscript.com/forum/topic/117993-api-ntcreatepagingfile/
|
||||||
|
|
||||||
|
$source = @'
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Security.Principal;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
using Microsoft.Win32.SafeHandles;
|
||||||
|
|
||||||
|
namespace Util
|
||||||
|
{
|
||||||
|
class NativeMethods
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct LUID
|
||||||
|
{
|
||||||
|
internal uint LowPart;
|
||||||
|
internal uint HighPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct LUID_AND_ATTRIBUTES
|
||||||
|
{
|
||||||
|
internal LUID Luid;
|
||||||
|
internal uint Attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
internal struct TOKEN_PRIVILEGE
|
||||||
|
{
|
||||||
|
internal uint PrivilegeCount;
|
||||||
|
internal LUID_AND_ATTRIBUTES Privilege;
|
||||||
|
|
||||||
|
internal static readonly uint Size = (uint)Marshal.SizeOf(typeof(TOKEN_PRIVILEGE));
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||||
|
internal struct UNICODE_STRING
|
||||||
|
{
|
||||||
|
internal UInt16 length;
|
||||||
|
internal UInt16 maximumLength;
|
||||||
|
internal string buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", SetLastError=true)]
|
||||||
|
internal static extern IntPtr LocalFree(IntPtr handle);
|
||||||
|
|
||||||
|
[DllImport("advapi32.dll", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true, PreserveSig = false)]
|
||||||
|
internal static extern bool LookupPrivilegeValueW(
|
||||||
|
[In] string lpSystemName,
|
||||||
|
[In] string lpName,
|
||||||
|
[Out] out LUID luid
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("advapi32.dll", SetLastError = true, PreserveSig = false)]
|
||||||
|
internal static extern bool AdjustTokenPrivileges(
|
||||||
|
[In] SafeCloseHandle tokenHandle,
|
||||||
|
[In] bool disableAllPrivileges,
|
||||||
|
[In] ref TOKEN_PRIVILEGE newState,
|
||||||
|
[In] uint bufferLength,
|
||||||
|
[Out] out TOKEN_PRIVILEGE previousState,
|
||||||
|
[Out] out uint returnLength
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true, PreserveSig = false)]
|
||||||
|
internal static extern bool OpenProcessToken(
|
||||||
|
[In] IntPtr processToken,
|
||||||
|
[In] int desiredAccess,
|
||||||
|
[Out] out SafeCloseHandle tokenHandle
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("ntdll.dll", CharSet = CharSet.Unicode, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
|
||||||
|
internal static extern Int32 NtCreatePagingFile(
|
||||||
|
[In] ref UNICODE_STRING pageFileName,
|
||||||
|
[In] ref Int64 minimumSize,
|
||||||
|
[In] ref Int64 maximumSize,
|
||||||
|
[In] UInt32 flags
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||||
|
internal static extern uint QueryDosDeviceW(
|
||||||
|
string lpDeviceName,
|
||||||
|
StringBuilder lpTargetPath,
|
||||||
|
int ucchMax
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class SafeCloseHandle: SafeHandleZeroOrMinusOneIsInvalid
|
||||||
|
{
|
||||||
|
[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)]
|
||||||
|
internal extern static bool CloseHandle(IntPtr handle);
|
||||||
|
|
||||||
|
private SafeCloseHandle() : base(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public SafeCloseHandle(IntPtr preexistingHandle, bool ownsHandle) : base(ownsHandle)
|
||||||
|
{
|
||||||
|
SetHandle(preexistingHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
override protected bool ReleaseHandle()
|
||||||
|
{
|
||||||
|
return CloseHandle(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PageFile
|
||||||
|
{
|
||||||
|
public static void SetPageFileSize(long minimumValue, long maximumValue, string lpDeviceName)
|
||||||
|
{
|
||||||
|
SetPageFilePrivilege();
|
||||||
|
StringBuilder lpTargetPath = new StringBuilder(260);
|
||||||
|
|
||||||
|
UInt32 resultQueryDosDevice = NativeMethods.QueryDosDeviceW(lpDeviceName, lpTargetPath, lpTargetPath.Capacity);
|
||||||
|
if (resultQueryDosDevice == 0)
|
||||||
|
{
|
||||||
|
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||||
|
}
|
||||||
|
|
||||||
|
string pageFilePath = lpTargetPath.ToString() + "\\pagefile.sys";
|
||||||
|
|
||||||
|
NativeMethods.UNICODE_STRING pageFileName = new NativeMethods.UNICODE_STRING
|
||||||
|
{
|
||||||
|
length = (ushort)(pageFilePath.Length * 2),
|
||||||
|
maximumLength = (ushort)(2 * (pageFilePath.Length + 1)),
|
||||||
|
buffer = pageFilePath
|
||||||
|
};
|
||||||
|
|
||||||
|
Int32 resultNtCreatePagingFile = NativeMethods.NtCreatePagingFile(ref pageFileName, ref minimumValue, ref maximumValue, 0);
|
||||||
|
if (resultNtCreatePagingFile != 0)
|
||||||
|
{
|
||||||
|
throw new Win32Exception(Marshal.GetLastWin32Error());
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("PageFile: {0} / {1} bytes for {2}", minimumValue, maximumValue, pageFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetPageFilePrivilege()
|
||||||
|
{
|
||||||
|
const int SE_PRIVILEGE_ENABLED = 0x00000002;
|
||||||
|
const int AdjustPrivileges = 0x00000020;
|
||||||
|
const int Query = 0x00000008;
|
||||||
|
|
||||||
|
NativeMethods.LUID luid;
|
||||||
|
NativeMethods.LookupPrivilegeValueW(null, "SeCreatePagefilePrivilege", out luid);
|
||||||
|
|
||||||
|
SafeCloseHandle hToken;
|
||||||
|
NativeMethods.OpenProcessToken(
|
||||||
|
Process.GetCurrentProcess().Handle,
|
||||||
|
AdjustPrivileges | Query,
|
||||||
|
out hToken
|
||||||
|
);
|
||||||
|
|
||||||
|
NativeMethods.TOKEN_PRIVILEGE previousState;
|
||||||
|
NativeMethods.TOKEN_PRIVILEGE newState;
|
||||||
|
uint previousSize = 0;
|
||||||
|
newState.PrivilegeCount = 1;
|
||||||
|
newState.Privilege.Luid = luid;
|
||||||
|
newState.Privilege.Attributes = SE_PRIVILEGE_ENABLED;
|
||||||
|
|
||||||
|
NativeMethods.AdjustTokenPrivileges(hToken, false, ref newState, NativeMethods.TOKEN_PRIVILEGE.Size, out previousState, out previousSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'@
|
||||||
|
|
||||||
|
Add-Type -TypeDefinition $source
|
||||||
|
|
||||||
|
# Set SetPageFileSize
|
||||||
|
[Util.PageFile]::SetPageFileSize($minimumSize, $maximumSize, $diskRoot)
|
||||||
70
.github/workflows/go.yml
vendored
Normal file
70
.github/workflows/go.yml
vendored
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
name: Go
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
# edtited - "title, body, or the base branch of the PR is modified"
|
||||||
|
# synchronize - "commit(s) pushed to the pull request"
|
||||||
|
types: [opened, synchronize, edited, reopened]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ ubuntu-16.04, macos-10.15 ]
|
||||||
|
name: Testing on on ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Fix windows CRLF
|
||||||
|
run: git config --global core.autocrlf false
|
||||||
|
|
||||||
|
- name: Check out code into the Go module directory
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
# We need to increase the page size because the tests run out of memory on github CI windows.
|
||||||
|
# Use the powershell script from this github action: https://github.com/al-cheb/configure-pagefile-action/blob/master/scripts/SetPageFileSize.ps1
|
||||||
|
# MIT License (MIT) Copyright (c) 2020 Maxim Lobanov and contributors
|
||||||
|
- name: Increase page size on windows
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
shell: powershell
|
||||||
|
run: powershell -command .\.github\workflows\SetPageFileSize.ps1
|
||||||
|
|
||||||
|
|
||||||
|
- name: Set up Go 1.x
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: 1.14
|
||||||
|
|
||||||
|
|
||||||
|
# Source: https://github.com/actions/cache/blob/main/examples.md#go---modules
|
||||||
|
- name: Go Cache
|
||||||
|
uses: actions/cache@v2
|
||||||
|
with:
|
||||||
|
path: ~/go/pkg/mod
|
||||||
|
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-go-
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
shell: bash
|
||||||
|
run: ./build_and_test.sh
|
||||||
|
|
||||||
|
coverage:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
name: Produce code coverage
|
||||||
|
steps:
|
||||||
|
- name: Check out code into the Go module directory
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Set up Go 1.x
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: 1.14
|
||||||
|
|
||||||
|
- name: Create coverage file
|
||||||
|
# Because of https://github.com/golang/go/issues/27333 this seem to "fail" even though nothing is wrong, so ignore the failure
|
||||||
|
run: go test -json -covermode=atomic -coverpkg=./... -coverprofile coverage.txt ./... || true
|
||||||
|
|
||||||
|
- name: Upload coverage file
|
||||||
|
run: bash <(curl -s https://codecov.io/bash)
|
||||||
18
.gitignore
vendored
18
.gitignore
vendored
@@ -13,6 +13,21 @@ kaspad.db
|
|||||||
*.o
|
*.o
|
||||||
*.a
|
*.a
|
||||||
*.so
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test binary, built with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Real binaries, build with `go build .`
|
||||||
|
kaspad
|
||||||
|
cmd/gencerts/gencerts
|
||||||
|
cmd/kaspactl/kaspactl
|
||||||
|
cmd/kasminer/kaspaminer
|
||||||
|
*.exe
|
||||||
|
*.exe~
|
||||||
|
|
||||||
|
# Output of the go coverage tool
|
||||||
|
*.out
|
||||||
|
|
||||||
# Folders
|
# Folders
|
||||||
_obj
|
_obj
|
||||||
@@ -31,8 +46,7 @@ _cgo_export.*
|
|||||||
|
|
||||||
_testmain.go
|
_testmain.go
|
||||||
|
|
||||||
*.exe
|
|
||||||
|
|
||||||
# IDE
|
# IDE
|
||||||
.idea
|
.idea
|
||||||
.vscode
|
.vscode
|
||||||
|
|||||||
19
CONTRIBUTING.md
Normal file
19
CONTRIBUTING.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Contributing to Kaspad
|
||||||
|
|
||||||
|
Any contribution to Kaspad is very welcome.
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
|
If you want to start contributing to Kaspad and don't know where to start, you can pick an issue from
|
||||||
|
the [list](https://github.com/kaspanet/kaspad/issues).
|
||||||
|
|
||||||
|
If you want to make a big change it's better to discuss it first by opening an issue or talk about it in
|
||||||
|
[Discord](https://discord.gg/WmGhhzk) to avoid duplicate work.
|
||||||
|
|
||||||
|
## Pull Request process
|
||||||
|
|
||||||
|
Any pull request should be opened against the development branch of the target version. The development branch format is
|
||||||
|
as follows: `vx.y.z-dev`, for example: `v0.8.5-dev`.
|
||||||
|
|
||||||
|
All pull requests should pass the checks written in `build_and_test.sh`, so it's recommended to run this script before
|
||||||
|
submitting your PR.
|
||||||
29
README.md
29
README.md
@@ -9,12 +9,16 @@ Warning: This is pre-alpha software. There's no guarantee anything works.
|
|||||||
|
|
||||||
Kaspad is the reference full node Kaspa implementation written in Go (golang).
|
Kaspad is the reference full node Kaspa implementation written in Go (golang).
|
||||||
|
|
||||||
This project is currently under active development and is in a pre-Alpha state.
|
This project is currently under active development and is in a pre-Alpha state.
|
||||||
Some things still don't work and APIs are far from finalized. The code is provided for reference only.
|
Some things still don't work and APIs are far from finalized. The code is provided for reference only.
|
||||||
|
|
||||||
|
## What is kaspa
|
||||||
|
|
||||||
|
Kaspa is an attempt at a proof-of-work cryptocurrency with instant confirmations and sub-second block times. It is based on [the PHANTOM protocol](https://eprint.iacr.org/2018/104.pdf), a generalization of Nakamoto consensus.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
Latest version of [Go](http://golang.org) (currently 1.13).
|
Go 1.14 or later.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@@ -27,25 +31,17 @@ Latest version of [Go](http://golang.org) (currently 1.13).
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ go version
|
$ go version
|
||||||
$ go env GOROOT GOPATH
|
|
||||||
```
|
```
|
||||||
|
|
||||||
NOTE: The `GOROOT` and `GOPATH` above must not be the same path. It is
|
|
||||||
recommended that `GOPATH` is set to a directory in your home directory such as
|
|
||||||
`~/dev/go` to avoid write permission issues. It is also recommended to add
|
|
||||||
`$GOPATH/bin` to your `PATH` at this point.
|
|
||||||
|
|
||||||
- Run the following commands to obtain and install kaspad including all dependencies:
|
- Run the following commands to obtain and install kaspad including all dependencies:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ git clone https://github.com/kaspanet/kaspad $GOPATH/src/github.com/kaspanet/kaspad
|
$ git clone https://github.com/kaspanet/kaspad
|
||||||
$ cd $GOPATH/src/github.com/kaspanet/kaspad
|
$ cd kaspad
|
||||||
$ ./test.sh
|
|
||||||
$ go install . ./cmd/...
|
$ 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
|
- Kaspad (and utilities) should now be installed in `$(go env GOPATH)/bin`. If you did
|
||||||
not already add the bin directory to your system path during Go installation,
|
not already add the bin directory to your system path during Go installation,
|
||||||
you are encouraged to do so now.
|
you are encouraged to do so now.
|
||||||
|
|
||||||
@@ -55,10 +51,8 @@ $ go install . ./cmd/...
|
|||||||
Kaspad has several configuration options available to tweak how it runs, but all
|
Kaspad has several configuration options available to tweak how it runs, but all
|
||||||
of the basic operations work with zero configuration.
|
of the basic operations work with zero configuration.
|
||||||
|
|
||||||
#### Linux/BSD/POSIX/Source
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ ./kaspad
|
$ kaspad
|
||||||
```
|
```
|
||||||
|
|
||||||
## Discord
|
## Discord
|
||||||
@@ -71,9 +65,8 @@ is used for this project.
|
|||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
The documentation is a work-in-progress. It is located in the [docs](https://github.com/kaspanet/kaspad/tree/master/docs) folder.
|
The documentation is a work-in-progress.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Kaspad is licensed under the copyfree [ISC License](https://choosealicense.com/licenses/isc/).
|
Kaspad is licensed under the copyfree [ISC License](https://choosealicense.com/licenses/isc/).
|
||||||
|
|
||||||
|
|||||||
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.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
362
app/app.go
362
app/app.go
@@ -2,248 +2,184 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync/atomic"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/addressmanager"
|
"github.com/kaspanet/kaspad/infrastructure/db/database"
|
||||||
|
"github.com/kaspanet/kaspad/infrastructure/db/database/ldb"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/netadapter/id"
|
"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/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
|
var desiredLimits = &limits.DesiredLimits{
|
||||||
type App struct {
|
FileLimitWant: 2048,
|
||||||
cfg *config.Config
|
FileLimitMin: 1024,
|
||||||
rpcServer *rpc.Server
|
|
||||||
addressManager *addressmanager.AddressManager
|
|
||||||
protocolManager *protocol.Manager
|
|
||||||
connectionManager *connmanager.ConnectionManager
|
|
||||||
netAdapter *netadapter.NetAdapter
|
|
||||||
|
|
||||||
started, shutdown int32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start launches all the kaspad services.
|
var serviceDescription = &winservice.ServiceDescription{
|
||||||
func (a *App) Start() {
|
Name: "kaspadsvc",
|
||||||
// Already started?
|
DisplayName: "Kaspad Service",
|
||||||
if atomic.AddInt32(&a.started, 1) != 1 {
|
Description: "Downloads and stays synchronized with the Kaspa blockDAG and " +
|
||||||
return
|
"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 {
|
if err != nil {
|
||||||
panics.Exit(log, fmt.Sprintf("Error starting the p2p protocol: %+v", err))
|
fmt.Fprintln(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()
|
return app.main(nil)
|
||||||
|
|
||||||
a.connectionManager.Start()
|
|
||||||
|
|
||||||
if !a.cfg.DisableRPC {
|
|
||||||
a.rpcServer.Start()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop gracefully shuts down all the kaspad services.
|
func (app *kaspadApp) main(startedChan chan<- struct{}) error {
|
||||||
func (a *App) Stop() error {
|
// Get a channel that will be closed when a shutdown signal has been
|
||||||
// Make sure this only happens once.
|
// triggered either from an OS signal such as SIGINT (Ctrl+C) or from
|
||||||
if atomic.AddInt32(&a.shutdown, 1) != 1 {
|
// another subsystem such as the RPC server.
|
||||||
log.Infof("Kaspad is already in the process of shutting down")
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Warnf("Kaspad shutting down")
|
if app.cfg.ResetDatabase {
|
||||||
|
err := removeDatabase(app.cfg)
|
||||||
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 err != nil {
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new App instance configured to listen on addr for the
|
// doUpgrades performs upgrades to kaspad as new versions require it.
|
||||||
// kaspa network type specified by dagParams. Use start to begin accepting
|
// currently it's a placeholder we got from kaspad upstream, that does nothing
|
||||||
// connections from peers.
|
func doUpgrades() error {
|
||||||
func New(cfg *config.Config, databaseContext *dbaccess.DatabaseContext, interrupt <-chan struct{}) (*App, error) {
|
return nil
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) maybeSeedFromDNS() {
|
// dbPath returns the path to the block database given a database type.
|
||||||
if !a.cfg.DisableDNSSeed {
|
func databasePath(cfg *config.Config) string {
|
||||||
dnsseed.SeedFromDNS(a.cfg.NetParams(), a.cfg.DNSSeed, domainmessage.SFNodeNetwork, false, nil,
|
return filepath.Join(cfg.DataDir, "db")
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupIndexes(cfg *config.Config) (blockdag.IndexManager, *indexers.AcceptanceIndex) {
|
func removeDatabase(cfg *config.Config) error {
|
||||||
// Create indexes if needed.
|
dbPath := databasePath(cfg)
|
||||||
var indexes []indexers.Indexer
|
return os.RemoveAll(dbPath)
|
||||||
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 {
|
func openDB(cfg *config.Config) (database.Database, error) {
|
||||||
mempoolConfig := mempool.Config{
|
dbPath := databasePath(cfg)
|
||||||
Policy: mempool.Policy{
|
log.Infof("Loading database from '%s'", dbPath)
|
||||||
AcceptNonStd: cfg.RelayNonStd,
|
return ldb.NewLevelDB(dbPath)
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
// Reads and validates the next kaspa message from conn using the
|
||||||
// protocol version pver and the kaspa network kaspanet. The returns
|
// 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.
|
// raw payload, and a possible error.
|
||||||
msg, rawPayload, err := wire.ReadMessage(conn, pver, kaspanet)
|
msg, rawPayload, err := wire.ReadMessage(conn, pver, kaspanet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
20
app/appmessage/common.go
Normal file
20
app/appmessage/common.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// 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 (
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MaxInvPerMsg is the maximum number of inventory vectors that can be in any type of kaspa inv message.
|
||||||
|
const MaxInvPerMsg = 1 << 17
|
||||||
|
|
||||||
|
// errNonCanonicalVarInt is the common format string used for non-canonically
|
||||||
|
// encoded variable length integer errors.
|
||||||
|
var errNonCanonicalVarInt = "non-canonical varint %x - discriminant %x must " +
|
||||||
|
"encode a value greater than %x"
|
||||||
|
|
||||||
|
// errNoEncodingForType signifies that there's no encoding for the given type.
|
||||||
|
var errNoEncodingForType = errors.New("there's no encoding for this type")
|
||||||
44
app/appmessage/common_test.go
Normal file
44
app/appmessage/common_test.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
|
||||||
|
// mainnetGenesisHash is the hash of the first block in the block DAG for the
|
||||||
|
// main network (genesis block).
|
||||||
|
var mainnetGenesisHash = externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||||
|
0xdc, 0x5f, 0x5b, 0x5b, 0x1d, 0xc2, 0xa7, 0x25,
|
||||||
|
0x49, 0xd5, 0x1d, 0x4d, 0xee, 0xd7, 0xa4, 0x8b,
|
||||||
|
0xaf, 0xd3, 0x14, 0x4b, 0x56, 0x78, 0x98, 0xb1,
|
||||||
|
0x8c, 0xfd, 0x9f, 0x69, 0xdd, 0xcf, 0xbb, 0x63,
|
||||||
|
})
|
||||||
|
|
||||||
|
// simnetGenesisHash is the hash of the first block in the block DAG for the
|
||||||
|
// simulation test network.
|
||||||
|
var simnetGenesisHash = externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||||
|
0x9d, 0x89, 0xb0, 0x6e, 0xb3, 0x47, 0xb5, 0x6e,
|
||||||
|
0xcd, 0x6c, 0x63, 0x99, 0x45, 0x91, 0xd5, 0xce,
|
||||||
|
0x9b, 0x43, 0x05, 0xc1, 0xa5, 0x5e, 0x2a, 0xda,
|
||||||
|
0x90, 0x4c, 0xf0, 0x6c, 0x4d, 0x5f, 0xd3, 0x62,
|
||||||
|
})
|
||||||
|
|
||||||
|
// mainnetGenesisMerkleRoot is the hash of the first transaction in the genesis
|
||||||
|
// block for the main network.
|
||||||
|
var mainnetGenesisMerkleRoot = externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||||
|
0x4a, 0x5e, 0x1e, 0x4b, 0xaa, 0xb8, 0x9f, 0x3a,
|
||||||
|
0x32, 0x51, 0x8a, 0x88, 0xc3, 0x1b, 0xc8, 0x7f,
|
||||||
|
0x61, 0x8f, 0x76, 0x67, 0x3e, 0x2c, 0xc7, 0x7a,
|
||||||
|
0xb2, 0x12, 0x7b, 0x7a, 0xfd, 0xed, 0xa3, 0x3b,
|
||||||
|
})
|
||||||
|
|
||||||
|
var exampleAcceptedIDMerkleRoot = externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||||
|
0x09, 0x3B, 0xC7, 0xE3, 0x67, 0x11, 0x7B, 0x3C,
|
||||||
|
0x30, 0xC1, 0xF8, 0xFD, 0xD0, 0xD9, 0x72, 0x87,
|
||||||
|
0x7F, 0x16, 0xC5, 0x96, 0x2E, 0x8B, 0xD9, 0x63,
|
||||||
|
0x65, 0x9C, 0x79, 0x3C, 0xE3, 0x70, 0xD9, 0x5F,
|
||||||
|
})
|
||||||
|
|
||||||
|
var exampleUTXOCommitment = externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
|
||||||
|
0x10, 0x3B, 0xC7, 0xE3, 0x67, 0x11, 0x7B, 0x3C,
|
||||||
|
0x30, 0xC1, 0xF8, 0xFD, 0xD0, 0xD9, 0x72, 0x87,
|
||||||
|
0x7F, 0x16, 0xC5, 0x96, 0x2E, 0x8B, 0xD9, 0x63,
|
||||||
|
0x65, 0x9C, 0x79, 0x3C, 0xE3, 0x70, 0xD9, 0x5F,
|
||||||
|
})
|
||||||
@@ -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
|
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
|
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.
|
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
|
through channels, functions, etc. In addition, concrete implementations of most
|
||||||
of the currently supported kaspa messages are provided. For these supported
|
of the currently supported kaspa messages are provided. For these supported
|
||||||
messages, all of the details of marshalling and unmarshalling to and from the
|
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.
|
themselves with the specifics.
|
||||||
|
|
||||||
Message Interaction
|
Message Interaction
|
||||||
@@ -55,7 +55,7 @@ Protocol Version
|
|||||||
|
|
||||||
The protocol version should be negotiated with the remote peer at a higher
|
The protocol version should be negotiated with the remote peer at a higher
|
||||||
level than this package via the version (MsgVersion) message exchange, however,
|
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
|
latest protocol version this package supports and is typically the value to use
|
||||||
for all outbound connections before a potentially lower protocol version is
|
for all outbound connections before a potentially lower protocol version is
|
||||||
negotiated.
|
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
|
message and which kaspa network the message applies to. This package provides
|
||||||
the following constants:
|
the following constants:
|
||||||
|
|
||||||
domainmessage.Mainnet
|
appmessage.Mainnet
|
||||||
domainmessage.Testnet (Test network)
|
appmessage.Testnet (Test network)
|
||||||
domainmessage.Regtest (Regression test network)
|
appmessage.Simnet (Simulation test network)
|
||||||
domainmessage.Simnet (Simulation test network)
|
appmessage.Devnet (Development network)
|
||||||
domainmessage.Devnet (Development network)
|
|
||||||
|
|
||||||
Determining Message Type
|
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
|
// Assumes msg is already a valid concrete message such as one created
|
||||||
// via NewMsgVersion or read via ReadMessage.
|
// via NewMsgVersion or read via ReadMessage.
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case *domainmessage.MsgVersion:
|
case *appmessage.MsgVersion:
|
||||||
// The message is a pointer to a MsgVersion struct.
|
// The message is a pointer to a MsgVersion struct.
|
||||||
fmt.Printf("Protocol version: %d", msg.ProtocolVersion)
|
fmt.Printf("Protocol version: %d", msg.ProtocolVersion)
|
||||||
case *domainmessage.MsgBlock:
|
case *appmessage.MsgBlock:
|
||||||
// The message is a pointer to a MsgBlock struct.
|
// The message is a pointer to a MsgBlock struct.
|
||||||
fmt.Printf("Number of tx in block: %d", msg.Header.TxnCount)
|
fmt.Printf("Number of tx in block: %d", msg.Header.TxnCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
Reading Messages
|
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
|
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:
|
a remote node running a kaspa peer. Example syntax is:
|
||||||
|
|
||||||
// Reads and validates the next kaspa message from conn using the
|
// Reads and validates the next kaspa message from conn using the
|
||||||
// protocol version pver and the kaspa network kaspaNet. The returns
|
// 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.
|
// 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 {
|
if err != nil {
|
||||||
// Log and handle the error
|
// Log and handle the error
|
||||||
}
|
}
|
||||||
|
|
||||||
Writing Messages
|
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
|
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
|
a remote node running a kaspa peer. Example syntax to request addresses
|
||||||
from a remote peer is:
|
from a remote peer is:
|
||||||
|
|
||||||
// Create a new getaddr kaspa message.
|
// Create a new getaddr kaspa message.
|
||||||
msg := domainmessage.NewMsgRequestAddresses()
|
msg := appmessage.NewMsgRequestAddresses()
|
||||||
|
|
||||||
// Writes a kaspa message msg to conn using the protocol version
|
// Writes a kaspa message msg to conn using the protocol version
|
||||||
// pver, and the kaspa network kaspaNet. The return is a possible
|
// pver, and the kaspa network kaspaNet. The return is a possible
|
||||||
// error.
|
// error.
|
||||||
err := domainmessage.WriteMessage(conn, msg, pver, kaspaNet)
|
err := appmessage.WriteMessage(conn, msg, pver, kaspaNet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Log and handle the error
|
// Log and handle the error
|
||||||
}
|
}
|
||||||
@@ -127,8 +126,8 @@ Errors
|
|||||||
|
|
||||||
Errors returned by this package are either the raw errors provided by underlying
|
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
|
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
|
differentiate between general IO errors and malformed messages through type
|
||||||
assertions.
|
assertions.
|
||||||
*/
|
*/
|
||||||
package domainmessage
|
package appmessage
|
||||||
317
app/appmessage/domainconverters.go
Normal file
317
app/appmessage/domainconverters.go
Normal file
@@ -0,0 +1,317 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/utils/blockheader"
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks"
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionid"
|
||||||
|
"github.com/kaspanet/kaspad/util/mstime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DomainBlockToMsgBlock converts an externalapi.DomainBlock to MsgBlock
|
||||||
|
func DomainBlockToMsgBlock(domainBlock *externalapi.DomainBlock) *MsgBlock {
|
||||||
|
msgTxs := make([]*MsgTx, 0, len(domainBlock.Transactions))
|
||||||
|
for _, domainTransaction := range domainBlock.Transactions {
|
||||||
|
msgTxs = append(msgTxs, DomainTransactionToMsgTx(domainTransaction))
|
||||||
|
}
|
||||||
|
return &MsgBlock{
|
||||||
|
Header: *DomainBlockHeaderToBlockHeader(domainBlock.Header),
|
||||||
|
Transactions: msgTxs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DomainBlockHeaderToBlockHeader converts an externalapi.BlockHeader to MsgBlockHeader
|
||||||
|
func DomainBlockHeaderToBlockHeader(domainBlockHeader externalapi.BlockHeader) *MsgBlockHeader {
|
||||||
|
return &MsgBlockHeader{
|
||||||
|
Version: domainBlockHeader.Version(),
|
||||||
|
ParentHashes: domainBlockHeader.ParentHashes(),
|
||||||
|
HashMerkleRoot: domainBlockHeader.HashMerkleRoot(),
|
||||||
|
AcceptedIDMerkleRoot: domainBlockHeader.AcceptedIDMerkleRoot(),
|
||||||
|
UTXOCommitment: domainBlockHeader.UTXOCommitment(),
|
||||||
|
Timestamp: mstime.UnixMilliseconds(domainBlockHeader.TimeInMilliseconds()),
|
||||||
|
Bits: domainBlockHeader.Bits(),
|
||||||
|
Nonce: domainBlockHeader.Nonce(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgBlockToDomainBlock converts a MsgBlock to externalapi.DomainBlock
|
||||||
|
func MsgBlockToDomainBlock(msgBlock *MsgBlock) *externalapi.DomainBlock {
|
||||||
|
transactions := make([]*externalapi.DomainTransaction, 0, len(msgBlock.Transactions))
|
||||||
|
for _, msgTx := range msgBlock.Transactions {
|
||||||
|
transactions = append(transactions, MsgTxToDomainTransaction(msgTx))
|
||||||
|
}
|
||||||
|
|
||||||
|
return &externalapi.DomainBlock{
|
||||||
|
Header: BlockHeaderToDomainBlockHeader(&msgBlock.Header),
|
||||||
|
Transactions: transactions,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockHeaderToDomainBlockHeader converts a MsgBlockHeader to externalapi.BlockHeader
|
||||||
|
func BlockHeaderToDomainBlockHeader(blockHeader *MsgBlockHeader) externalapi.BlockHeader {
|
||||||
|
return blockheader.NewImmutableBlockHeader(
|
||||||
|
blockHeader.Version,
|
||||||
|
blockHeader.ParentHashes,
|
||||||
|
blockHeader.HashMerkleRoot,
|
||||||
|
blockHeader.AcceptedIDMerkleRoot,
|
||||||
|
blockHeader.UTXOCommitment,
|
||||||
|
blockHeader.Timestamp.UnixMilliseconds(),
|
||||||
|
blockHeader.Bits,
|
||||||
|
blockHeader.Nonce,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DomainTransactionToMsgTx converts an externalapi.DomainTransaction into an MsgTx
|
||||||
|
func DomainTransactionToMsgTx(domainTransaction *externalapi.DomainTransaction) *MsgTx {
|
||||||
|
txIns := make([]*TxIn, 0, len(domainTransaction.Inputs))
|
||||||
|
for _, input := range domainTransaction.Inputs {
|
||||||
|
txIns = append(txIns, domainTransactionInputToTxIn(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
txOuts := make([]*TxOut, 0, len(domainTransaction.Outputs))
|
||||||
|
for _, output := range domainTransaction.Outputs {
|
||||||
|
txOuts = append(txOuts, domainTransactionOutputToTxOut(output))
|
||||||
|
}
|
||||||
|
|
||||||
|
return &MsgTx{
|
||||||
|
Version: domainTransaction.Version,
|
||||||
|
TxIn: txIns,
|
||||||
|
TxOut: txOuts,
|
||||||
|
LockTime: domainTransaction.LockTime,
|
||||||
|
SubnetworkID: domainTransaction.SubnetworkID,
|
||||||
|
Gas: domainTransaction.Gas,
|
||||||
|
PayloadHash: domainTransaction.PayloadHash,
|
||||||
|
Payload: domainTransaction.Payload,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func domainTransactionOutputToTxOut(domainTransactionOutput *externalapi.DomainTransactionOutput) *TxOut {
|
||||||
|
return &TxOut{
|
||||||
|
Value: domainTransactionOutput.Value,
|
||||||
|
ScriptPubKey: domainTransactionOutput.ScriptPublicKey,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func domainTransactionInputToTxIn(domainTransactionInput *externalapi.DomainTransactionInput) *TxIn {
|
||||||
|
return &TxIn{
|
||||||
|
PreviousOutpoint: *domainOutpointToOutpoint(domainTransactionInput.PreviousOutpoint),
|
||||||
|
SignatureScript: domainTransactionInput.SignatureScript,
|
||||||
|
Sequence: domainTransactionInput.Sequence,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func domainOutpointToOutpoint(domainOutpoint externalapi.DomainOutpoint) *Outpoint {
|
||||||
|
return NewOutpoint(
|
||||||
|
&domainOutpoint.TransactionID,
|
||||||
|
domainOutpoint.Index)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgTxToDomainTransaction converts an MsgTx into externalapi.DomainTransaction
|
||||||
|
func MsgTxToDomainTransaction(msgTx *MsgTx) *externalapi.DomainTransaction {
|
||||||
|
transactionInputs := make([]*externalapi.DomainTransactionInput, 0, len(msgTx.TxIn))
|
||||||
|
for _, txIn := range msgTx.TxIn {
|
||||||
|
transactionInputs = append(transactionInputs, txInToDomainTransactionInput(txIn))
|
||||||
|
}
|
||||||
|
|
||||||
|
transactionOutputs := make([]*externalapi.DomainTransactionOutput, 0, len(msgTx.TxOut))
|
||||||
|
for _, txOut := range msgTx.TxOut {
|
||||||
|
transactionOutputs = append(transactionOutputs, txOutToDomainTransactionOutput(txOut))
|
||||||
|
}
|
||||||
|
|
||||||
|
payload := make([]byte, 0)
|
||||||
|
if msgTx.Payload != nil {
|
||||||
|
payload = msgTx.Payload
|
||||||
|
}
|
||||||
|
|
||||||
|
return &externalapi.DomainTransaction{
|
||||||
|
Version: msgTx.Version,
|
||||||
|
Inputs: transactionInputs,
|
||||||
|
Outputs: transactionOutputs,
|
||||||
|
LockTime: msgTx.LockTime,
|
||||||
|
SubnetworkID: msgTx.SubnetworkID,
|
||||||
|
Gas: msgTx.Gas,
|
||||||
|
PayloadHash: msgTx.PayloadHash,
|
||||||
|
Payload: payload,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func txOutToDomainTransactionOutput(txOut *TxOut) *externalapi.DomainTransactionOutput {
|
||||||
|
return &externalapi.DomainTransactionOutput{
|
||||||
|
Value: txOut.Value,
|
||||||
|
ScriptPublicKey: txOut.ScriptPubKey,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func txInToDomainTransactionInput(txIn *TxIn) *externalapi.DomainTransactionInput {
|
||||||
|
return &externalapi.DomainTransactionInput{
|
||||||
|
PreviousOutpoint: *outpointToDomainOutpoint(&txIn.PreviousOutpoint), //TODO
|
||||||
|
SignatureScript: txIn.SignatureScript,
|
||||||
|
Sequence: txIn.Sequence,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func outpointToDomainOutpoint(outpoint *Outpoint) *externalapi.DomainOutpoint {
|
||||||
|
return &externalapi.DomainOutpoint{
|
||||||
|
TransactionID: outpoint.TxID,
|
||||||
|
Index: outpoint.Index,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RPCTransactionToDomainTransaction converts RPCTransactions to DomainTransactions
|
||||||
|
func RPCTransactionToDomainTransaction(rpcTransaction *RPCTransaction) (*externalapi.DomainTransaction, error) {
|
||||||
|
inputs := make([]*externalapi.DomainTransactionInput, len(rpcTransaction.Inputs))
|
||||||
|
for i, input := range rpcTransaction.Inputs {
|
||||||
|
transactionIDBytes, err := hex.DecodeString(input.PreviousOutpoint.TransactionID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
transactionID, err := transactionid.FromBytes(transactionIDBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
previousOutpoint := &externalapi.DomainOutpoint{
|
||||||
|
TransactionID: *transactionID,
|
||||||
|
Index: input.PreviousOutpoint.Index,
|
||||||
|
}
|
||||||
|
signatureScript, err := hex.DecodeString(input.SignatureScript)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
inputs[i] = &externalapi.DomainTransactionInput{
|
||||||
|
PreviousOutpoint: *previousOutpoint,
|
||||||
|
SignatureScript: signatureScript,
|
||||||
|
Sequence: input.Sequence,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outputs := make([]*externalapi.DomainTransactionOutput, len(rpcTransaction.Outputs))
|
||||||
|
for i, output := range rpcTransaction.Outputs {
|
||||||
|
scriptPublicKey, err := hex.DecodeString(output.ScriptPublicKey.Script)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
outputs[i] = &externalapi.DomainTransactionOutput{
|
||||||
|
Value: output.Amount,
|
||||||
|
ScriptPublicKey: &externalapi.ScriptPublicKey{Script: scriptPublicKey, Version: output.ScriptPublicKey.Version},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
subnetworkIDBytes, err := hex.DecodeString(rpcTransaction.SubnetworkID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
subnetworkID, err := subnetworks.FromBytes(subnetworkIDBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
payloadHashBytes, err := hex.DecodeString(rpcTransaction.PayloadHash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
payloadHash, err := externalapi.NewDomainHashFromByteSlice(payloadHashBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
payload, err := hex.DecodeString(rpcTransaction.Payload)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &externalapi.DomainTransaction{
|
||||||
|
Version: rpcTransaction.Version,
|
||||||
|
Inputs: inputs,
|
||||||
|
Outputs: outputs,
|
||||||
|
LockTime: rpcTransaction.LockTime,
|
||||||
|
SubnetworkID: *subnetworkID,
|
||||||
|
Gas: rpcTransaction.LockTime,
|
||||||
|
PayloadHash: *payloadHash,
|
||||||
|
Payload: payload,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DomainTransactionToRPCTransaction converts DomainTransactions to RPCTransactions
|
||||||
|
func DomainTransactionToRPCTransaction(transaction *externalapi.DomainTransaction) *RPCTransaction {
|
||||||
|
inputs := make([]*RPCTransactionInput, len(transaction.Inputs))
|
||||||
|
for i, input := range transaction.Inputs {
|
||||||
|
transactionID := input.PreviousOutpoint.TransactionID.String()
|
||||||
|
previousOutpoint := &RPCOutpoint{
|
||||||
|
TransactionID: transactionID,
|
||||||
|
Index: input.PreviousOutpoint.Index,
|
||||||
|
}
|
||||||
|
signatureScript := hex.EncodeToString(input.SignatureScript)
|
||||||
|
inputs[i] = &RPCTransactionInput{
|
||||||
|
PreviousOutpoint: previousOutpoint,
|
||||||
|
SignatureScript: signatureScript,
|
||||||
|
Sequence: input.Sequence,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outputs := make([]*RPCTransactionOutput, len(transaction.Outputs))
|
||||||
|
for i, output := range transaction.Outputs {
|
||||||
|
scriptPublicKey := hex.EncodeToString(output.ScriptPublicKey.Script)
|
||||||
|
outputs[i] = &RPCTransactionOutput{
|
||||||
|
Amount: output.Value,
|
||||||
|
ScriptPublicKey: &RPCScriptPublicKey{Script: scriptPublicKey, Version: output.ScriptPublicKey.Version},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
subnetworkID := hex.EncodeToString(transaction.SubnetworkID[:])
|
||||||
|
payloadHash := transaction.PayloadHash.String()
|
||||||
|
payload := hex.EncodeToString(transaction.Payload)
|
||||||
|
return &RPCTransaction{
|
||||||
|
Version: transaction.Version,
|
||||||
|
Inputs: inputs,
|
||||||
|
Outputs: outputs,
|
||||||
|
LockTime: transaction.LockTime,
|
||||||
|
SubnetworkID: subnetworkID,
|
||||||
|
Gas: transaction.LockTime,
|
||||||
|
PayloadHash: payloadHash,
|
||||||
|
Payload: payload,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OutpointAndUTXOEntryPairsToDomainOutpointAndUTXOEntryPairs converts
|
||||||
|
// OutpointAndUTXOEntryPairs to domain OutpointAndUTXOEntryPairs
|
||||||
|
func OutpointAndUTXOEntryPairsToDomainOutpointAndUTXOEntryPairs(
|
||||||
|
outpointAndUTXOEntryPairs []*OutpointAndUTXOEntryPair) []*externalapi.OutpointAndUTXOEntryPair {
|
||||||
|
|
||||||
|
domainOutpointAndUTXOEntryPairs := make([]*externalapi.OutpointAndUTXOEntryPair, len(outpointAndUTXOEntryPairs))
|
||||||
|
for i, outpointAndUTXOEntryPair := range outpointAndUTXOEntryPairs {
|
||||||
|
domainOutpointAndUTXOEntryPairs[i] = &externalapi.OutpointAndUTXOEntryPair{
|
||||||
|
Outpoint: &externalapi.DomainOutpoint{
|
||||||
|
TransactionID: outpointAndUTXOEntryPair.Outpoint.TxID,
|
||||||
|
Index: outpointAndUTXOEntryPair.Outpoint.Index,
|
||||||
|
},
|
||||||
|
UTXOEntry: utxo.NewUTXOEntry(
|
||||||
|
outpointAndUTXOEntryPair.UTXOEntry.Amount,
|
||||||
|
outpointAndUTXOEntryPair.UTXOEntry.ScriptPublicKey,
|
||||||
|
outpointAndUTXOEntryPair.UTXOEntry.IsCoinbase,
|
||||||
|
outpointAndUTXOEntryPair.UTXOEntry.BlockBlueScore,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return domainOutpointAndUTXOEntryPairs
|
||||||
|
}
|
||||||
|
|
||||||
|
// DomainOutpointAndUTXOEntryPairsToOutpointAndUTXOEntryPairs converts
|
||||||
|
// domain OutpointAndUTXOEntryPairs to OutpointAndUTXOEntryPairs
|
||||||
|
func DomainOutpointAndUTXOEntryPairsToOutpointAndUTXOEntryPairs(
|
||||||
|
outpointAndUTXOEntryPairs []*externalapi.OutpointAndUTXOEntryPair) []*OutpointAndUTXOEntryPair {
|
||||||
|
|
||||||
|
domainOutpointAndUTXOEntryPairs := make([]*OutpointAndUTXOEntryPair, len(outpointAndUTXOEntryPairs))
|
||||||
|
for i, outpointAndUTXOEntryPair := range outpointAndUTXOEntryPairs {
|
||||||
|
domainOutpointAndUTXOEntryPairs[i] = &OutpointAndUTXOEntryPair{
|
||||||
|
Outpoint: &Outpoint{
|
||||||
|
TxID: outpointAndUTXOEntryPair.Outpoint.TransactionID,
|
||||||
|
Index: outpointAndUTXOEntryPair.Outpoint.Index,
|
||||||
|
},
|
||||||
|
UTXOEntry: &UTXOEntry{
|
||||||
|
Amount: outpointAndUTXOEntryPair.UTXOEntry.Amount(),
|
||||||
|
ScriptPublicKey: outpointAndUTXOEntryPair.UTXOEntry.ScriptPublicKey(),
|
||||||
|
IsCoinbase: outpointAndUTXOEntryPair.UTXOEntry.IsCoinbase(),
|
||||||
|
BlockBlueScore: outpointAndUTXOEntryPair.UTXOEntry.BlockBlueScore(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return domainOutpointAndUTXOEntryPairs
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -32,3 +32,16 @@ func (e *MessageError) Error() string {
|
|||||||
func messageError(f string, desc string) *MessageError {
|
func messageError(f string, desc string) *MessageError {
|
||||||
return &MessageError{Func: f, Description: desc}
|
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
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
235
app/appmessage/message.go
Normal file
235
app/appmessage/message.go
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
// 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
|
||||||
|
CmdRequestHeaders
|
||||||
|
CmdBlock
|
||||||
|
CmdTx
|
||||||
|
CmdPing
|
||||||
|
CmdPong
|
||||||
|
CmdRequestBlockLocator
|
||||||
|
CmdBlockLocator
|
||||||
|
CmdInvRelayBlock
|
||||||
|
CmdRequestRelayBlocks
|
||||||
|
CmdInvTransaction
|
||||||
|
CmdRequestTransactions
|
||||||
|
CmdIBDBlock
|
||||||
|
CmdDoneHeaders
|
||||||
|
CmdTransactionNotFound
|
||||||
|
CmdReject
|
||||||
|
CmdHeader
|
||||||
|
CmdRequestNextHeaders
|
||||||
|
CmdRequestPruningPointUTXOSetAndBlock
|
||||||
|
CmdPruningPointUTXOSetChunk
|
||||||
|
CmdRequestIBDBlocks
|
||||||
|
CmdUnexpectedPruningPoint
|
||||||
|
CmdRequestPruningPointHash
|
||||||
|
CmdPruningPointHash
|
||||||
|
CmdIBDBlockLocator
|
||||||
|
CmdIBDBlockLocatorHighestHash
|
||||||
|
CmdBlockHeaders
|
||||||
|
CmdRequestNextPruningPointUTXOSetChunk
|
||||||
|
CmdDonePruningPointUTXOSetChunks
|
||||||
|
|
||||||
|
// rpc
|
||||||
|
CmdGetCurrentNetworkRequestMessage
|
||||||
|
CmdGetCurrentNetworkResponseMessage
|
||||||
|
CmdSubmitBlockRequestMessage
|
||||||
|
CmdSubmitBlockResponseMessage
|
||||||
|
CmdGetBlockTemplateRequestMessage
|
||||||
|
CmdGetBlockTemplateResponseMessage
|
||||||
|
CmdGetBlockTemplateTransactionMessage
|
||||||
|
CmdNotifyBlockAddedRequestMessage
|
||||||
|
CmdNotifyBlockAddedResponseMessage
|
||||||
|
CmdBlockAddedNotificationMessage
|
||||||
|
CmdGetPeerAddressesRequestMessage
|
||||||
|
CmdGetPeerAddressesResponseMessage
|
||||||
|
CmdGetSelectedTipHashRequestMessage
|
||||||
|
CmdGetSelectedTipHashResponseMessage
|
||||||
|
CmdGetMempoolEntryRequestMessage
|
||||||
|
CmdGetMempoolEntryResponseMessage
|
||||||
|
CmdGetConnectedPeerInfoRequestMessage
|
||||||
|
CmdGetConnectedPeerInfoResponseMessage
|
||||||
|
CmdAddPeerRequestMessage
|
||||||
|
CmdAddPeerResponseMessage
|
||||||
|
CmdSubmitTransactionRequestMessage
|
||||||
|
CmdSubmitTransactionResponseMessage
|
||||||
|
CmdNotifyVirtualSelectedParentChainChangedRequestMessage
|
||||||
|
CmdNotifyVirtualSelectedParentChainChangedResponseMessage
|
||||||
|
CmdVirtualSelectedParentChainChangedNotificationMessage
|
||||||
|
CmdGetBlockRequestMessage
|
||||||
|
CmdGetBlockResponseMessage
|
||||||
|
CmdGetSubnetworkRequestMessage
|
||||||
|
CmdGetSubnetworkResponseMessage
|
||||||
|
CmdGetVirtualSelectedParentChainFromBlockRequestMessage
|
||||||
|
CmdGetVirtualSelectedParentChainFromBlockResponseMessage
|
||||||
|
CmdGetBlocksRequestMessage
|
||||||
|
CmdGetBlocksResponseMessage
|
||||||
|
CmdGetBlockCountRequestMessage
|
||||||
|
CmdGetBlockCountResponseMessage
|
||||||
|
CmdGetBlockDAGInfoRequestMessage
|
||||||
|
CmdGetBlockDAGInfoResponseMessage
|
||||||
|
CmdResolveFinalityConflictRequestMessage
|
||||||
|
CmdResolveFinalityConflictResponseMessage
|
||||||
|
CmdNotifyFinalityConflictsRequestMessage
|
||||||
|
CmdNotifyFinalityConflictsResponseMessage
|
||||||
|
CmdFinalityConflictNotificationMessage
|
||||||
|
CmdFinalityConflictResolvedNotificationMessage
|
||||||
|
CmdGetMempoolEntriesRequestMessage
|
||||||
|
CmdGetMempoolEntriesResponseMessage
|
||||||
|
CmdShutDownRequestMessage
|
||||||
|
CmdShutDownResponseMessage
|
||||||
|
CmdGetHeadersRequestMessage
|
||||||
|
CmdGetHeadersResponseMessage
|
||||||
|
CmdNotifyUTXOsChangedRequestMessage
|
||||||
|
CmdNotifyUTXOsChangedResponseMessage
|
||||||
|
CmdUTXOsChangedNotificationMessage
|
||||||
|
CmdGetUTXOsByAddressesRequestMessage
|
||||||
|
CmdGetUTXOsByAddressesResponseMessage
|
||||||
|
CmdGetVirtualSelectedParentBlueScoreRequestMessage
|
||||||
|
CmdGetVirtualSelectedParentBlueScoreResponseMessage
|
||||||
|
CmdNotifyVirtualSelectedParentBlueScoreChangedRequestMessage
|
||||||
|
CmdNotifyVirtualSelectedParentBlueScoreChangedResponseMessage
|
||||||
|
CmdVirtualSelectedParentBlueScoreChangedNotificationMessage
|
||||||
|
)
|
||||||
|
|
||||||
|
// ProtocolMessageCommandToString maps all MessageCommands to their string representation
|
||||||
|
var ProtocolMessageCommandToString = map[MessageCommand]string{
|
||||||
|
CmdVersion: "Version",
|
||||||
|
CmdVerAck: "VerAck",
|
||||||
|
CmdRequestAddresses: "RequestAddresses",
|
||||||
|
CmdAddresses: "Addresses",
|
||||||
|
CmdRequestHeaders: "RequestHeaders",
|
||||||
|
CmdBlock: "Block",
|
||||||
|
CmdTx: "Tx",
|
||||||
|
CmdPing: "Ping",
|
||||||
|
CmdPong: "Pong",
|
||||||
|
CmdRequestBlockLocator: "RequestBlockLocator",
|
||||||
|
CmdBlockLocator: "BlockLocator",
|
||||||
|
CmdInvRelayBlock: "InvRelayBlock",
|
||||||
|
CmdRequestRelayBlocks: "RequestRelayBlocks",
|
||||||
|
CmdInvTransaction: "InvTransaction",
|
||||||
|
CmdRequestTransactions: "RequestTransactions",
|
||||||
|
CmdIBDBlock: "IBDBlock",
|
||||||
|
CmdDoneHeaders: "DoneHeaders",
|
||||||
|
CmdTransactionNotFound: "TransactionNotFound",
|
||||||
|
CmdReject: "Reject",
|
||||||
|
CmdHeader: "Header",
|
||||||
|
CmdRequestNextHeaders: "RequestNextHeaders",
|
||||||
|
CmdRequestPruningPointUTXOSetAndBlock: "RequestPruningPointUTXOSetAndBlock",
|
||||||
|
CmdPruningPointUTXOSetChunk: "PruningPointUTXOSetChunk",
|
||||||
|
CmdRequestIBDBlocks: "RequestIBDBlocks",
|
||||||
|
CmdUnexpectedPruningPoint: "UnexpectedPruningPoint",
|
||||||
|
CmdRequestPruningPointHash: "RequestPruningPointHashHash",
|
||||||
|
CmdPruningPointHash: "PruningPointHash",
|
||||||
|
CmdIBDBlockLocator: "IBDBlockLocator",
|
||||||
|
CmdIBDBlockLocatorHighestHash: "IBDBlockLocatorHighestHash",
|
||||||
|
CmdBlockHeaders: "BlockHeaders",
|
||||||
|
CmdRequestNextPruningPointUTXOSetChunk: "RequestNextPruningPointUTXOSetChunk",
|
||||||
|
CmdDonePruningPointUTXOSetChunks: "DonePruningPointUTXOSetChunks",
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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",
|
||||||
|
CmdNotifyVirtualSelectedParentChainChangedRequestMessage: "NotifyVirtualSelectedParentChainChangedRequest",
|
||||||
|
CmdNotifyVirtualSelectedParentChainChangedResponseMessage: "NotifyVirtualSelectedParentChainChangedResponse",
|
||||||
|
CmdVirtualSelectedParentChainChangedNotificationMessage: "VirtualSelectedParentChainChangedNotification",
|
||||||
|
CmdGetBlockRequestMessage: "GetBlockRequest",
|
||||||
|
CmdGetBlockResponseMessage: "GetBlockResponse",
|
||||||
|
CmdGetSubnetworkRequestMessage: "GetSubnetworkRequest",
|
||||||
|
CmdGetSubnetworkResponseMessage: "GetSubnetworkResponse",
|
||||||
|
CmdGetVirtualSelectedParentChainFromBlockRequestMessage: "GetVirtualSelectedParentChainFromBlockRequest",
|
||||||
|
CmdGetVirtualSelectedParentChainFromBlockResponseMessage: "GetVirtualSelectedParentChainFromBlockResponse",
|
||||||
|
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: "GetMempoolEntriesRequest",
|
||||||
|
CmdGetMempoolEntriesResponseMessage: "GetMempoolEntriesResponse",
|
||||||
|
CmdGetHeadersRequestMessage: "GetHeadersRequest",
|
||||||
|
CmdGetHeadersResponseMessage: "GetHeadersResponse",
|
||||||
|
CmdNotifyUTXOsChangedRequestMessage: "NotifyUTXOsChangedRequest",
|
||||||
|
CmdNotifyUTXOsChangedResponseMessage: "NotifyUTXOsChangedResponse",
|
||||||
|
CmdUTXOsChangedNotificationMessage: "UTXOsChangedNotification",
|
||||||
|
CmdGetUTXOsByAddressesRequestMessage: "GetUTXOsByAddressesRequest",
|
||||||
|
CmdGetUTXOsByAddressesResponseMessage: "GetUTXOsByAddressesResponse",
|
||||||
|
CmdGetVirtualSelectedParentBlueScoreRequestMessage: "GetVirtualSelectedParentBlueScoreRequest",
|
||||||
|
CmdGetVirtualSelectedParentBlueScoreResponseMessage: "GetVirtualSelectedParentBlueScoreResponse",
|
||||||
|
CmdNotifyVirtualSelectedParentBlueScoreChangedRequestMessage: "NotifyVirtualSelectedParentBlueScoreChangedRequest",
|
||||||
|
CmdNotifyVirtualSelectedParentBlueScoreChangedResponseMessage: "NotifyVirtualSelectedParentBlueScoreChangedResponse",
|
||||||
|
CmdVirtualSelectedParentBlueScoreChangedNotificationMessage: "VirtualSelectedParentBlueScoreChangedNotification",
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
19
app/appmessage/p2p_blockheaders.go
Normal file
19
app/appmessage/p2p_blockheaders.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
// BlockHeadersMessage represents a kaspa BlockHeaders message
|
||||||
|
type BlockHeadersMessage struct {
|
||||||
|
baseMessage
|
||||||
|
BlockHeaders []*MsgBlockHeader
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *BlockHeadersMessage) Command() MessageCommand {
|
||||||
|
return CmdBlockHeaders
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBlockHeadersMessage returns a new kaspa BlockHeaders message
|
||||||
|
func NewBlockHeadersMessage(blockHeaders []*MsgBlockHeader) *BlockHeadersMessage {
|
||||||
|
return &BlockHeadersMessage{
|
||||||
|
BlockHeaders: blockHeaders,
|
||||||
|
}
|
||||||
|
}
|
||||||
30
app/appmessage/p2p_msgaddresses.go
Normal file
30
app/appmessage/p2p_msgaddresses.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// 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 appmessage
|
||||||
|
|
||||||
|
// MaxAddressesPerMsg is the maximum number of addresses that can be in a single
|
||||||
|
// kaspa Addresses message (MsgAddresses).
|
||||||
|
const MaxAddressesPerMsg = 1000
|
||||||
|
|
||||||
|
// MsgAddresses implements the Message interface and represents a kaspa
|
||||||
|
// Addresses message.
|
||||||
|
type MsgAddresses struct {
|
||||||
|
baseMessage
|
||||||
|
AddressList []*NetAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message. This is part
|
||||||
|
// of the Message interface implementation.
|
||||||
|
func (msg *MsgAddresses) Command() MessageCommand {
|
||||||
|
return CmdAddresses
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMsgAddresses returns a new kaspa Addresses message that conforms to the
|
||||||
|
// Message interface. See MsgAddresses for details.
|
||||||
|
func NewMsgAddresses(addressList []*NetAddress) *MsgAddresses {
|
||||||
|
return &MsgAddresses{
|
||||||
|
AddressList: addressList,
|
||||||
|
}
|
||||||
|
}
|
||||||
87
app/appmessage/p2p_msgblock.go
Normal file
87
app/appmessage/p2p_msgblock.go
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
// 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 (
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
// defaultTransactionAlloc is the default size used for the backing array
|
||||||
|
// for transactions. The transaction array will dynamically grow as needed, but
|
||||||
|
// this figure is intended to provide enough space for the number of
|
||||||
|
// transactions in the vast majority of blocks without needing to grow the
|
||||||
|
// backing array multiple times.
|
||||||
|
const defaultTransactionAlloc = 2048
|
||||||
|
|
||||||
|
// 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 = MaxMassAcceptedByBlock / 2
|
||||||
|
|
||||||
|
// MaxTxPerBlock is the maximum number of transactions that could
|
||||||
|
// possibly fit into a block.
|
||||||
|
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.
|
||||||
|
type TxLoc struct {
|
||||||
|
TxStart int
|
||||||
|
TxLen int
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgBlock implements the Message interface and represents a kaspa
|
||||||
|
// 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 MsgBlockHeader
|
||||||
|
Transactions []*MsgTx
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTransaction adds a transaction to the message.
|
||||||
|
func (msg *MsgBlock) AddTransaction(tx *MsgTx) {
|
||||||
|
msg.Transactions = append(msg.Transactions, tx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearTransactions removes all transactions from the message.
|
||||||
|
func (msg *MsgBlock) ClearTransactions() {
|
||||||
|
msg.Transactions = make([]*MsgTx, 0, defaultTransactionAlloc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message. This is part
|
||||||
|
// of the Message interface implementation.
|
||||||
|
func (msg *MsgBlock) Command() MessageCommand {
|
||||||
|
return CmdBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxPayloadLength returns the maximum length the payload can be for the
|
||||||
|
// receiver. This is part of the Message interface implementation.
|
||||||
|
func (msg *MsgBlock) MaxPayloadLength(pver uint32) uint32 {
|
||||||
|
return MaxMessagePayload
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConvertToPartial clears out all the payloads of the subnetworks that are
|
||||||
|
// incompatible with the given subnetwork ID.
|
||||||
|
// Note: this operation modifies the block in place.
|
||||||
|
func (msg *MsgBlock) ConvertToPartial(subnetworkID *externalapi.DomainSubnetworkID) {
|
||||||
|
for _, tx := range msg.Transactions {
|
||||||
|
if !tx.SubnetworkID.Equal(subnetworkID) {
|
||||||
|
tx.Payload = []byte{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMsgBlock returns a new kaspa block message that conforms to the
|
||||||
|
// Message interface. See MsgBlock for details.
|
||||||
|
func NewMsgBlock(blockHeader *MsgBlockHeader) *MsgBlock {
|
||||||
|
return &MsgBlock{
|
||||||
|
Header: *blockHeader,
|
||||||
|
Transactions: make([]*MsgTx, 0, defaultTransactionAlloc),
|
||||||
|
}
|
||||||
|
}
|
||||||
240
app/appmessage/p2p_msgblock_test.go
Normal file
240
app/appmessage/p2p_msgblock_test.go
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
// 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 (
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
"github.com/kaspanet/kaspad/util/mstime"
|
||||||
|
"math"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestBlock tests the MsgBlock API.
|
||||||
|
func TestBlock(t *testing.T) {
|
||||||
|
pver := ProtocolVersion
|
||||||
|
|
||||||
|
// Block 1 header.
|
||||||
|
parentHashes := blockOne.Header.ParentHashes
|
||||||
|
hashMerkleRoot := blockOne.Header.HashMerkleRoot
|
||||||
|
acceptedIDMerkleRoot := blockOne.Header.AcceptedIDMerkleRoot
|
||||||
|
utxoCommitment := blockOne.Header.UTXOCommitment
|
||||||
|
bits := blockOne.Header.Bits
|
||||||
|
nonce := blockOne.Header.Nonce
|
||||||
|
bh := NewBlockHeader(1, parentHashes, hashMerkleRoot, acceptedIDMerkleRoot, utxoCommitment, bits, nonce)
|
||||||
|
|
||||||
|
// Ensure the command is expected value.
|
||||||
|
wantCmd := MessageCommand(5)
|
||||||
|
msg := NewMsgBlock(bh)
|
||||||
|
if cmd := msg.Command(); cmd != wantCmd {
|
||||||
|
t.Errorf("NewMsgBlock: wrong command - got %v want %v",
|
||||||
|
cmd, wantCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure max payload is expected value for latest protocol version.
|
||||||
|
wantPayload := uint32(1024 * 1024 * 32)
|
||||||
|
maxPayload := msg.MaxPayloadLength(pver)
|
||||||
|
if maxPayload != wantPayload {
|
||||||
|
t.Errorf("MaxPayloadLength: wrong max payload length for "+
|
||||||
|
"protocol version %d - got %v, want %v", pver,
|
||||||
|
maxPayload, wantPayload)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure we get the same block header data back out.
|
||||||
|
if !reflect.DeepEqual(&msg.Header, bh) {
|
||||||
|
t.Errorf("NewMsgBlock: wrong block header - got %v, want %v",
|
||||||
|
spew.Sdump(&msg.Header), spew.Sdump(bh))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure transactions are added properly.
|
||||||
|
tx := blockOne.Transactions[0].Copy()
|
||||||
|
msg.AddTransaction(tx)
|
||||||
|
if !reflect.DeepEqual(msg.Transactions, blockOne.Transactions) {
|
||||||
|
t.Errorf("AddTransaction: wrong transactions - got %v, want %v",
|
||||||
|
spew.Sdump(msg.Transactions),
|
||||||
|
spew.Sdump(blockOne.Transactions))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure transactions are properly cleared.
|
||||||
|
msg.ClearTransactions()
|
||||||
|
if len(msg.Transactions) != 0 {
|
||||||
|
t.Errorf("ClearTransactions: wrong transactions - got %v, want %v",
|
||||||
|
len(msg.Transactions), 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConvertToPartial(t *testing.T) {
|
||||||
|
localSubnetworkID := &externalapi.DomainSubnetworkID{0x12}
|
||||||
|
|
||||||
|
transactions := []struct {
|
||||||
|
subnetworkID *externalapi.DomainSubnetworkID
|
||||||
|
payload []byte
|
||||||
|
expectedPayloadLength int
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
subnetworkID: &subnetworks.SubnetworkIDNative,
|
||||||
|
payload: []byte{},
|
||||||
|
expectedPayloadLength: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
subnetworkID: &subnetworks.SubnetworkIDRegistry,
|
||||||
|
payload: []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08},
|
||||||
|
expectedPayloadLength: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
subnetworkID: localSubnetworkID,
|
||||||
|
payload: []byte{0x01},
|
||||||
|
expectedPayloadLength: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
subnetworkID: &externalapi.DomainSubnetworkID{0x34},
|
||||||
|
payload: []byte{0x02},
|
||||||
|
expectedPayloadLength: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
block := MsgBlock{}
|
||||||
|
payload := []byte{1}
|
||||||
|
for _, transaction := range transactions {
|
||||||
|
block.Transactions = append(block.Transactions, NewSubnetworkMsgTx(1, nil, nil, transaction.subnetworkID, 0, payload))
|
||||||
|
}
|
||||||
|
|
||||||
|
block.ConvertToPartial(localSubnetworkID)
|
||||||
|
|
||||||
|
for _, testTransaction := range transactions {
|
||||||
|
var subnetworkTx *MsgTx
|
||||||
|
for _, blockTransaction := range block.Transactions {
|
||||||
|
if blockTransaction.SubnetworkID.Equal(testTransaction.subnetworkID) {
|
||||||
|
subnetworkTx = blockTransaction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if subnetworkTx == nil {
|
||||||
|
t.Errorf("ConvertToPartial: subnetworkID '%s' not found in block!", testTransaction.subnetworkID)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
payloadLength := len(subnetworkTx.Payload)
|
||||||
|
if payloadLength != testTransaction.expectedPayloadLength {
|
||||||
|
t.Errorf("ConvertToPartial: unexpected payload length for subnetwork '%s': expected: %d, got: %d",
|
||||||
|
testTransaction.subnetworkID, testTransaction.expectedPayloadLength, payloadLength)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//blockOne is the first block in the mainnet block DAG.
|
||||||
|
var blockOne = MsgBlock{
|
||||||
|
Header: MsgBlockHeader{
|
||||||
|
Version: 0,
|
||||||
|
ParentHashes: []*externalapi.DomainHash{mainnetGenesisHash, simnetGenesisHash},
|
||||||
|
HashMerkleRoot: mainnetGenesisMerkleRoot,
|
||||||
|
AcceptedIDMerkleRoot: exampleAcceptedIDMerkleRoot,
|
||||||
|
UTXOCommitment: exampleUTXOCommitment,
|
||||||
|
Timestamp: mstime.UnixMilliseconds(0x17315ed0f99),
|
||||||
|
Bits: 0x1d00ffff, // 486604799
|
||||||
|
Nonce: 0x9962e301, // 2573394689
|
||||||
|
},
|
||||||
|
Transactions: []*MsgTx{
|
||||||
|
NewNativeMsgTx(1,
|
||||||
|
[]*TxIn{
|
||||||
|
{
|
||||||
|
PreviousOutpoint: Outpoint{
|
||||||
|
TxID: externalapi.DomainTransactionID{},
|
||||||
|
Index: 0xffffffff,
|
||||||
|
},
|
||||||
|
SignatureScript: []byte{
|
||||||
|
0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04,
|
||||||
|
},
|
||||||
|
Sequence: math.MaxUint64,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[]*TxOut{
|
||||||
|
{
|
||||||
|
Value: 0x12a05f200,
|
||||||
|
ScriptPubKey: &externalapi.ScriptPublicKey{
|
||||||
|
Script: []byte{
|
||||||
|
0x41, // OP_DATA_65
|
||||||
|
0x04, 0x96, 0xb5, 0x38, 0xe8, 0x53, 0x51, 0x9c,
|
||||||
|
0x72, 0x6a, 0x2c, 0x91, 0xe6, 0x1e, 0xc1, 0x16,
|
||||||
|
0x00, 0xae, 0x13, 0x90, 0x81, 0x3a, 0x62, 0x7c,
|
||||||
|
0x66, 0xfb, 0x8b, 0xe7, 0x94, 0x7b, 0xe6, 0x3c,
|
||||||
|
0x52, 0xda, 0x75, 0x89, 0x37, 0x95, 0x15, 0xd4,
|
||||||
|
0xe0, 0xa6, 0x04, 0xf8, 0x14, 0x17, 0x81, 0xe6,
|
||||||
|
0x22, 0x94, 0x72, 0x11, 0x66, 0xbf, 0x62, 0x1e,
|
||||||
|
0x73, 0xa8, 0x2c, 0xbf, 0x23, 0x42, 0xc8, 0x58,
|
||||||
|
0xee, // 65-byte signature
|
||||||
|
0xac, // OP_CHECKSIG
|
||||||
|
},
|
||||||
|
Version: 0},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block one serialized bytes.
|
||||||
|
var blockOneBytes = []byte{
|
||||||
|
0x00, 0x00, // Version 0
|
||||||
|
0x02, // NumParentBlocks
|
||||||
|
0xdc, 0x5f, 0x5b, 0x5b, 0x1d, 0xc2, 0xa7, 0x25, // mainnetGenesisHash
|
||||||
|
0x49, 0xd5, 0x1d, 0x4d, 0xee, 0xd7, 0xa4, 0x8b,
|
||||||
|
0xaf, 0xd3, 0x14, 0x4b, 0x56, 0x78, 0x98, 0xb1,
|
||||||
|
0x8c, 0xfd, 0x9f, 0x69, 0xdd, 0xcf, 0xbb, 0x63,
|
||||||
|
0xf6, 0x7a, 0xd7, 0x69, 0x5d, 0x9b, 0x66, 0x2a, // simnetGenesisHash
|
||||||
|
0x72, 0xff, 0x3d, 0x8e, 0xdb, 0xbb, 0x2d, 0xe0,
|
||||||
|
0xbf, 0xa6, 0x7b, 0x13, 0x97, 0x4b, 0xb9, 0x91,
|
||||||
|
0x0d, 0x11, 0x6d, 0x5c, 0xbd, 0x86, 0x3e, 0x68,
|
||||||
|
0x4a, 0x5e, 0x1e, 0x4b, 0xaa, 0xb8, 0x9f, 0x3a, // HashMerkleRoot
|
||||||
|
0x32, 0x51, 0x8a, 0x88, 0xc3, 0x1b, 0xc8, 0x7f,
|
||||||
|
0x61, 0x8f, 0x76, 0x67, 0x3e, 0x2c, 0xc7, 0x7a,
|
||||||
|
0xb2, 0x12, 0x7b, 0x7a, 0xfd, 0xed, 0xa3, 0x3b,
|
||||||
|
0x09, 0x3B, 0xC7, 0xE3, 0x67, 0x11, 0x7B, 0x3C, // AcceptedIDMerkleRoot
|
||||||
|
0x30, 0xC1, 0xF8, 0xFD, 0xD0, 0xD9, 0x72, 0x87,
|
||||||
|
0x7F, 0x16, 0xC5, 0x96, 0x2E, 0x8B, 0xD9, 0x63,
|
||||||
|
0x65, 0x9C, 0x79, 0x3C, 0xE3, 0x70, 0xD9, 0x5F,
|
||||||
|
0x10, 0x3B, 0xC7, 0xE3, 0x67, 0x11, 0x7B, 0x3C, // UTXOCommitment
|
||||||
|
0x30, 0xC1, 0xF8, 0xFD, 0xD0, 0xD9, 0x72, 0x87,
|
||||||
|
0x7F, 0x16, 0xC5, 0x96, 0x2E, 0x8B, 0xD9, 0x63,
|
||||||
|
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
|
||||||
|
0x01, // TxnCount
|
||||||
|
0x00, 0x00, 0x00, 0x00, // Version
|
||||||
|
0x01, // Varint for number of transaction inputs
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Previous output hash
|
||||||
|
0xff, 0xff, 0xff, 0xff, // Prevous output index
|
||||||
|
0x07, // Varint for length of signature script
|
||||||
|
0x04, 0xff, 0xff, 0x00, 0x1d, 0x01, 0x04, // Signature script (coinbase)
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // Sequence
|
||||||
|
0x01, // Varint for number of transaction outputs
|
||||||
|
0x00, 0xf2, 0x05, 0x2a, 0x01, 0x00, 0x00, 0x00, // Transaction amount
|
||||||
|
0x43, // Varint for length of scriptPubKey
|
||||||
|
0x41, // OP_DATA_65
|
||||||
|
0x04, 0x96, 0xb5, 0x38, 0xe8, 0x53, 0x51, 0x9c,
|
||||||
|
0x72, 0x6a, 0x2c, 0x91, 0xe6, 0x1e, 0xc1, 0x16,
|
||||||
|
0x00, 0xae, 0x13, 0x90, 0x81, 0x3a, 0x62, 0x7c,
|
||||||
|
0x66, 0xfb, 0x8b, 0xe7, 0x94, 0x7b, 0xe6, 0x3c,
|
||||||
|
0x52, 0xda, 0x75, 0x89, 0x37, 0x95, 0x15, 0xd4,
|
||||||
|
0xe0, 0xa6, 0x04, 0xf8, 0x14, 0x17, 0x81, 0xe6,
|
||||||
|
0x22, 0x94, 0x72, 0x11, 0x66, 0xbf, 0x62, 0x1e,
|
||||||
|
0x73, 0xa8, 0x2c, 0xbf, 0x23, 0x42, 0xc8, 0x58,
|
||||||
|
0xee, // 65-byte uncompressed public key
|
||||||
|
0xac, // OP_CHECKSIG
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Lock time
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, // SubnetworkID
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transaction location information for block one transactions.
|
||||||
|
var blockOneTxLocs = []TxLoc{
|
||||||
|
{TxStart: 186, TxLen: 162},
|
||||||
|
}
|
||||||
108
app/appmessage/p2p_msgblockheader.go
Normal file
108
app/appmessage/p2p_msgblockheader.go
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
// 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 (
|
||||||
|
"math"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
"github.com/kaspanet/kaspad/util/mstime"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// BaseBlockHeaderPayload is the base number of bytes a block header can be,
|
||||||
|
// not including the list of parent block headers.
|
||||||
|
// Version 4 bytes + Timestamp 8 bytes + Bits 4 bytes + Nonce 8 bytes +
|
||||||
|
// + NumParentBlocks 1 byte + HashMerkleRoot hash +
|
||||||
|
// + AcceptedIDMerkleRoot hash + UTXOCommitment hash.
|
||||||
|
// To get total size of block header len(ParentHashes) * externalapi.DomainHashSize should be
|
||||||
|
// added to this value
|
||||||
|
const BaseBlockHeaderPayload = 25 + 3*(externalapi.DomainHashSize)
|
||||||
|
|
||||||
|
// MaxNumParentBlocks is the maximum number of parent blocks a block can reference.
|
||||||
|
// Currently set to 255 as the maximum number NumParentBlocks can be due to it being a byte
|
||||||
|
const MaxNumParentBlocks = 255
|
||||||
|
|
||||||
|
// MaxBlockHeaderPayload is the maximum number of bytes a block header can be.
|
||||||
|
// BaseBlockHeaderPayload + up to MaxNumParentBlocks hashes of parent blocks
|
||||||
|
const MaxBlockHeaderPayload = BaseBlockHeaderPayload + (MaxNumParentBlocks * externalapi.DomainHashSize)
|
||||||
|
|
||||||
|
// MsgBlockHeader defines information about a block and is used in the kaspa
|
||||||
|
// block (MsgBlock) and headers (MsgHeader) messages.
|
||||||
|
type MsgBlockHeader struct {
|
||||||
|
baseMessage
|
||||||
|
|
||||||
|
// Version of the block. This is not the same as the protocol version.
|
||||||
|
Version uint16
|
||||||
|
|
||||||
|
// Hashes of the parent block headers in the blockDAG.
|
||||||
|
ParentHashes []*externalapi.DomainHash
|
||||||
|
|
||||||
|
// HashMerkleRoot is the merkle tree reference to hash of all transactions for the block.
|
||||||
|
HashMerkleRoot *externalapi.DomainHash
|
||||||
|
|
||||||
|
// AcceptedIDMerkleRoot is merkle tree reference to hash all transactions
|
||||||
|
// accepted form the block.Blues
|
||||||
|
AcceptedIDMerkleRoot *externalapi.DomainHash
|
||||||
|
|
||||||
|
// UTXOCommitment is an ECMH UTXO commitment to the block UTXO.
|
||||||
|
UTXOCommitment *externalapi.DomainHash
|
||||||
|
|
||||||
|
// Time the block was created.
|
||||||
|
Timestamp mstime.Time
|
||||||
|
|
||||||
|
// Difficulty target for the block.
|
||||||
|
Bits uint32
|
||||||
|
|
||||||
|
// Nonce used to generate the block.
|
||||||
|
Nonce uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// NumParentBlocks return the number of entries in ParentHashes
|
||||||
|
func (h *MsgBlockHeader) NumParentBlocks() byte {
|
||||||
|
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 *MsgBlockHeader) BlockHash() *externalapi.DomainHash {
|
||||||
|
return consensushashing.HeaderHash(BlockHeaderToDomainBlockHeader(h))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsGenesis returns true iff this block is a genesis block
|
||||||
|
func (h *MsgBlockHeader) IsGenesis() bool {
|
||||||
|
return h.NumParentBlocks() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message. This is part
|
||||||
|
// of the Message interface implementation.
|
||||||
|
func (h *MsgBlockHeader) Command() MessageCommand {
|
||||||
|
return CmdHeader
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewBlockHeader returns a new MsgBlockHeader using the provided version, previous
|
||||||
|
// block hash, hash merkle root, accepted ID merkle root, difficulty bits, and nonce used to generate the
|
||||||
|
// block with defaults or calclulated values for the remaining fields.
|
||||||
|
func NewBlockHeader(version uint16, parentHashes []*externalapi.DomainHash, hashMerkleRoot *externalapi.DomainHash,
|
||||||
|
acceptedIDMerkleRoot *externalapi.DomainHash, utxoCommitment *externalapi.DomainHash, bits uint32, nonce uint64) *MsgBlockHeader {
|
||||||
|
|
||||||
|
// Limit the timestamp to one millisecond precision since the protocol
|
||||||
|
// doesn't support better.
|
||||||
|
return &MsgBlockHeader{
|
||||||
|
Version: version,
|
||||||
|
ParentHashes: parentHashes,
|
||||||
|
HashMerkleRoot: hashMerkleRoot,
|
||||||
|
AcceptedIDMerkleRoot: acceptedIDMerkleRoot,
|
||||||
|
UTXOCommitment: utxoCommitment,
|
||||||
|
Timestamp: mstime.Now(),
|
||||||
|
Bits: bits,
|
||||||
|
Nonce: nonce,
|
||||||
|
}
|
||||||
|
}
|
||||||
88
app/appmessage/p2p_msgblockheader_test.go
Normal file
88
app/appmessage/p2p_msgblockheader_test.go
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
// 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 (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
"github.com/kaspanet/kaspad/util/mstime"
|
||||||
|
"github.com/kaspanet/kaspad/util/random"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestBlockHeader tests the MsgBlockHeader API.
|
||||||
|
func TestBlockHeader(t *testing.T) {
|
||||||
|
nonce, err := random.Uint64()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("random.Uint64: Error generating nonce: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
hashes := []*externalapi.DomainHash{mainnetGenesisHash, simnetGenesisHash}
|
||||||
|
|
||||||
|
merkleHash := mainnetGenesisMerkleRoot
|
||||||
|
acceptedIDMerkleRoot := exampleAcceptedIDMerkleRoot
|
||||||
|
bits := uint32(0x1d00ffff)
|
||||||
|
bh := NewBlockHeader(1, hashes, merkleHash, acceptedIDMerkleRoot, exampleUTXOCommitment, bits, nonce)
|
||||||
|
|
||||||
|
// Ensure we get the same data back out.
|
||||||
|
if !reflect.DeepEqual(bh.ParentHashes, hashes) {
|
||||||
|
t.Errorf("NewBlockHeader: wrong prev hashes - got %v, want %v",
|
||||||
|
spew.Sprint(bh.ParentHashes), spew.Sprint(hashes))
|
||||||
|
}
|
||||||
|
if bh.HashMerkleRoot != merkleHash {
|
||||||
|
t.Errorf("NewBlockHeader: wrong merkle root - got %v, want %v",
|
||||||
|
spew.Sprint(bh.HashMerkleRoot), spew.Sprint(merkleHash))
|
||||||
|
}
|
||||||
|
if bh.Bits != bits {
|
||||||
|
t.Errorf("NewBlockHeader: wrong bits - got %v, want %v",
|
||||||
|
bh.Bits, bits)
|
||||||
|
}
|
||||||
|
if bh.Nonce != nonce {
|
||||||
|
t.Errorf("NewBlockHeader: wrong nonce - got %v, want %v",
|
||||||
|
bh.Nonce, nonce)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsGenesis(t *testing.T) {
|
||||||
|
nonce := uint64(123123) // 0x1e0f3
|
||||||
|
bits := uint32(0x1d00ffff)
|
||||||
|
timestamp := mstime.UnixMilliseconds(0x495fab29000)
|
||||||
|
|
||||||
|
baseBlockHdr := &MsgBlockHeader{
|
||||||
|
Version: 1,
|
||||||
|
ParentHashes: []*externalapi.DomainHash{mainnetGenesisHash, simnetGenesisHash},
|
||||||
|
HashMerkleRoot: mainnetGenesisMerkleRoot,
|
||||||
|
Timestamp: timestamp,
|
||||||
|
Bits: bits,
|
||||||
|
Nonce: nonce,
|
||||||
|
}
|
||||||
|
genesisBlockHdr := &MsgBlockHeader{
|
||||||
|
Version: 1,
|
||||||
|
ParentHashes: []*externalapi.DomainHash{},
|
||||||
|
HashMerkleRoot: mainnetGenesisMerkleRoot,
|
||||||
|
Timestamp: timestamp,
|
||||||
|
Bits: bits,
|
||||||
|
Nonce: nonce,
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
in *MsgBlockHeader // Block header to encode
|
||||||
|
isGenesis bool // Expected result for call of .IsGenesis
|
||||||
|
}{
|
||||||
|
{genesisBlockHdr, true},
|
||||||
|
{baseBlockHdr, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("Running %d tests", len(tests))
|
||||||
|
for i, test := range tests {
|
||||||
|
isGenesis := test.in.IsGenesis()
|
||||||
|
if isGenesis != test.isGenesis {
|
||||||
|
t.Errorf("MsgBlockHeader.IsGenesis: #%d got: %t, want: %t",
|
||||||
|
i, isGenesis, test.isGenesis)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MaxBlockLocatorsPerMsg is the maximum number of block locator hashes allowed
|
// MaxBlockLocatorsPerMsg is the maximum number of block locator hashes allowed
|
||||||
@@ -13,7 +13,7 @@ const MaxBlockLocatorsPerMsg = 500
|
|||||||
// syncing with you.
|
// syncing with you.
|
||||||
type MsgBlockLocator struct {
|
type MsgBlockLocator struct {
|
||||||
baseMessage
|
baseMessage
|
||||||
BlockLocatorHashes []*daghash.Hash
|
BlockLocatorHashes []*externalapi.DomainHash
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command returns the protocol command string for the message. This is part
|
// Command returns the protocol command string for the message. This is part
|
||||||
@@ -24,7 +24,7 @@ func (msg *MsgBlockLocator) Command() MessageCommand {
|
|||||||
|
|
||||||
// NewMsgBlockLocator returns a new kaspa locator message that conforms to
|
// NewMsgBlockLocator returns a new kaspa locator message that conforms to
|
||||||
// the Message interface. See MsgBlockLocator for details.
|
// the Message interface. See MsgBlockLocator for details.
|
||||||
func NewMsgBlockLocator(locatorHashes []*daghash.Hash) *MsgBlockLocator {
|
func NewMsgBlockLocator(locatorHashes []*externalapi.DomainHash) *MsgBlockLocator {
|
||||||
return &MsgBlockLocator{
|
return &MsgBlockLocator{
|
||||||
BlockLocatorHashes: locatorHashes,
|
BlockLocatorHashes: locatorHashes,
|
||||||
}
|
}
|
||||||
@@ -1,21 +1,22 @@
|
|||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestBlockLocator tests the MsgBlockLocator API.
|
// TestBlockLocator tests the MsgBlockLocator API.
|
||||||
func TestBlockLocator(t *testing.T) {
|
func TestBlockLocator(t *testing.T) {
|
||||||
hashStr := "000000000002e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0"
|
hashStr := "000000000002e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0"
|
||||||
locatorHash, err := daghash.NewHashFromStr(hashStr)
|
locatorHash, err := externalapi.NewDomainHashFromString(hashStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("NewHashFromStr: %v", err)
|
t.Errorf("NewHashFromStr: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
msg := NewMsgBlockLocator([]*daghash.Hash{locatorHash})
|
msg := NewMsgBlockLocator([]*externalapi.DomainHash{locatorHash})
|
||||||
|
|
||||||
// Ensure the command is expected value.
|
// Ensure the command is expected value.
|
||||||
wantCmd := MessageCommand(10)
|
wantCmd := MessageCommand(10)
|
||||||
22
app/appmessage/p2p_msgdoneheaders.go
Normal file
22
app/appmessage/p2p_msgdoneheaders.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
// MsgDoneHeaders implements the Message interface and represents a kaspa
|
||||||
|
// DoneHeaders message. It is used to notify the IBD syncing peer that the
|
||||||
|
// syncer sent all the requested headers.
|
||||||
|
//
|
||||||
|
// This message has no payload.
|
||||||
|
type MsgDoneHeaders struct {
|
||||||
|
baseMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message. This is part
|
||||||
|
// of the Message interface implementation.
|
||||||
|
func (msg *MsgDoneHeaders) Command() MessageCommand {
|
||||||
|
return CmdDoneHeaders
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMsgDoneHeaders returns a new kaspa DoneIBDBlocks message that conforms to the
|
||||||
|
// Message interface.
|
||||||
|
func NewMsgDoneHeaders() *MsgDoneHeaders {
|
||||||
|
return &MsgDoneHeaders{}
|
||||||
|
}
|
||||||
16
app/appmessage/p2p_msgdonepruningpointutxosetchunks.go
Normal file
16
app/appmessage/p2p_msgdonepruningpointutxosetchunks.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
// MsgDonePruningPointUTXOSetChunks represents a kaspa DonePruningPointUTXOSetChunks message
|
||||||
|
type MsgDonePruningPointUTXOSetChunks struct {
|
||||||
|
baseMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *MsgDonePruningPointUTXOSetChunks) Command() MessageCommand {
|
||||||
|
return CmdDonePruningPointUTXOSetChunks
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMsgDonePruningPointUTXOSetChunks returns a new MsgDonePruningPointUTXOSetChunks.
|
||||||
|
func NewMsgDonePruningPointUTXOSetChunks() *MsgDonePruningPointUTXOSetChunks {
|
||||||
|
return &MsgDonePruningPointUTXOSetChunks{}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
// MsgIBDBlock implements the Message interface and represents a kaspa
|
// MsgIBDBlock implements the Message interface and represents a kaspa
|
||||||
// ibdblock message. It is used to deliver block and transaction information in
|
// ibdblock message. It is used to deliver block and transaction information in
|
||||||
@@ -2,10 +2,9 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -26,7 +25,7 @@ func TestIBDBlock(t *testing.T) {
|
|||||||
bh := NewBlockHeader(1, parentHashes, hashMerkleRoot, acceptedIDMerkleRoot, utxoCommitment, bits, nonce)
|
bh := NewBlockHeader(1, parentHashes, hashMerkleRoot, acceptedIDMerkleRoot, utxoCommitment, bits, nonce)
|
||||||
|
|
||||||
// Ensure the command is expected value.
|
// Ensure the command is expected value.
|
||||||
wantCmd := MessageCommand(17)
|
wantCmd := MessageCommand(15)
|
||||||
msg := NewMsgIBDBlock(NewMsgBlock(bh))
|
msg := NewMsgIBDBlock(NewMsgBlock(bh))
|
||||||
if cmd := msg.Command(); cmd != wantCmd {
|
if cmd := msg.Command(); cmd != wantCmd {
|
||||||
t.Errorf("NewMsgIBDBlock: wrong command - got %v want %v",
|
t.Errorf("NewMsgIBDBlock: wrong command - got %v want %v",
|
||||||
@@ -64,55 +63,3 @@ func TestIBDBlock(t *testing.T) {
|
|||||||
len(msg.Transactions), 0)
|
len(msg.Transactions), 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestIBDBlockEncoding tests the MsgIBDBlock domainmessage encode and decode for various numbers
|
|
||||||
// of transaction inputs and outputs and protocol versions.
|
|
||||||
func TestIBDBlockEncoding(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
in *MsgIBDBlock // Message to encode
|
|
||||||
out *MsgIBDBlock // Expected decoded message
|
|
||||||
buf []byte // Encoded value
|
|
||||||
txLocs []TxLoc // Expected transaction locations
|
|
||||||
pver uint32 // Protocol version for domainmessage encoding
|
|
||||||
}{
|
|
||||||
// Latest protocol version.
|
|
||||||
{
|
|
||||||
&MsgIBDBlock{MsgBlock: &blockOne},
|
|
||||||
&MsgIBDBlock{MsgBlock: &blockOne},
|
|
||||||
blockOneBytes,
|
|
||||||
blockOneTxLocs,
|
|
||||||
ProtocolVersion,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Logf("Running %d tests", len(tests))
|
|
||||||
for i, test := range tests {
|
|
||||||
// Encode the message to domainmessage format.
|
|
||||||
var buf bytes.Buffer
|
|
||||||
err := test.in.KaspaEncode(&buf, test.pver)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("KaspaEncode #%d error %v", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !bytes.Equal(buf.Bytes(), test.buf) {
|
|
||||||
t.Errorf("KaspaEncode #%d\n got: %s want: %s", i,
|
|
||||||
spew.Sdump(buf.Bytes()), spew.Sdump(test.buf))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode the message from domainmessage format.
|
|
||||||
var msg MsgIBDBlock
|
|
||||||
msg.MsgBlock = new(MsgBlock)
|
|
||||||
rbuf := bytes.NewReader(test.buf)
|
|
||||||
err = msg.KaspaDecode(rbuf, test.pver)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("KaspaDecode #%d error %v", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(&msg, test.out) {
|
|
||||||
t.Errorf("KaspaDecode #%d\n got: %s want: %s", i,
|
|
||||||
spew.Sdump(&msg), spew.Sdump(test.out))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
27
app/appmessage/p2p_msgibdblocklocator.go
Normal file
27
app/appmessage/p2p_msgibdblocklocator.go
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MsgIBDBlockLocator represents a kaspa ibdBlockLocator message
|
||||||
|
type MsgIBDBlockLocator struct {
|
||||||
|
baseMessage
|
||||||
|
TargetHash *externalapi.DomainHash
|
||||||
|
BlockLocatorHashes []*externalapi.DomainHash
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *MsgIBDBlockLocator) Command() MessageCommand {
|
||||||
|
return CmdIBDBlockLocator
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMsgIBDBlockLocator returns a new kaspa ibdBlockLocator message
|
||||||
|
func NewMsgIBDBlockLocator(targetHash *externalapi.DomainHash,
|
||||||
|
blockLocatorHashes []*externalapi.DomainHash) *MsgIBDBlockLocator {
|
||||||
|
|
||||||
|
return &MsgIBDBlockLocator{
|
||||||
|
TargetHash: targetHash,
|
||||||
|
BlockLocatorHashes: blockLocatorHashes,
|
||||||
|
}
|
||||||
|
}
|
||||||
23
app/appmessage/p2p_msgibdblocklocatorhighesthash.go
Normal file
23
app/appmessage/p2p_msgibdblocklocatorhighesthash.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MsgIBDBlockLocatorHighestHash represents a kaspa BlockLocatorHighestHash message
|
||||||
|
type MsgIBDBlockLocatorHighestHash struct {
|
||||||
|
baseMessage
|
||||||
|
HighestHash *externalapi.DomainHash
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *MsgIBDBlockLocatorHighestHash) Command() MessageCommand {
|
||||||
|
return CmdIBDBlockLocatorHighestHash
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMsgIBDBlockLocatorHighestHash returns a new BlockLocatorHighestHash message
|
||||||
|
func NewMsgIBDBlockLocatorHighestHash(highestHash *externalapi.DomainHash) *MsgIBDBlockLocatorHighestHash {
|
||||||
|
return &MsgIBDBlockLocatorHighestHash{
|
||||||
|
HighestHash: highestHash,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MsgInvRelayBlock implements the Message interface and represents a kaspa
|
// MsgInvRelayBlock implements the Message interface and represents a kaspa
|
||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
// by sending their hash, and let the receiving node decide if it needs it.
|
// by sending their hash, and let the receiving node decide if it needs it.
|
||||||
type MsgInvRelayBlock struct {
|
type MsgInvRelayBlock struct {
|
||||||
baseMessage
|
baseMessage
|
||||||
Hash *daghash.Hash
|
Hash *externalapi.DomainHash
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command returns the protocol command string for the message. This is part
|
// Command returns the protocol command string for the message. This is part
|
||||||
@@ -20,7 +20,7 @@ func (msg *MsgInvRelayBlock) Command() MessageCommand {
|
|||||||
|
|
||||||
// NewMsgInvBlock returns a new kaspa invrelblk message that conforms to
|
// NewMsgInvBlock returns a new kaspa invrelblk message that conforms to
|
||||||
// the Message interface. See MsgInvRelayBlock for details.
|
// the Message interface. See MsgInvRelayBlock for details.
|
||||||
func NewMsgInvBlock(hash *daghash.Hash) *MsgInvRelayBlock {
|
func NewMsgInvBlock(hash *externalapi.DomainHash) *MsgInvRelayBlock {
|
||||||
return &MsgInvRelayBlock{
|
return &MsgInvRelayBlock{
|
||||||
Hash: hash,
|
Hash: hash,
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MaxInvPerTxInvMsg is the maximum number of hashes that can
|
// MaxInvPerTxInvMsg is the maximum number of hashes that can
|
||||||
@@ -13,7 +13,7 @@ const MaxInvPerTxInvMsg = MaxInvPerMsg
|
|||||||
// by sending their ID, and let the receiving node decide if it needs it.
|
// by sending their ID, and let the receiving node decide if it needs it.
|
||||||
type MsgInvTransaction struct {
|
type MsgInvTransaction struct {
|
||||||
baseMessage
|
baseMessage
|
||||||
TxIDs []*daghash.TxID
|
TxIDs []*externalapi.DomainTransactionID
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command returns the protocol command string for the message. This is part
|
// Command returns the protocol command string for the message. This is part
|
||||||
@@ -24,7 +24,7 @@ func (msg *MsgInvTransaction) Command() MessageCommand {
|
|||||||
|
|
||||||
// NewMsgInvTransaction returns a new kaspa TxInv message that conforms to
|
// NewMsgInvTransaction returns a new kaspa TxInv message that conforms to
|
||||||
// the Message interface. See MsgInvTransaction for details.
|
// the Message interface. See MsgInvTransaction for details.
|
||||||
func NewMsgInvTransaction(ids []*daghash.TxID) *MsgInvTransaction {
|
func NewMsgInvTransaction(ids []*externalapi.DomainTransactionID) *MsgInvTransaction {
|
||||||
return &MsgInvTransaction{
|
return &MsgInvTransaction{
|
||||||
TxIDs: ids,
|
TxIDs: ids,
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
// MsgPing implements the Message interface and represents a kaspa ping
|
// MsgPing implements the Message interface and represents a kaspa ping
|
||||||
// message.
|
// message.
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
// MsgPong implements the Message interface and represents a kaspa pong
|
// MsgPong implements the Message interface and represents a kaspa pong
|
||||||
// message which is used primarily to confirm that a connection is still valid
|
// message which is used primarily to confirm that a connection is still valid
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
23
app/appmessage/p2p_msgpruningpointhash.go
Normal file
23
app/appmessage/p2p_msgpruningpointhash.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MsgPruningPointHashMessage represents a kaspa PruningPointHash message
|
||||||
|
type MsgPruningPointHashMessage struct {
|
||||||
|
baseMessage
|
||||||
|
Hash *externalapi.DomainHash
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *MsgPruningPointHashMessage) Command() MessageCommand {
|
||||||
|
return CmdPruningPointHash
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPruningPointHashMessage returns a new kaspa PruningPointHash message
|
||||||
|
func NewPruningPointHashMessage(hash *externalapi.DomainHash) *MsgPruningPointHashMessage {
|
||||||
|
return &MsgPruningPointHashMessage{
|
||||||
|
Hash: hash,
|
||||||
|
}
|
||||||
|
}
|
||||||
36
app/appmessage/p2p_msgpruningpointutxosetchunk.go
Normal file
36
app/appmessage/p2p_msgpruningpointutxosetchunk.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
|
||||||
|
// MsgPruningPointUTXOSetChunk represents a kaspa PruningPointUTXOSetChunk message
|
||||||
|
type MsgPruningPointUTXOSetChunk struct {
|
||||||
|
baseMessage
|
||||||
|
OutpointAndUTXOEntryPairs []*OutpointAndUTXOEntryPair
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *MsgPruningPointUTXOSetChunk) Command() MessageCommand {
|
||||||
|
return CmdPruningPointUTXOSetChunk
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMsgPruningPointUTXOSetChunk returns a new MsgPruningPointUTXOSetChunk.
|
||||||
|
func NewMsgPruningPointUTXOSetChunk(outpointAndUTXOEntryPairs []*OutpointAndUTXOEntryPair) *MsgPruningPointUTXOSetChunk {
|
||||||
|
return &MsgPruningPointUTXOSetChunk{
|
||||||
|
OutpointAndUTXOEntryPairs: outpointAndUTXOEntryPairs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OutpointAndUTXOEntryPair is an outpoint along with its
|
||||||
|
// respective UTXO entry
|
||||||
|
type OutpointAndUTXOEntryPair struct {
|
||||||
|
Outpoint *Outpoint
|
||||||
|
UTXOEntry *UTXOEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
// UTXOEntry houses details about an individual transaction output in a UTXO
|
||||||
|
type UTXOEntry struct {
|
||||||
|
Amount uint64
|
||||||
|
ScriptPublicKey *externalapi.ScriptPublicKey
|
||||||
|
BlockBlueScore uint64
|
||||||
|
IsCoinbase bool
|
||||||
|
}
|
||||||
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,10 +2,10 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/util/subnetworkid"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MsgRequestAddresses implements the Message interface and represents a kaspa
|
// MsgRequestAddresses implements the Message interface and represents a kaspa
|
||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
type MsgRequestAddresses struct {
|
type MsgRequestAddresses struct {
|
||||||
baseMessage
|
baseMessage
|
||||||
IncludeAllSubnetworks bool
|
IncludeAllSubnetworks bool
|
||||||
SubnetworkID *subnetworkid.SubnetworkID
|
SubnetworkID *externalapi.DomainSubnetworkID
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command returns the protocol command string for the message. This is part
|
// Command returns the protocol command string for the message. This is part
|
||||||
@@ -28,7 +28,7 @@ func (msg *MsgRequestAddresses) Command() MessageCommand {
|
|||||||
|
|
||||||
// NewMsgRequestAddresses returns a new kaspa RequestAddresses message that conforms to the
|
// NewMsgRequestAddresses returns a new kaspa RequestAddresses message that conforms to the
|
||||||
// Message interface. See MsgRequestAddresses for details.
|
// Message interface. See MsgRequestAddresses for details.
|
||||||
func NewMsgRequestAddresses(includeAllSubnetworks bool, subnetworkID *subnetworkid.SubnetworkID) *MsgRequestAddresses {
|
func NewMsgRequestAddresses(includeAllSubnetworks bool, subnetworkID *externalapi.DomainSubnetworkID) *MsgRequestAddresses {
|
||||||
return &MsgRequestAddresses{
|
return &MsgRequestAddresses{
|
||||||
IncludeAllSubnetworks: includeAllSubnetworks,
|
IncludeAllSubnetworks: includeAllSubnetworks,
|
||||||
SubnetworkID: subnetworkID,
|
SubnetworkID: subnetworkID,
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
@@ -1,17 +1,18 @@
|
|||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MsgRequestBlockLocator implements the Message interface and represents a kaspa
|
// MsgRequestBlockLocator implements the Message interface and represents a kaspa
|
||||||
// RequestBlockLocator message. It is used to request a block locator between high
|
// RequestBlockLocator message. It is used to request a block locator between low
|
||||||
// and low hash.
|
// and high hash.
|
||||||
// The locator is returned via a locator message (MsgBlockLocator).
|
// The locator is returned via a locator message (MsgBlockLocator).
|
||||||
type MsgRequestBlockLocator struct {
|
type MsgRequestBlockLocator struct {
|
||||||
baseMessage
|
baseMessage
|
||||||
HighHash *daghash.Hash
|
LowHash *externalapi.DomainHash
|
||||||
LowHash *daghash.Hash
|
HighHash *externalapi.DomainHash
|
||||||
|
Limit uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command returns the protocol command string for the message. This is part
|
// Command returns the protocol command string for the message. This is part
|
||||||
@@ -23,9 +24,10 @@ func (msg *MsgRequestBlockLocator) Command() MessageCommand {
|
|||||||
// NewMsgRequestBlockLocator returns a new RequestBlockLocator message that conforms to the
|
// NewMsgRequestBlockLocator returns a new RequestBlockLocator message that conforms to the
|
||||||
// Message interface using the passed parameters and defaults for the remaining
|
// Message interface using the passed parameters and defaults for the remaining
|
||||||
// fields.
|
// fields.
|
||||||
func NewMsgRequestBlockLocator(highHash, lowHash *daghash.Hash) *MsgRequestBlockLocator {
|
func NewMsgRequestBlockLocator(lowHash, highHash *externalapi.DomainHash, limit uint32) *MsgRequestBlockLocator {
|
||||||
return &MsgRequestBlockLocator{
|
return &MsgRequestBlockLocator{
|
||||||
HighHash: highHash,
|
|
||||||
LowHash: lowHash,
|
LowHash: lowHash,
|
||||||
|
HighHash: highHash,
|
||||||
|
Limit: limit,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestRequestBlockLocator tests the MsgRequestBlockLocator API.
|
// TestRequestBlockLocator tests the MsgRequestBlockLocator API.
|
||||||
func TestRequestBlockLocator(t *testing.T) {
|
func TestRequestBlockLocator(t *testing.T) {
|
||||||
hashStr := "000000000002e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0"
|
hashStr := "000000000002e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0"
|
||||||
highHash, err := daghash.NewHashFromStr(hashStr)
|
highHash, err := externalapi.NewDomainHashFromString(hashStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("NewHashFromStr: %v", err)
|
t.Errorf("NewHashFromStr: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the command is expected value.
|
// Ensure the command is expected value.
|
||||||
wantCmd := MessageCommand(9)
|
wantCmd := MessageCommand(9)
|
||||||
msg := NewMsgRequestBlockLocator(highHash, &daghash.ZeroHash)
|
msg := NewMsgRequestBlockLocator(highHash, &externalapi.DomainHash{}, 0)
|
||||||
if cmd := msg.Command(); cmd != wantCmd {
|
if cmd := msg.Command(); cmd != wantCmd {
|
||||||
t.Errorf("NewMsgRequestBlockLocator: wrong command - got %v want %v",
|
t.Errorf("NewMsgRequestBlockLocator: wrong command - got %v want %v",
|
||||||
cmd, wantCmd)
|
cmd, wantCmd)
|
||||||
34
app/appmessage/p2p_msgrequestheaders.go
Normal file
34
app/appmessage/p2p_msgrequestheaders.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// 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 (
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MsgRequestHeaders implements the Message interface and represents a kaspa
|
||||||
|
// RequestHeaders message. It is used to request a list of blocks starting after the
|
||||||
|
// low hash and until the high hash.
|
||||||
|
type MsgRequestHeaders struct {
|
||||||
|
baseMessage
|
||||||
|
LowHash *externalapi.DomainHash
|
||||||
|
HighHash *externalapi.DomainHash
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message. This is part
|
||||||
|
// of the Message interface implementation.
|
||||||
|
func (msg *MsgRequestHeaders) Command() MessageCommand {
|
||||||
|
return CmdRequestHeaders
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMsgRequstHeaders returns a new kaspa RequestHeaders message that conforms to the
|
||||||
|
// Message interface using the passed parameters and defaults for the remaining
|
||||||
|
// fields.
|
||||||
|
func NewMsgRequstHeaders(lowHash, highHash *externalapi.DomainHash) *MsgRequestHeaders {
|
||||||
|
return &MsgRequestHeaders{
|
||||||
|
LowHash: lowHash,
|
||||||
|
HighHash: highHash,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,39 +2,39 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestRequstIBDBlocks tests the MsgRequestIBDBlocks API.
|
// TestRequstIBDBlocks tests the MsgRequestHeaders API.
|
||||||
func TestRequstIBDBlocks(t *testing.T) {
|
func TestRequstIBDBlocks(t *testing.T) {
|
||||||
hashStr := "000000000002e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0"
|
hashStr := "000000000002e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0"
|
||||||
lowHash, err := daghash.NewHashFromStr(hashStr)
|
lowHash, err := externalapi.NewDomainHashFromString(hashStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("NewHashFromStr: %v", err)
|
t.Errorf("NewHashFromStr: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
hashStr = "3ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
|
hashStr = "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
|
||||||
highHash, err := daghash.NewHashFromStr(hashStr)
|
highHash, err := externalapi.NewDomainHashFromString(hashStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("NewHashFromStr: %v", err)
|
t.Errorf("NewHashFromStr: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we get the same data back out.
|
// Ensure we get the same data back out.
|
||||||
msg := NewMsgRequstIBDBlocks(lowHash, highHash)
|
msg := NewMsgRequstHeaders(lowHash, highHash)
|
||||||
if !msg.HighHash.IsEqual(highHash) {
|
if !msg.HighHash.Equal(highHash) {
|
||||||
t.Errorf("NewMsgRequstIBDBlocks: wrong high hash - got %v, want %v",
|
t.Errorf("NewMsgRequstHeaders: wrong high hash - got %v, want %v",
|
||||||
msg.HighHash, highHash)
|
msg.HighHash, highHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the command is expected value.
|
// Ensure the command is expected value.
|
||||||
wantCmd := MessageCommand(4)
|
wantCmd := MessageCommand(4)
|
||||||
if cmd := msg.Command(); cmd != wantCmd {
|
if cmd := msg.Command(); cmd != wantCmd {
|
||||||
t.Errorf("NewMsgRequstIBDBlocks: wrong command - got %v want %v",
|
t.Errorf("NewMsgRequstHeaders: wrong command - got %v want %v",
|
||||||
cmd, wantCmd)
|
cmd, wantCmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
26
app/appmessage/p2p_msgrequestibdblocks.go
Normal file
26
app/appmessage/p2p_msgrequestibdblocks.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MsgRequestIBDBlocks implements the Message interface and represents a kaspa
|
||||||
|
// RequestIBDBlocks message. It is used to request blocks as part of the IBD
|
||||||
|
// protocol.
|
||||||
|
type MsgRequestIBDBlocks struct {
|
||||||
|
baseMessage
|
||||||
|
Hashes []*externalapi.DomainHash
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message. This is part
|
||||||
|
// of the Message interface implementation.
|
||||||
|
func (msg *MsgRequestIBDBlocks) Command() MessageCommand {
|
||||||
|
return CmdRequestIBDBlocks
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMsgRequestIBDBlocks returns a new MsgRequestIBDBlocks.
|
||||||
|
func NewMsgRequestIBDBlocks(hashes []*externalapi.DomainHash) *MsgRequestIBDBlocks {
|
||||||
|
return &MsgRequestIBDBlocks{
|
||||||
|
Hashes: hashes,
|
||||||
|
}
|
||||||
|
}
|
||||||
22
app/appmessage/p2p_msgrequestnextheaders.go
Normal file
22
app/appmessage/p2p_msgrequestnextheaders.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
// MsgRequestNextHeaders implements the Message interface and represents a kaspa
|
||||||
|
// RequestNextHeaders message. It is used to notify the IBD syncer peer to send
|
||||||
|
// more headers.
|
||||||
|
//
|
||||||
|
// This message has no payload.
|
||||||
|
type MsgRequestNextHeaders struct {
|
||||||
|
baseMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message. This is part
|
||||||
|
// of the Message interface implementation.
|
||||||
|
func (msg *MsgRequestNextHeaders) Command() MessageCommand {
|
||||||
|
return CmdRequestNextHeaders
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMsgRequestNextHeaders returns a new kaspa RequestNextHeaders message that conforms to the
|
||||||
|
// Message interface.
|
||||||
|
func NewMsgRequestNextHeaders() *MsgRequestNextHeaders {
|
||||||
|
return &MsgRequestNextHeaders{}
|
||||||
|
}
|
||||||
16
app/appmessage/p2p_msgrequestnextpruningpointutxosetchunk.go
Normal file
16
app/appmessage/p2p_msgrequestnextpruningpointutxosetchunk.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
// MsgRequestNextPruningPointUTXOSetChunk represents a kaspa RequestNextPruningPointUTXOSetChunk message
|
||||||
|
type MsgRequestNextPruningPointUTXOSetChunk struct {
|
||||||
|
baseMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *MsgRequestNextPruningPointUTXOSetChunk) Command() MessageCommand {
|
||||||
|
return CmdRequestNextPruningPointUTXOSetChunk
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMsgRequestNextPruningPointUTXOSetChunk returns a new MsgRequestNextPruningPointUTXOSetChunk.
|
||||||
|
func NewMsgRequestNextPruningPointUTXOSetChunk() *MsgRequestNextPruningPointUTXOSetChunk {
|
||||||
|
return &MsgRequestNextPruningPointUTXOSetChunk{}
|
||||||
|
}
|
||||||
23
app/appmessage/p2p_msgrequestpruningpointutxosetandblock.go
Normal file
23
app/appmessage/p2p_msgrequestpruningpointutxosetandblock.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MsgRequestPruningPointUTXOSetAndBlock represents a kaspa RequestPruningPointUTXOSetAndBlock message
|
||||||
|
type MsgRequestPruningPointUTXOSetAndBlock struct {
|
||||||
|
baseMessage
|
||||||
|
PruningPointHash *externalapi.DomainHash
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *MsgRequestPruningPointUTXOSetAndBlock) Command() MessageCommand {
|
||||||
|
return CmdRequestPruningPointUTXOSetAndBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMsgRequestPruningPointUTXOSetAndBlock returns a new MsgRequestPruningPointUTXOSetAndBlock
|
||||||
|
func NewMsgRequestPruningPointUTXOSetAndBlock(pruningPointHash *externalapi.DomainHash) *MsgRequestPruningPointUTXOSetAndBlock {
|
||||||
|
return &MsgRequestPruningPointUTXOSetAndBlock{
|
||||||
|
PruningPointHash: pruningPointHash,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,19 +1,19 @@
|
|||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MsgRequestRelayBlocksHashes is the maximum number of hashes that can
|
// MaxRequestRelayBlocksHashes is the maximum number of hashes that can
|
||||||
// be in a single RequestRelayBlocks message.
|
// be in a single RequestRelayBlocks message.
|
||||||
const MsgRequestRelayBlocksHashes = MaxInvPerMsg
|
const MaxRequestRelayBlocksHashes = MaxInvPerMsg
|
||||||
|
|
||||||
// MsgRequestRelayBlocks implements the Message interface and represents a kaspa
|
// MsgRequestRelayBlocks implements the Message interface and represents a kaspa
|
||||||
// RequestRelayBlocks message. It is used to request blocks as part of the block
|
// RequestRelayBlocks message. It is used to request blocks as part of the block
|
||||||
// relay protocol.
|
// relay protocol.
|
||||||
type MsgRequestRelayBlocks struct {
|
type MsgRequestRelayBlocks struct {
|
||||||
baseMessage
|
baseMessage
|
||||||
Hashes []*daghash.Hash
|
Hashes []*externalapi.DomainHash
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command returns the protocol command string for the message. This is part
|
// Command returns the protocol command string for the message. This is part
|
||||||
@@ -24,7 +24,7 @@ func (msg *MsgRequestRelayBlocks) Command() MessageCommand {
|
|||||||
|
|
||||||
// NewMsgRequestRelayBlocks returns a new kaspa RequestRelayBlocks message that conforms to
|
// NewMsgRequestRelayBlocks returns a new kaspa RequestRelayBlocks message that conforms to
|
||||||
// the Message interface. See MsgRequestRelayBlocks for details.
|
// the Message interface. See MsgRequestRelayBlocks for details.
|
||||||
func NewMsgRequestRelayBlocks(hashes []*daghash.Hash) *MsgRequestRelayBlocks {
|
func NewMsgRequestRelayBlocks(hashes []*externalapi.DomainHash) *MsgRequestRelayBlocks {
|
||||||
return &MsgRequestRelayBlocks{
|
return &MsgRequestRelayBlocks{
|
||||||
Hashes: hashes,
|
Hashes: hashes,
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MaxInvPerRequestTransactionsMsg is the maximum number of hashes that can
|
// MaxInvPerRequestTransactionsMsg is the maximum number of hashes that can
|
||||||
@@ -13,7 +13,7 @@ const MaxInvPerRequestTransactionsMsg = MaxInvPerMsg
|
|||||||
// transactions relay protocol.
|
// transactions relay protocol.
|
||||||
type MsgRequestTransactions struct {
|
type MsgRequestTransactions struct {
|
||||||
baseMessage
|
baseMessage
|
||||||
IDs []*daghash.TxID
|
IDs []*externalapi.DomainTransactionID
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command returns the protocol command string for the message. This is part
|
// Command returns the protocol command string for the message. This is part
|
||||||
@@ -24,7 +24,7 @@ func (msg *MsgRequestTransactions) Command() MessageCommand {
|
|||||||
|
|
||||||
// NewMsgRequestTransactions returns a new kaspa RequestTransactions message that conforms to
|
// NewMsgRequestTransactions returns a new kaspa RequestTransactions message that conforms to
|
||||||
// the Message interface. See MsgRequestTransactions for details.
|
// the Message interface. See MsgRequestTransactions for details.
|
||||||
func NewMsgRequestTransactions(ids []*daghash.TxID) *MsgRequestTransactions {
|
func NewMsgRequestTransactions(ids []*externalapi.DomainTransactionID) *MsgRequestTransactions {
|
||||||
return &MsgRequestTransactions{
|
return &MsgRequestTransactions{
|
||||||
IDs: ids,
|
IDs: ids,
|
||||||
}
|
}
|
||||||
@@ -2,17 +2,17 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MsgTransactionNotFound defines a kaspa TransactionNotFound message which is sent in response to
|
// 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.
|
// a RequestTransactions message if any of the requested data in not available on the peer.
|
||||||
type MsgTransactionNotFound struct {
|
type MsgTransactionNotFound struct {
|
||||||
baseMessage
|
baseMessage
|
||||||
ID *daghash.TxID
|
ID *externalapi.DomainTransactionID
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command returns the protocol command string for the message. This is part
|
// Command returns the protocol command string for the message. This is part
|
||||||
@@ -23,7 +23,7 @@ func (msg *MsgTransactionNotFound) Command() MessageCommand {
|
|||||||
|
|
||||||
// NewMsgTransactionNotFound returns a new kaspa transactionsnotfound message that conforms to the
|
// NewMsgTransactionNotFound returns a new kaspa transactionsnotfound message that conforms to the
|
||||||
// Message interface. See MsgTransactionNotFound for details.
|
// Message interface. See MsgTransactionNotFound for details.
|
||||||
func NewMsgTransactionNotFound(id *daghash.TxID) *MsgTransactionNotFound {
|
func NewMsgTransactionNotFound(id *externalapi.DomainTransactionID) *MsgTransactionNotFound {
|
||||||
return &MsgTransactionNotFound{
|
return &MsgTransactionNotFound{
|
||||||
ID: id,
|
ID: id,
|
||||||
}
|
}
|
||||||
325
app/appmessage/p2p_msgtx.go
Normal file
325
app/appmessage/p2p_msgtx.go
Normal file
@@ -0,0 +1,325 @@
|
|||||||
|
// 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 (
|
||||||
|
"encoding/binary"
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/utils/hashes"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// MaxPrevOutIndex is the maximum index the index field of a previous
|
||||||
|
// outpoint can be.
|
||||||
|
MaxPrevOutIndex uint32 = 0xffffffff
|
||||||
|
|
||||||
|
// defaultTxInOutAlloc is the default size used for the backing array for
|
||||||
|
// transaction inputs and outputs. The array will dynamically grow as needed,
|
||||||
|
// but this figure is intended to provide enough space for the number of
|
||||||
|
// inputs and outputs in a typical transaction without needing to grow the
|
||||||
|
// backing array multiple times.
|
||||||
|
defaultTxInOutAlloc = 15
|
||||||
|
|
||||||
|
// minTxInPayload is the minimum payload size for a transaction input.
|
||||||
|
// PreviousOutpoint.TxID + PreviousOutpoint.Index 4 bytes + Varint for
|
||||||
|
// SignatureScript length 1 byte + Sequence 4 bytes.
|
||||||
|
minTxInPayload = 9 + externalapi.DomainHashSize
|
||||||
|
|
||||||
|
// maxTxInPerMessage is the maximum number of transactions inputs that
|
||||||
|
// a transaction which fits into a message could possibly have.
|
||||||
|
maxTxInPerMessage = (MaxMessagePayload / minTxInPayload) + 1
|
||||||
|
|
||||||
|
// MinTxOutPayload is the minimum payload size for a transaction output.
|
||||||
|
// Value 8 bytes + version 2 bytes + Varint for ScriptPublicKey length 1 byte.
|
||||||
|
MinTxOutPayload = 11
|
||||||
|
|
||||||
|
// maxTxOutPerMessage is the maximum number of transactions outputs that
|
||||||
|
// a transaction which fits into a message could possibly have.
|
||||||
|
maxTxOutPerMessage = (MaxMessagePayload / MinTxOutPayload) + 1
|
||||||
|
|
||||||
|
// minTxPayload is the minimum payload size for a transaction. Note
|
||||||
|
// that any realistically usable transaction must have at least one
|
||||||
|
// input or output, but that is a rule enforced at a higher layer, so
|
||||||
|
// it is intentionally not included here.
|
||||||
|
// Version 4 bytes + Varint number of transaction inputs 1 byte + Varint
|
||||||
|
// number of transaction outputs 1 byte + LockTime 4 bytes + min input
|
||||||
|
// payload + min output payload.
|
||||||
|
minTxPayload = 10
|
||||||
|
)
|
||||||
|
|
||||||
|
// Outpoint defines a kaspa data type that is used to track previous
|
||||||
|
// transaction outputs.
|
||||||
|
type Outpoint struct {
|
||||||
|
TxID externalapi.DomainTransactionID
|
||||||
|
Index uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOutpoint returns a new kaspa transaction outpoint point with the
|
||||||
|
// provided hash and index.
|
||||||
|
func NewOutpoint(txID *externalapi.DomainTransactionID, index uint32) *Outpoint {
|
||||||
|
return &Outpoint{
|
||||||
|
TxID: *txID,
|
||||||
|
Index: index,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns the Outpoint in the human-readable form "txID:index".
|
||||||
|
func (o Outpoint) String() string {
|
||||||
|
// Allocate enough for ID string, colon, and 10 digits. Although
|
||||||
|
// at the time of writing, the number of digits can be no greater than
|
||||||
|
// the length of the decimal representation of maxTxOutPerMessage, the
|
||||||
|
// maximum message payload may increase in the future and this
|
||||||
|
// optimization may go unnoticed, so allocate space for 10 decimal
|
||||||
|
// digits, which will fit any uint32.
|
||||||
|
buf := make([]byte, 2*externalapi.DomainHashSize+1, 2*externalapi.DomainHashSize+1+10)
|
||||||
|
copy(buf, o.TxID.String())
|
||||||
|
buf[2*externalapi.DomainHashSize] = ':'
|
||||||
|
buf = strconv.AppendUint(buf, uint64(o.Index), 10)
|
||||||
|
return string(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TxIn defines a kaspa transaction input.
|
||||||
|
type TxIn struct {
|
||||||
|
PreviousOutpoint Outpoint
|
||||||
|
SignatureScript []byte
|
||||||
|
Sequence uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTxIn returns a new kaspa transaction input with the provided
|
||||||
|
// previous outpoint point and signature script with a default sequence of
|
||||||
|
// MaxTxInSequenceNum.
|
||||||
|
func NewTxIn(prevOut *Outpoint, signatureScript []byte, sequence uint64) *TxIn {
|
||||||
|
return &TxIn{
|
||||||
|
PreviousOutpoint: *prevOut,
|
||||||
|
SignatureScript: signatureScript,
|
||||||
|
Sequence: sequence,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TxOut defines a kaspa transaction output.
|
||||||
|
type TxOut struct {
|
||||||
|
Value uint64
|
||||||
|
ScriptPubKey *externalapi.ScriptPublicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewTxOut returns a new kaspa transaction output with the provided
|
||||||
|
// transaction value and public key script.
|
||||||
|
func NewTxOut(value uint64, scriptPubKey *externalapi.ScriptPublicKey) *TxOut {
|
||||||
|
return &TxOut{
|
||||||
|
Value: value,
|
||||||
|
ScriptPubKey: scriptPubKey,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MsgTx implements the Message interface and represents a kaspa tx message.
|
||||||
|
// It is used to deliver transaction information in response to a getdata
|
||||||
|
// message (MsgGetData) for a given transaction.
|
||||||
|
//
|
||||||
|
// Use the AddTxIn and AddTxOut functions to build up the list of transaction
|
||||||
|
// inputs and outputs.
|
||||||
|
type MsgTx struct {
|
||||||
|
baseMessage
|
||||||
|
Version uint16
|
||||||
|
TxIn []*TxIn
|
||||||
|
TxOut []*TxOut
|
||||||
|
LockTime uint64
|
||||||
|
SubnetworkID externalapi.DomainSubnetworkID
|
||||||
|
Gas uint64
|
||||||
|
PayloadHash externalapi.DomainHash
|
||||||
|
Payload []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTxIn adds a transaction input to the message.
|
||||||
|
func (msg *MsgTx) AddTxIn(ti *TxIn) {
|
||||||
|
msg.TxIn = append(msg.TxIn, ti)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddTxOut adds a transaction output to the message.
|
||||||
|
func (msg *MsgTx) AddTxOut(to *TxOut) {
|
||||||
|
msg.TxOut = append(msg.TxOut, to)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCoinBase determines whether or not a transaction is a coinbase transaction. A coinbase
|
||||||
|
// transaction is a special transaction created by miners that distributes fees and block subsidy
|
||||||
|
// to the previous blocks' miners, and to specify the scriptPubKey that will be used to pay the current
|
||||||
|
// miner in future blocks. Each input of the coinbase transaction should set index to maximum
|
||||||
|
// value and reference the relevant block id, instead of previous transaction id.
|
||||||
|
func (msg *MsgTx) IsCoinBase() bool {
|
||||||
|
// A coinbase transaction must have subnetwork id SubnetworkIDCoinbase
|
||||||
|
return msg.SubnetworkID == subnetworks.SubnetworkIDCoinbase
|
||||||
|
}
|
||||||
|
|
||||||
|
// TxHash generates the Hash for the transaction.
|
||||||
|
func (msg *MsgTx) TxHash() *externalapi.DomainHash {
|
||||||
|
return consensushashing.TransactionHash(MsgTxToDomainTransaction(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TxID generates the Hash for the transaction without the signature script, gas and payload fields.
|
||||||
|
func (msg *MsgTx) TxID() *externalapi.DomainTransactionID {
|
||||||
|
return consensushashing.TransactionID(MsgTxToDomainTransaction(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy creates a deep copy of a transaction so that the original does not get
|
||||||
|
// modified when the copy is manipulated.
|
||||||
|
func (msg *MsgTx) Copy() *MsgTx {
|
||||||
|
// Create new tx and start by copying primitive values and making space
|
||||||
|
// for the transaction inputs and outputs.
|
||||||
|
newTx := MsgTx{
|
||||||
|
Version: msg.Version,
|
||||||
|
TxIn: make([]*TxIn, 0, len(msg.TxIn)),
|
||||||
|
TxOut: make([]*TxOut, 0, len(msg.TxOut)),
|
||||||
|
LockTime: msg.LockTime,
|
||||||
|
SubnetworkID: msg.SubnetworkID,
|
||||||
|
Gas: msg.Gas,
|
||||||
|
PayloadHash: msg.PayloadHash,
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg.Payload != nil {
|
||||||
|
newTx.Payload = make([]byte, len(msg.Payload))
|
||||||
|
copy(newTx.Payload, msg.Payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deep copy the old TxIn data.
|
||||||
|
for _, oldTxIn := range msg.TxIn {
|
||||||
|
// Deep copy the old previous outpoint.
|
||||||
|
oldOutpoint := oldTxIn.PreviousOutpoint
|
||||||
|
newOutpoint := Outpoint{}
|
||||||
|
newOutpoint.TxID = oldOutpoint.TxID
|
||||||
|
newOutpoint.Index = oldOutpoint.Index
|
||||||
|
|
||||||
|
// Deep copy the old signature script.
|
||||||
|
var newScript []byte
|
||||||
|
oldScript := oldTxIn.SignatureScript
|
||||||
|
oldScriptLen := len(oldScript)
|
||||||
|
if oldScriptLen > 0 {
|
||||||
|
newScript = make([]byte, oldScriptLen)
|
||||||
|
copy(newScript, oldScript[:oldScriptLen])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new txIn with the deep copied data.
|
||||||
|
newTxIn := TxIn{
|
||||||
|
PreviousOutpoint: newOutpoint,
|
||||||
|
SignatureScript: newScript,
|
||||||
|
Sequence: oldTxIn.Sequence,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, append this fully copied txin.
|
||||||
|
newTx.TxIn = append(newTx.TxIn, &newTxIn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deep copy the old TxOut data.
|
||||||
|
for _, oldTxOut := range msg.TxOut {
|
||||||
|
// Deep copy the old ScriptPublicKey
|
||||||
|
var newScript externalapi.ScriptPublicKey
|
||||||
|
oldScript := oldTxOut.ScriptPubKey
|
||||||
|
oldScriptLen := len(oldScript.Script)
|
||||||
|
if oldScriptLen > 0 {
|
||||||
|
newScript = externalapi.ScriptPublicKey{Script: make([]byte, oldScriptLen), Version: oldScript.Version}
|
||||||
|
copy(newScript.Script, oldScript.Script[:oldScriptLen])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new txOut with the deep copied data and append it to
|
||||||
|
// new Tx.
|
||||||
|
newTxOut := TxOut{
|
||||||
|
Value: oldTxOut.Value,
|
||||||
|
ScriptPubKey: &newScript,
|
||||||
|
}
|
||||||
|
newTx.TxOut = append(newTx.TxOut, &newTxOut)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &newTx
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message. This is part
|
||||||
|
// of the Message interface implementation.
|
||||||
|
func (msg *MsgTx) Command() MessageCommand {
|
||||||
|
return CmdTx
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxPayloadLength returns the maximum length the payload can be for the
|
||||||
|
// receiver. This is part of the Message interface implementation.
|
||||||
|
func (msg *MsgTx) MaxPayloadLength(pver uint32) uint32 {
|
||||||
|
return MaxMessagePayload
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsSubnetworkCompatible return true iff subnetworkID is one or more of the following:
|
||||||
|
// 1. The SupportsAll subnetwork (full node)
|
||||||
|
// 2. The native subnetwork
|
||||||
|
// 3. The transaction's subnetwork
|
||||||
|
func (msg *MsgTx) IsSubnetworkCompatible(subnetworkID *externalapi.DomainSubnetworkID) bool {
|
||||||
|
return subnetworkID == nil ||
|
||||||
|
subnetworkID.Equal(&subnetworks.SubnetworkIDNative) ||
|
||||||
|
subnetworkID.Equal(&msg.SubnetworkID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// newMsgTx returns a new tx message that conforms to the Message interface.
|
||||||
|
//
|
||||||
|
// All fields except version and gas has default values if nil is passed:
|
||||||
|
// txIn, txOut - empty arrays
|
||||||
|
// payload - an empty payload
|
||||||
|
//
|
||||||
|
// The payload hash is calculated automatically according to provided payload.
|
||||||
|
// Also, the lock time is set to zero to indicate the transaction is valid
|
||||||
|
// immediately as opposed to some time in future.
|
||||||
|
func newMsgTx(version uint16, txIn []*TxIn, txOut []*TxOut, subnetworkID *externalapi.DomainSubnetworkID,
|
||||||
|
gas uint64, payload []byte, lockTime uint64) *MsgTx {
|
||||||
|
|
||||||
|
if txIn == nil {
|
||||||
|
txIn = make([]*TxIn, 0, defaultTxInOutAlloc)
|
||||||
|
}
|
||||||
|
|
||||||
|
if txOut == nil {
|
||||||
|
txOut = make([]*TxOut, 0, defaultTxInOutAlloc)
|
||||||
|
}
|
||||||
|
|
||||||
|
var payloadHash externalapi.DomainHash
|
||||||
|
if *subnetworkID != subnetworks.SubnetworkIDNative {
|
||||||
|
payloadHash = *hashes.PayloadHash(payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &MsgTx{
|
||||||
|
Version: version,
|
||||||
|
TxIn: txIn,
|
||||||
|
TxOut: txOut,
|
||||||
|
SubnetworkID: *subnetworkID,
|
||||||
|
Gas: gas,
|
||||||
|
PayloadHash: payloadHash,
|
||||||
|
Payload: payload,
|
||||||
|
LockTime: lockTime,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNativeMsgTx returns a new tx message in the native subnetwork
|
||||||
|
func NewNativeMsgTx(version uint16, txIn []*TxIn, txOut []*TxOut) *MsgTx {
|
||||||
|
return newMsgTx(version, txIn, txOut, &subnetworks.SubnetworkIDNative, 0, nil, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSubnetworkMsgTx returns a new tx message in the specified subnetwork with specified gas and payload
|
||||||
|
func NewSubnetworkMsgTx(version uint16, txIn []*TxIn, txOut []*TxOut, subnetworkID *externalapi.DomainSubnetworkID,
|
||||||
|
gas uint64, payload []byte) *MsgTx {
|
||||||
|
|
||||||
|
return newMsgTx(version, txIn, txOut, subnetworkID, gas, payload, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNativeMsgTxWithLocktime returns a new tx message in the native subnetwork with a locktime.
|
||||||
|
//
|
||||||
|
// See newMsgTx for further documntation of the parameters
|
||||||
|
func NewNativeMsgTxWithLocktime(version uint16, txIn []*TxIn, txOut []*TxOut, locktime uint64) *MsgTx {
|
||||||
|
return newMsgTx(version, txIn, txOut, &subnetworks.SubnetworkIDNative, 0, nil, locktime)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRegistryMsgTx creates a new MsgTx that registers a new subnetwork
|
||||||
|
func NewRegistryMsgTx(version uint16, txIn []*TxIn, txOut []*TxOut, gasLimit uint64) *MsgTx {
|
||||||
|
payload := make([]byte, 8)
|
||||||
|
binary.LittleEndian.PutUint64(payload, gasLimit)
|
||||||
|
|
||||||
|
return NewSubnetworkMsgTx(version, txIn, txOut, &subnetworks.SubnetworkIDRegistry, 0, payload)
|
||||||
|
}
|
||||||
261
app/appmessage/p2p_msgtx_test.go
Normal file
261
app/appmessage/p2p_msgtx_test.go
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
// 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 (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks"
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionid"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestTx tests the MsgTx API.
|
||||||
|
func TestTx(t *testing.T) {
|
||||||
|
pver := ProtocolVersion
|
||||||
|
|
||||||
|
txIDStr := "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
|
||||||
|
txID, err := transactionid.FromString(txIDStr)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("NewTxIDFromStr: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the command is expected value.
|
||||||
|
wantCmd := MessageCommand(6)
|
||||||
|
msg := NewNativeMsgTx(1, nil, nil)
|
||||||
|
if cmd := msg.Command(); cmd != wantCmd {
|
||||||
|
t.Errorf("NewMsgAddresses: wrong command - got %v want %v",
|
||||||
|
cmd, wantCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure max payload is expected value for latest protocol version.
|
||||||
|
wantPayload := uint32(1024 * 1024 * 32)
|
||||||
|
maxPayload := msg.MaxPayloadLength(pver)
|
||||||
|
if maxPayload != wantPayload {
|
||||||
|
t.Errorf("MaxPayloadLength: wrong max payload length for "+
|
||||||
|
"protocol version %d - got %v, want %v", pver,
|
||||||
|
maxPayload, wantPayload)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure we get the same transaction outpoint data back out.
|
||||||
|
// NOTE: This is a block hash and made up index, but we're only
|
||||||
|
// testing package functionality.
|
||||||
|
prevOutIndex := uint32(1)
|
||||||
|
prevOut := NewOutpoint(txID, prevOutIndex)
|
||||||
|
if !prevOut.TxID.Equal(txID) {
|
||||||
|
t.Errorf("NewOutpoint: wrong ID - got %v, want %v",
|
||||||
|
spew.Sprint(&prevOut.TxID), spew.Sprint(txID))
|
||||||
|
}
|
||||||
|
if prevOut.Index != prevOutIndex {
|
||||||
|
t.Errorf("NewOutpoint: wrong index - got %v, want %v",
|
||||||
|
prevOut.Index, prevOutIndex)
|
||||||
|
}
|
||||||
|
prevOutStr := fmt.Sprintf("%s:%d", txID.String(), prevOutIndex)
|
||||||
|
if s := prevOut.String(); s != prevOutStr {
|
||||||
|
t.Errorf("Outpoint.String: unexpected result - got %v, "+
|
||||||
|
"want %v", s, prevOutStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure we get the same transaction input back out.
|
||||||
|
sigScript := []byte{0x04, 0x31, 0xdc, 0x00, 0x1b, 0x01, 0x62}
|
||||||
|
txIn := NewTxIn(prevOut, sigScript, constants.MaxTxInSequenceNum)
|
||||||
|
if !reflect.DeepEqual(&txIn.PreviousOutpoint, prevOut) {
|
||||||
|
t.Errorf("NewTxIn: wrong prev outpoint - got %v, want %v",
|
||||||
|
spew.Sprint(&txIn.PreviousOutpoint),
|
||||||
|
spew.Sprint(prevOut))
|
||||||
|
}
|
||||||
|
if !bytes.Equal(txIn.SignatureScript, sigScript) {
|
||||||
|
t.Errorf("NewTxIn: wrong signature script - got %v, want %v",
|
||||||
|
spew.Sdump(txIn.SignatureScript),
|
||||||
|
spew.Sdump(sigScript))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure we get the same transaction output back out.
|
||||||
|
txValue := uint64(5000000000)
|
||||||
|
scriptPubKey := &externalapi.ScriptPublicKey{
|
||||||
|
Script: []byte{
|
||||||
|
0x41, // OP_DATA_65
|
||||||
|
0x04, 0xd6, 0x4b, 0xdf, 0xd0, 0x9e, 0xb1, 0xc5,
|
||||||
|
0xfe, 0x29, 0x5a, 0xbd, 0xeb, 0x1d, 0xca, 0x42,
|
||||||
|
0x81, 0xbe, 0x98, 0x8e, 0x2d, 0xa0, 0xb6, 0xc1,
|
||||||
|
0xc6, 0xa5, 0x9d, 0xc2, 0x26, 0xc2, 0x86, 0x24,
|
||||||
|
0xe1, 0x81, 0x75, 0xe8, 0x51, 0xc9, 0x6b, 0x97,
|
||||||
|
0x3d, 0x81, 0xb0, 0x1c, 0xc3, 0x1f, 0x04, 0x78,
|
||||||
|
0x34, 0xbc, 0x06, 0xd6, 0xd6, 0xed, 0xf6, 0x20,
|
||||||
|
0xd1, 0x84, 0x24, 0x1a, 0x6a, 0xed, 0x8b, 0x63,
|
||||||
|
0xa6, // 65-byte signature
|
||||||
|
0xac, // OP_CHECKSIG
|
||||||
|
},
|
||||||
|
Version: 0}
|
||||||
|
txOut := NewTxOut(txValue, scriptPubKey)
|
||||||
|
if txOut.Value != txValue {
|
||||||
|
t.Errorf("NewTxOut: wrong scriptPubKey - got %v, want %v",
|
||||||
|
txOut.Value, txValue)
|
||||||
|
|
||||||
|
}
|
||||||
|
if !bytes.Equal(txOut.ScriptPubKey.Script, scriptPubKey.Script) {
|
||||||
|
t.Errorf("NewTxOut: wrong scriptPubKey - got %v, want %v",
|
||||||
|
spew.Sdump(txOut.ScriptPubKey),
|
||||||
|
spew.Sdump(scriptPubKey))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure transaction inputs are added properly.
|
||||||
|
msg.AddTxIn(txIn)
|
||||||
|
if !reflect.DeepEqual(msg.TxIn[0], txIn) {
|
||||||
|
t.Errorf("AddTxIn: wrong transaction input added - got %v, want %v",
|
||||||
|
spew.Sprint(msg.TxIn[0]), spew.Sprint(txIn))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure transaction outputs are added properly.
|
||||||
|
msg.AddTxOut(txOut)
|
||||||
|
if !reflect.DeepEqual(msg.TxOut[0], txOut) {
|
||||||
|
t.Errorf("AddTxIn: wrong transaction output added - got %v, want %v",
|
||||||
|
spew.Sprint(msg.TxOut[0]), spew.Sprint(txOut))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the copy produced an identical transaction message.
|
||||||
|
newMsg := msg.Copy()
|
||||||
|
if !reflect.DeepEqual(newMsg, msg) {
|
||||||
|
t.Errorf("Copy: mismatched tx messages - got %v, want %v",
|
||||||
|
spew.Sdump(newMsg), spew.Sdump(msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestTxHash tests the ability to generate the hash of a transaction accurately.
|
||||||
|
func TestTxHashAndID(t *testing.T) {
|
||||||
|
txHash1Str := "4bee9ee495bd93a755de428376bd582a2bb6ec37c041753b711c0606d5745c13"
|
||||||
|
txID1Str := "f868bd20e816256b80eac976821be4589d24d21141bd1cec6e8005d0c16c6881"
|
||||||
|
wantTxID1, err := transactionid.FromString(txID1Str)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("NewTxIDFromStr: %v", err)
|
||||||
|
}
|
||||||
|
wantTxHash1, err := transactionid.FromString(txHash1Str)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("NewTxIDFromStr: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// A coinbase transaction
|
||||||
|
txIn := &TxIn{
|
||||||
|
PreviousOutpoint: Outpoint{
|
||||||
|
TxID: externalapi.DomainTransactionID{},
|
||||||
|
Index: math.MaxUint32,
|
||||||
|
},
|
||||||
|
SignatureScript: []byte{0x04, 0x31, 0xdc, 0x00, 0x1b, 0x01, 0x62},
|
||||||
|
Sequence: math.MaxUint64,
|
||||||
|
}
|
||||||
|
txOut := &TxOut{
|
||||||
|
Value: 5000000000,
|
||||||
|
ScriptPubKey: &externalapi.ScriptPublicKey{Script: []byte{
|
||||||
|
0x41, // OP_DATA_65
|
||||||
|
0x04, 0xd6, 0x4b, 0xdf, 0xd0, 0x9e, 0xb1, 0xc5,
|
||||||
|
0xfe, 0x29, 0x5a, 0xbd, 0xeb, 0x1d, 0xca, 0x42,
|
||||||
|
0x81, 0xbe, 0x98, 0x8e, 0x2d, 0xa0, 0xb6, 0xc1,
|
||||||
|
0xc6, 0xa5, 0x9d, 0xc2, 0x26, 0xc2, 0x86, 0x24,
|
||||||
|
0xe1, 0x81, 0x75, 0xe8, 0x51, 0xc9, 0x6b, 0x97,
|
||||||
|
0x3d, 0x81, 0xb0, 0x1c, 0xc3, 0x1f, 0x04, 0x78,
|
||||||
|
0x34, 0xbc, 0x06, 0xd6, 0xd6, 0xed, 0xf6, 0x20,
|
||||||
|
0xd1, 0x84, 0x24, 0x1a, 0x6a, 0xed, 0x8b, 0x63,
|
||||||
|
0xa6, // 65-byte signature
|
||||||
|
0xac, // OP_CHECKSIG
|
||||||
|
}, Version: 0},
|
||||||
|
}
|
||||||
|
tx1 := NewSubnetworkMsgTx(0, []*TxIn{txIn}, []*TxOut{txOut}, &subnetworks.SubnetworkIDCoinbase, 0, nil)
|
||||||
|
|
||||||
|
// Ensure the hash produced is expected.
|
||||||
|
tx1Hash := tx1.TxHash()
|
||||||
|
if *tx1Hash != (externalapi.DomainHash)(*wantTxHash1) {
|
||||||
|
t.Errorf("TxHash: wrong hash - got %v, want %v",
|
||||||
|
spew.Sprint(tx1Hash), spew.Sprint(wantTxHash1))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the TxID for coinbase transaction is the same as TxHash.
|
||||||
|
tx1ID := tx1.TxID()
|
||||||
|
if !tx1ID.Equal(wantTxID1) {
|
||||||
|
t.Errorf("TxID: wrong ID - got %v, want %v",
|
||||||
|
spew.Sprint(tx1ID), spew.Sprint(wantTxID1))
|
||||||
|
}
|
||||||
|
|
||||||
|
hash2Str := "cb1bdb4a83d4885535fb3cceb5c96597b7df903db83f0ffcd779d703affd8efd"
|
||||||
|
wantHash2, err := externalapi.NewDomainHashFromString(hash2Str)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("NewTxIDFromStr: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
id2Str := "ca080073d4ddf5b84443a0964af633f3c70a5b290fd3bc35a7e6f93fd33f9330"
|
||||||
|
wantID2, err := transactionid.FromString(id2Str)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("NewTxIDFromStr: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
payload := []byte{1, 2, 3}
|
||||||
|
txIns := []*TxIn{{
|
||||||
|
PreviousOutpoint: Outpoint{
|
||||||
|
Index: 0,
|
||||||
|
TxID: *externalapi.NewDomainTransactionIDFromByteArray(&[externalapi.DomainHashSize]byte{1, 2, 3}),
|
||||||
|
},
|
||||||
|
SignatureScript: []byte{
|
||||||
|
0x49, 0x30, 0x46, 0x02, 0x21, 0x00, 0xDA, 0x0D, 0xC6, 0xAE, 0xCE, 0xFE, 0x1E, 0x06, 0xEF, 0xDF,
|
||||||
|
0x05, 0x77, 0x37, 0x57, 0xDE, 0xB1, 0x68, 0x82, 0x09, 0x30, 0xE3, 0xB0, 0xD0, 0x3F, 0x46, 0xF5,
|
||||||
|
0xFC, 0xF1, 0x50, 0xBF, 0x99, 0x0C, 0x02, 0x21, 0x00, 0xD2, 0x5B, 0x5C, 0x87, 0x04, 0x00, 0x76,
|
||||||
|
0xE4, 0xF2, 0x53, 0xF8, 0x26, 0x2E, 0x76, 0x3E, 0x2D, 0xD5, 0x1E, 0x7F, 0xF0, 0xBE, 0x15, 0x77,
|
||||||
|
0x27, 0xC4, 0xBC, 0x42, 0x80, 0x7F, 0x17, 0xBD, 0x39, 0x01, 0x41, 0x04, 0xE6, 0xC2, 0x6E, 0xF6,
|
||||||
|
0x7D, 0xC6, 0x10, 0xD2, 0xCD, 0x19, 0x24, 0x84, 0x78, 0x9A, 0x6C, 0xF9, 0xAE, 0xA9, 0x93, 0x0B,
|
||||||
|
0x94, 0x4B, 0x7E, 0x2D, 0xB5, 0x34, 0x2B, 0x9D, 0x9E, 0x5B, 0x9F, 0xF7, 0x9A, 0xFF, 0x9A, 0x2E,
|
||||||
|
0xE1, 0x97, 0x8D, 0xD7, 0xFD, 0x01, 0xDF, 0xC5, 0x22, 0xEE, 0x02, 0x28, 0x3D, 0x3B, 0x06, 0xA9,
|
||||||
|
0xD0, 0x3A, 0xCF, 0x80, 0x96, 0x96, 0x8D, 0x7D, 0xBB, 0x0F, 0x91, 0x78,
|
||||||
|
},
|
||||||
|
Sequence: math.MaxUint64,
|
||||||
|
}}
|
||||||
|
txOuts := []*TxOut{
|
||||||
|
{
|
||||||
|
Value: 244623243,
|
||||||
|
ScriptPubKey: &externalapi.ScriptPublicKey{Script: []byte{
|
||||||
|
0x76, 0xA9, 0x14, 0xBA, 0xDE, 0xEC, 0xFD, 0xEF, 0x05, 0x07, 0x24, 0x7F, 0xC8, 0xF7, 0x42, 0x41,
|
||||||
|
0xD7, 0x3B, 0xC0, 0x39, 0x97, 0x2D, 0x7B, 0x88, 0xAC,
|
||||||
|
}, Version: 0},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Value: 44602432,
|
||||||
|
ScriptPubKey: &externalapi.ScriptPublicKey{Script: []byte{
|
||||||
|
0x76, 0xA9, 0x14, 0xC1, 0x09, 0x32, 0x48, 0x3F, 0xEC, 0x93, 0xED, 0x51, 0xF5, 0xFE, 0x95, 0xE7,
|
||||||
|
0x25, 0x59, 0xF2, 0xCC, 0x70, 0x43, 0xF9, 0x88, 0xAC,
|
||||||
|
}, Version: 0},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
tx2 := NewSubnetworkMsgTx(1, txIns, txOuts, &externalapi.DomainSubnetworkID{1, 2, 3}, 0, payload)
|
||||||
|
|
||||||
|
// Ensure the hash produced is expected.
|
||||||
|
tx2Hash := tx2.TxHash()
|
||||||
|
if !tx2Hash.Equal(wantHash2) {
|
||||||
|
t.Errorf("TxHash: wrong hash - got %v, want %v",
|
||||||
|
spew.Sprint(tx2Hash), spew.Sprint(wantHash2))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the TxID for coinbase transaction is the same as TxHash.
|
||||||
|
tx2ID := tx2.TxID()
|
||||||
|
if !tx2ID.Equal(wantID2) {
|
||||||
|
t.Errorf("TxID: wrong ID - got %v, want %v",
|
||||||
|
spew.Sprint(tx2ID), spew.Sprint(wantID2))
|
||||||
|
}
|
||||||
|
|
||||||
|
if tx2ID.Equal((*externalapi.DomainTransactionID)(tx2Hash)) {
|
||||||
|
t.Errorf("tx2ID and tx2Hash shouldn't be the same for non-coinbase transaction with signature and/or payload")
|
||||||
|
}
|
||||||
|
|
||||||
|
tx2.TxIn[0].SignatureScript = []byte{}
|
||||||
|
newTx2Hash := tx2.TxHash()
|
||||||
|
if *tx2ID == (externalapi.DomainTransactionID)(*newTx2Hash) {
|
||||||
|
t.Errorf("tx2ID and newTx2Hash should not be the same even for transaction with an empty signature")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// 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
|
// MsgVerAck defines a kaspa verack message which is used for a peer to
|
||||||
// acknowledge a version message (MsgVersion) after it has used the information
|
// acknowledge a version message (MsgVersion) after it has used the information
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
@@ -2,25 +2,24 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/netadapter/id"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
"github.com/kaspanet/kaspad/util/mstime"
|
|
||||||
"github.com/kaspanet/kaspad/version"
|
"github.com/kaspanet/kaspad/version"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/id"
|
||||||
"github.com/kaspanet/kaspad/util/subnetworkid"
|
"github.com/kaspanet/kaspad/util/mstime"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MaxUserAgentLen is the maximum allowed length for the user agent field in a
|
// MaxUserAgentLen is the maximum allowed length for the user agent field in a
|
||||||
// version message (MsgVersion).
|
// version message (MsgVersion).
|
||||||
const MaxUserAgentLen = 256
|
const MaxUserAgentLen = 256
|
||||||
|
|
||||||
// DefaultUserAgent for domainmessage in the stack
|
// DefaultUserAgent for appmessage in the stack
|
||||||
var DefaultUserAgent = fmt.Sprintf("/kaspad:%s/", version.Version())
|
var DefaultUserAgent = fmt.Sprintf("/kaspad:%s/", version.Version())
|
||||||
|
|
||||||
// MsgVersion implements the Message interface and represents a kaspa version
|
// MsgVersion implements the Message interface and represents a kaspa version
|
||||||
@@ -41,7 +40,7 @@ type MsgVersion struct {
|
|||||||
// Bitfield which identifies the enabled services.
|
// Bitfield which identifies the enabled services.
|
||||||
Services ServiceFlag
|
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
|
Timestamp mstime.Time
|
||||||
|
|
||||||
// Address of the local peer.
|
// Address of the local peer.
|
||||||
@@ -51,17 +50,14 @@ type MsgVersion struct {
|
|||||||
ID *id.ID
|
ID *id.ID
|
||||||
|
|
||||||
// The user agent that generated messsage. This is a encoded as a varString
|
// 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
|
UserAgent string
|
||||||
|
|
||||||
// The selected tip hash of the generator of the version message.
|
|
||||||
SelectedTipHash *daghash.Hash
|
|
||||||
|
|
||||||
// Don't announce transactions to peer.
|
// Don't announce transactions to peer.
|
||||||
DisableRelayTx bool
|
DisableRelayTx bool
|
||||||
|
|
||||||
// The subnetwork of the generator of the version message. Should be nil in full nodes
|
// The subnetwork of the generator of the version message. Should be nil in full nodes
|
||||||
SubnetworkID *subnetworkid.SubnetworkID
|
SubnetworkID *externalapi.DomainSubnetworkID
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasService returns whether the specified service is supported by the peer
|
// HasService returns whether the specified service is supported by the peer
|
||||||
@@ -86,7 +82,7 @@ func (msg *MsgVersion) Command() MessageCommand {
|
|||||||
// Message interface using the passed parameters and defaults for the remaining
|
// Message interface using the passed parameters and defaults for the remaining
|
||||||
// fields.
|
// fields.
|
||||||
func NewMsgVersion(addr *NetAddress, id *id.ID, network string,
|
func NewMsgVersion(addr *NetAddress, id *id.ID, network string,
|
||||||
selectedTipHash *daghash.Hash, subnetworkID *subnetworkid.SubnetworkID) *MsgVersion {
|
subnetworkID *externalapi.DomainSubnetworkID) *MsgVersion {
|
||||||
|
|
||||||
// Limit the timestamp to one millisecond precision since the protocol
|
// Limit the timestamp to one millisecond precision since the protocol
|
||||||
// doesn't support better.
|
// doesn't support better.
|
||||||
@@ -98,7 +94,6 @@ func NewMsgVersion(addr *NetAddress, id *id.ID, network string,
|
|||||||
Address: addr,
|
Address: addr,
|
||||||
ID: id,
|
ID: id,
|
||||||
UserAgent: DefaultUserAgent,
|
UserAgent: DefaultUserAgent,
|
||||||
SelectedTipHash: selectedTipHash,
|
|
||||||
DisableRelayTx: false,
|
DisableRelayTx: false,
|
||||||
SubnetworkID: subnetworkID,
|
SubnetworkID: subnetworkID,
|
||||||
}
|
}
|
||||||
@@ -2,15 +2,15 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/davecgh/go-spew/spew"
|
|
||||||
"github.com/kaspanet/kaspad/netadapter/id"
|
|
||||||
"github.com/kaspanet/kaspad/util/daghash"
|
|
||||||
"net"
|
"net"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/id"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestVersion tests the MsgVersion API.
|
// TestVersion tests the MsgVersion API.
|
||||||
@@ -18,7 +18,6 @@ func TestVersion(t *testing.T) {
|
|||||||
pver := ProtocolVersion
|
pver := ProtocolVersion
|
||||||
|
|
||||||
// Create version message data.
|
// Create version message data.
|
||||||
selectedTipHash := &daghash.Hash{12, 34}
|
|
||||||
tcpAddrMe := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 16111}
|
tcpAddrMe := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 16111}
|
||||||
me := NewNetAddress(tcpAddrMe, SFNodeNetwork)
|
me := NewNetAddress(tcpAddrMe, SFNodeNetwork)
|
||||||
generatedID, err := id.GenerateID()
|
generatedID, err := id.GenerateID()
|
||||||
@@ -27,7 +26,7 @@ func TestVersion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we get the correct data back out.
|
// Ensure we get the correct data back out.
|
||||||
msg := NewMsgVersion(me, generatedID, "mainnet", selectedTipHash, nil)
|
msg := NewMsgVersion(me, generatedID, "mainnet", nil)
|
||||||
if msg.ProtocolVersion != pver {
|
if msg.ProtocolVersion != pver {
|
||||||
t.Errorf("NewMsgVersion: wrong protocol version - got %v, want %v",
|
t.Errorf("NewMsgVersion: wrong protocol version - got %v, want %v",
|
||||||
msg.ProtocolVersion, pver)
|
msg.ProtocolVersion, pver)
|
||||||
@@ -44,10 +43,6 @@ func TestVersion(t *testing.T) {
|
|||||||
t.Errorf("NewMsgVersion: wrong user agent - got %v, want %v",
|
t.Errorf("NewMsgVersion: wrong user agent - got %v, want %v",
|
||||||
msg.UserAgent, DefaultUserAgent)
|
msg.UserAgent, DefaultUserAgent)
|
||||||
}
|
}
|
||||||
if !msg.SelectedTipHash.IsEqual(selectedTipHash) {
|
|
||||||
t.Errorf("NewMsgVersion: wrong selected tip hash - got %s, want %s",
|
|
||||||
msg.SelectedTipHash, selectedTipHash)
|
|
||||||
}
|
|
||||||
if msg.DisableRelayTx {
|
if msg.DisableRelayTx {
|
||||||
t.Errorf("NewMsgVersion: disable relay tx is not false by "+
|
t.Errorf("NewMsgVersion: disable relay tx is not false by "+
|
||||||
"default - got %v, want %v", msg.DisableRelayTx, false)
|
"default - got %v, want %v", msg.DisableRelayTx, false)
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/util/mstime"
|
"github.com/kaspanet/kaspad/util/mstime"
|
||||||
@@ -21,7 +21,7 @@ type NetAddress struct {
|
|||||||
// IP address of the peer.
|
// IP address of the peer.
|
||||||
IP net.IP
|
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.
|
// which differs from most everything else.
|
||||||
Port uint16
|
Port uint16
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
16
app/appmessage/p2p_requestpruningpointhash.go
Normal file
16
app/appmessage/p2p_requestpruningpointhash.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
// MsgRequestPruningPointHashMessage represents a kaspa RequestPruningPointHashMessage message
|
||||||
|
type MsgRequestPruningPointHashMessage struct {
|
||||||
|
baseMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *MsgRequestPruningPointHashMessage) Command() MessageCommand {
|
||||||
|
return CmdRequestPruningPointHash
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMsgRequestPruningPointHashMessage returns a new kaspa RequestPruningPointHash message
|
||||||
|
func NewMsgRequestPruningPointHashMessage() *MsgRequestPruningPointHashMessage {
|
||||||
|
return &MsgRequestPruningPointHashMessage{}
|
||||||
|
}
|
||||||
16
app/appmessage/p2p_unexpectedpruningpoint.go
Normal file
16
app/appmessage/p2p_unexpectedpruningpoint.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
// MsgUnexpectedPruningPoint represents a kaspa UnexpectedPruningPoint message
|
||||||
|
type MsgUnexpectedPruningPoint struct {
|
||||||
|
baseMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *MsgUnexpectedPruningPoint) Command() MessageCommand {
|
||||||
|
return CmdUnexpectedPruningPoint
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMsgUnexpectedPruningPoint returns a new kaspa UnexpectedPruningPoint message
|
||||||
|
func NewMsgUnexpectedPruningPoint() *MsgUnexpectedPruningPoint {
|
||||||
|
return &MsgUnexpectedPruningPoint{}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -10,10 +10,13 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// XXX pedro: we will probably need to bump this.
|
|
||||||
const (
|
const (
|
||||||
// ProtocolVersion is the latest protocol version this package supports.
|
// ProtocolVersion is the latest protocol version this package supports.
|
||||||
ProtocolVersion uint32 = 1
|
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.
|
// ServiceFlag identifies services supported by a kaspa peer.
|
||||||
@@ -103,9 +106,6 @@ const (
|
|||||||
// Testnet represents the test network.
|
// Testnet represents the test network.
|
||||||
Testnet KaspaNet = 0xddb8af8f
|
Testnet KaspaNet = 0xddb8af8f
|
||||||
|
|
||||||
// Regtest represents the regression test network.
|
|
||||||
Regtest KaspaNet = 0xf396cdd6
|
|
||||||
|
|
||||||
// Simnet represents the simulation test network.
|
// Simnet represents the simulation test network.
|
||||||
Simnet KaspaNet = 0x374dcf1c
|
Simnet KaspaNet = 0x374dcf1c
|
||||||
|
|
||||||
@@ -118,7 +118,6 @@ const (
|
|||||||
var bnStrings = map[KaspaNet]string{
|
var bnStrings = map[KaspaNet]string{
|
||||||
Mainnet: "Mainnet",
|
Mainnet: "Mainnet",
|
||||||
Testnet: "Testnet",
|
Testnet: "Testnet",
|
||||||
Regtest: "Regtest",
|
|
||||||
Simnet: "Simnet",
|
Simnet: "Simnet",
|
||||||
Devnet: "Devnet",
|
Devnet: "Devnet",
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package domainmessage
|
package appmessage
|
||||||
|
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
||||||
@@ -40,7 +40,6 @@ func TestKaspaNetStringer(t *testing.T) {
|
|||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{Mainnet, "Mainnet"},
|
{Mainnet, "Mainnet"},
|
||||||
{Regtest, "Regtest"},
|
|
||||||
{Testnet, "Testnet"},
|
{Testnet, "Testnet"},
|
||||||
{Simnet, "Simnet"},
|
{Simnet, "Simnet"},
|
||||||
{0xffffffff, "Unknown KaspaNet (4294967295)"},
|
{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{}
|
||||||
|
}
|
||||||
107
app/appmessage/rpc_get_block.go
Normal file
107
app/appmessage/rpc_get_block.go
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
// GetBlockRequestMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type GetBlockRequestMessage struct {
|
||||||
|
baseMessage
|
||||||
|
Hash string
|
||||||
|
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, includeTransactionVerboseData bool) *GetBlockRequestMessage {
|
||||||
|
return &GetBlockRequestMessage{
|
||||||
|
Hash: hash,
|
||||||
|
IncludeTransactionVerboseData: includeTransactionVerboseData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBlockResponseMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type GetBlockResponseMessage struct {
|
||||||
|
baseMessage
|
||||||
|
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
|
||||||
|
Version uint16
|
||||||
|
VersionHex string
|
||||||
|
HashMerkleRoot string
|
||||||
|
AcceptedIDMerkleRoot string
|
||||||
|
UTXOCommitment string
|
||||||
|
TxIDs []string
|
||||||
|
TransactionVerboseData []*TransactionVerboseData
|
||||||
|
Time int64
|
||||||
|
Nonce uint64
|
||||||
|
Bits string
|
||||||
|
Difficulty float64
|
||||||
|
ParentHashes []string
|
||||||
|
SelectedParentHash string
|
||||||
|
BlueScore uint64
|
||||||
|
IsHeaderOnly bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransactionVerboseData holds verbose data about a transaction
|
||||||
|
type TransactionVerboseData struct {
|
||||||
|
TxID string
|
||||||
|
Hash string
|
||||||
|
Size uint64
|
||||||
|
Version uint16
|
||||||
|
LockTime uint64
|
||||||
|
SubnetworkID string
|
||||||
|
Gas uint64
|
||||||
|
PayloadHash string
|
||||||
|
Payload string
|
||||||
|
TransactionVerboseInputs []*TransactionVerboseInput
|
||||||
|
TransactionVerboseOutputs []*TransactionVerboseOutput
|
||||||
|
BlockHash string
|
||||||
|
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 {
|
||||||
|
Hex string
|
||||||
|
Type string
|
||||||
|
Address string
|
||||||
|
}
|
||||||
42
app/appmessage/rpc_get_block_count.go
Normal file
42
app/appmessage/rpc_get_block_count.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
|
||||||
|
// 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
|
||||||
|
HeaderCount 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(syncInfo *externalapi.SyncInfo) *GetBlockCountResponseMessage {
|
||||||
|
return &GetBlockCountResponseMessage{
|
||||||
|
BlockCount: syncInfo.BlockCount,
|
||||||
|
HeaderCount: syncInfo.HeaderCount,
|
||||||
|
}
|
||||||
|
}
|
||||||
42
app/appmessage/rpc_get_block_dag_info.go
Normal file
42
app/appmessage/rpc_get_block_dag_info.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
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
|
||||||
|
HeaderCount 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{}
|
||||||
|
}
|
||||||
43
app/appmessage/rpc_get_block_template.go
Normal file
43
app/appmessage/rpc_get_block_template.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
// GetBlockTemplateRequestMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type GetBlockTemplateRequestMessage struct {
|
||||||
|
baseMessage
|
||||||
|
PayAddress 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) *GetBlockTemplateRequestMessage {
|
||||||
|
return &GetBlockTemplateRequestMessage{
|
||||||
|
PayAddress: payAddress,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBlockTemplateResponseMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type GetBlockTemplateResponseMessage struct {
|
||||||
|
baseMessage
|
||||||
|
MsgBlock *MsgBlock
|
||||||
|
IsSynced 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(msgBlock *MsgBlock, isSynced bool) *GetBlockTemplateResponseMessage {
|
||||||
|
return &GetBlockTemplateResponseMessage{
|
||||||
|
MsgBlock: msgBlock,
|
||||||
|
IsSynced: isSynced,
|
||||||
|
}
|
||||||
|
}
|
||||||
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
50
app/appmessage/rpc_get_connected_peer_info.go
Normal file
50
app/appmessage/rpc_get_connected_peer_info.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
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
|
||||||
|
IsOutbound bool
|
||||||
|
TimeOffset int64
|
||||||
|
UserAgent string
|
||||||
|
AdvertisedProtocolVersion uint32
|
||||||
|
TimeConnected int64
|
||||||
|
IsIBDPeer bool
|
||||||
|
}
|
||||||
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
41
app/appmessage/rpc_get_utxos_by_addresses.go
Normal file
41
app/appmessage/rpc_get_utxos_by_addresses.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
// GetUTXOsByAddressesRequestMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type GetUTXOsByAddressesRequestMessage struct {
|
||||||
|
baseMessage
|
||||||
|
Addresses []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *GetUTXOsByAddressesRequestMessage) Command() MessageCommand {
|
||||||
|
return CmdGetUTXOsByAddressesRequestMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGetUTXOsByAddressesRequestMessage returns a instance of the message
|
||||||
|
func NewGetUTXOsByAddressesRequestMessage(addresses []string) *GetUTXOsByAddressesRequestMessage {
|
||||||
|
return &GetUTXOsByAddressesRequestMessage{
|
||||||
|
Addresses: addresses,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetUTXOsByAddressesResponseMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type GetUTXOsByAddressesResponseMessage struct {
|
||||||
|
baseMessage
|
||||||
|
Entries []*UTXOsByAddressesEntry
|
||||||
|
|
||||||
|
Error *RPCError
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *GetUTXOsByAddressesResponseMessage) Command() MessageCommand {
|
||||||
|
return CmdGetUTXOsByAddressesResponseMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGetUTXOsByAddressesResponseMessage returns a instance of the message
|
||||||
|
func NewGetUTXOsByAddressesResponseMessage(entries []*UTXOsByAddressesEntry) *GetUTXOsByAddressesResponseMessage {
|
||||||
|
return &GetUTXOsByAddressesResponseMessage{
|
||||||
|
Entries: entries,
|
||||||
|
}
|
||||||
|
}
|
||||||
38
app/appmessage/rpc_get_virtual_selected_parent_blue_score.go
Normal file
38
app/appmessage/rpc_get_virtual_selected_parent_blue_score.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
// GetVirtualSelectedParentBlueScoreRequestMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type GetVirtualSelectedParentBlueScoreRequestMessage struct {
|
||||||
|
baseMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *GetVirtualSelectedParentBlueScoreRequestMessage) Command() MessageCommand {
|
||||||
|
return CmdGetVirtualSelectedParentBlueScoreRequestMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGetVirtualSelectedParentBlueScoreRequestMessage returns a instance of the message
|
||||||
|
func NewGetVirtualSelectedParentBlueScoreRequestMessage() *GetVirtualSelectedParentBlueScoreRequestMessage {
|
||||||
|
return &GetVirtualSelectedParentBlueScoreRequestMessage{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVirtualSelectedParentBlueScoreResponseMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type GetVirtualSelectedParentBlueScoreResponseMessage struct {
|
||||||
|
baseMessage
|
||||||
|
BlueScore uint64
|
||||||
|
|
||||||
|
Error *RPCError
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *GetVirtualSelectedParentBlueScoreResponseMessage) Command() MessageCommand {
|
||||||
|
return CmdGetVirtualSelectedParentBlueScoreResponseMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGetVirtualSelectedParentBlueScoreResponseMessage returns a instance of the message
|
||||||
|
func NewGetVirtualSelectedParentBlueScoreResponseMessage(blueScore uint64) *GetVirtualSelectedParentBlueScoreResponseMessage {
|
||||||
|
return &GetVirtualSelectedParentBlueScoreResponseMessage{
|
||||||
|
BlueScore: blueScore,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
// GetVirtualSelectedParentChainFromBlockRequestMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type GetVirtualSelectedParentChainFromBlockRequestMessage struct {
|
||||||
|
baseMessage
|
||||||
|
StartHash string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *GetVirtualSelectedParentChainFromBlockRequestMessage) Command() MessageCommand {
|
||||||
|
return CmdGetVirtualSelectedParentChainFromBlockRequestMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGetVirtualSelectedParentChainFromBlockRequestMessage returns a instance of the message
|
||||||
|
func NewGetVirtualSelectedParentChainFromBlockRequestMessage(startHash string) *GetVirtualSelectedParentChainFromBlockRequestMessage {
|
||||||
|
return &GetVirtualSelectedParentChainFromBlockRequestMessage{
|
||||||
|
StartHash: startHash,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetVirtualSelectedParentChainFromBlockResponseMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type GetVirtualSelectedParentChainFromBlockResponseMessage struct {
|
||||||
|
baseMessage
|
||||||
|
RemovedChainBlockHashes []string
|
||||||
|
AddedChainBlocks []*ChainBlock
|
||||||
|
|
||||||
|
Error *RPCError
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *GetVirtualSelectedParentChainFromBlockResponseMessage) Command() MessageCommand {
|
||||||
|
return CmdGetVirtualSelectedParentChainFromBlockResponseMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGetVirtualSelectedParentChainFromBlockResponseMessage returns a instance of the message
|
||||||
|
func NewGetVirtualSelectedParentChainFromBlockResponseMessage(removedChainBlockHashes []string,
|
||||||
|
addedChainBlocks []*ChainBlock) *GetVirtualSelectedParentChainFromBlockResponseMessage {
|
||||||
|
|
||||||
|
return &GetVirtualSelectedParentChainFromBlockResponseMessage{
|
||||||
|
RemovedChainBlockHashes: removedChainBlockHashes,
|
||||||
|
AddedChainBlocks: addedChainBlocks,
|
||||||
|
}
|
||||||
|
}
|
||||||
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
62
app/appmessage/rpc_notify_utxos_changed.go
Normal file
62
app/appmessage/rpc_notify_utxos_changed.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
// NotifyUTXOsChangedRequestMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type NotifyUTXOsChangedRequestMessage struct {
|
||||||
|
baseMessage
|
||||||
|
Addresses []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *NotifyUTXOsChangedRequestMessage) Command() MessageCommand {
|
||||||
|
return CmdNotifyUTXOsChangedRequestMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotifyUTXOsChangedRequestMessage returns a instance of the message
|
||||||
|
func NewNotifyUTXOsChangedRequestMessage(addresses []string) *NotifyUTXOsChangedRequestMessage {
|
||||||
|
return &NotifyUTXOsChangedRequestMessage{
|
||||||
|
Addresses: addresses,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyUTXOsChangedResponseMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type NotifyUTXOsChangedResponseMessage struct {
|
||||||
|
baseMessage
|
||||||
|
Error *RPCError
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *NotifyUTXOsChangedResponseMessage) Command() MessageCommand {
|
||||||
|
return CmdNotifyUTXOsChangedResponseMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotifyUTXOsChangedResponseMessage returns a instance of the message
|
||||||
|
func NewNotifyUTXOsChangedResponseMessage() *NotifyUTXOsChangedResponseMessage {
|
||||||
|
return &NotifyUTXOsChangedResponseMessage{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UTXOsChangedNotificationMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type UTXOsChangedNotificationMessage struct {
|
||||||
|
baseMessage
|
||||||
|
Added []*UTXOsByAddressesEntry
|
||||||
|
Removed []*UTXOsByAddressesEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
// UTXOsByAddressesEntry represents a UTXO of some address
|
||||||
|
type UTXOsByAddressesEntry struct {
|
||||||
|
Address string
|
||||||
|
Outpoint *RPCOutpoint
|
||||||
|
UTXOEntry *RPCUTXOEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *UTXOsChangedNotificationMessage) Command() MessageCommand {
|
||||||
|
return CmdUTXOsChangedNotificationMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewUTXOsChangedNotificationMessage returns a instance of the message
|
||||||
|
func NewUTXOsChangedNotificationMessage() *UTXOsChangedNotificationMessage {
|
||||||
|
return &UTXOsChangedNotificationMessage{}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
// NotifyVirtualSelectedParentBlueScoreChangedRequestMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type NotifyVirtualSelectedParentBlueScoreChangedRequestMessage struct {
|
||||||
|
baseMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *NotifyVirtualSelectedParentBlueScoreChangedRequestMessage) Command() MessageCommand {
|
||||||
|
return CmdNotifyVirtualSelectedParentBlueScoreChangedRequestMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotifyVirtualSelectedParentBlueScoreChangedRequestMessage returns a instance of the message
|
||||||
|
func NewNotifyVirtualSelectedParentBlueScoreChangedRequestMessage() *NotifyVirtualSelectedParentBlueScoreChangedRequestMessage {
|
||||||
|
return &NotifyVirtualSelectedParentBlueScoreChangedRequestMessage{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyVirtualSelectedParentBlueScoreChangedResponseMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type NotifyVirtualSelectedParentBlueScoreChangedResponseMessage struct {
|
||||||
|
baseMessage
|
||||||
|
Error *RPCError
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *NotifyVirtualSelectedParentBlueScoreChangedResponseMessage) Command() MessageCommand {
|
||||||
|
return CmdNotifyVirtualSelectedParentBlueScoreChangedResponseMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotifyVirtualSelectedParentBlueScoreChangedResponseMessage returns a instance of the message
|
||||||
|
func NewNotifyVirtualSelectedParentBlueScoreChangedResponseMessage() *NotifyVirtualSelectedParentBlueScoreChangedResponseMessage {
|
||||||
|
return &NotifyVirtualSelectedParentBlueScoreChangedResponseMessage{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// VirtualSelectedParentBlueScoreChangedNotificationMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type VirtualSelectedParentBlueScoreChangedNotificationMessage struct {
|
||||||
|
baseMessage
|
||||||
|
VirtualSelectedParentBlueScore uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *VirtualSelectedParentBlueScoreChangedNotificationMessage) Command() MessageCommand {
|
||||||
|
return CmdVirtualSelectedParentBlueScoreChangedNotificationMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewVirtualSelectedParentBlueScoreChangedNotificationMessage returns a instance of the message
|
||||||
|
func NewVirtualSelectedParentBlueScoreChangedNotificationMessage(
|
||||||
|
virtualSelectedParentBlueScore uint64) *VirtualSelectedParentBlueScoreChangedNotificationMessage {
|
||||||
|
|
||||||
|
return &VirtualSelectedParentBlueScoreChangedNotificationMessage{
|
||||||
|
VirtualSelectedParentBlueScore: virtualSelectedParentBlueScore,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
// NotifyVirtualSelectedParentChainChangedRequestMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type NotifyVirtualSelectedParentChainChangedRequestMessage struct {
|
||||||
|
baseMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *NotifyVirtualSelectedParentChainChangedRequestMessage) Command() MessageCommand {
|
||||||
|
return CmdNotifyVirtualSelectedParentChainChangedRequestMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotifyVirtualSelectedParentChainChangedRequestMessage returns a instance of the message
|
||||||
|
func NewNotifyVirtualSelectedParentChainChangedRequestMessage() *NotifyVirtualSelectedParentChainChangedRequestMessage {
|
||||||
|
return &NotifyVirtualSelectedParentChainChangedRequestMessage{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyVirtualSelectedParentChainChangedResponseMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type NotifyVirtualSelectedParentChainChangedResponseMessage struct {
|
||||||
|
baseMessage
|
||||||
|
Error *RPCError
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *NotifyVirtualSelectedParentChainChangedResponseMessage) Command() MessageCommand {
|
||||||
|
return CmdNotifyVirtualSelectedParentChainChangedResponseMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewNotifyVirtualSelectedParentChainChangedResponseMessage returns a instance of the message
|
||||||
|
func NewNotifyVirtualSelectedParentChainChangedResponseMessage() *NotifyVirtualSelectedParentChainChangedResponseMessage {
|
||||||
|
return &NotifyVirtualSelectedParentChainChangedResponseMessage{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// VirtualSelectedParentChainChangedNotificationMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type VirtualSelectedParentChainChangedNotificationMessage 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
|
||||||
|
AcceptedTransactionIDs []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command returns the protocol command string for the message
|
||||||
|
func (msg *VirtualSelectedParentChainChangedNotificationMessage) Command() MessageCommand {
|
||||||
|
return CmdVirtualSelectedParentChainChangedNotificationMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewVirtualSelectedParentChainChangedNotificationMessage returns a instance of the message
|
||||||
|
func NewVirtualSelectedParentChainChangedNotificationMessage(removedChainBlockHashes []string,
|
||||||
|
addedChainBlocks []*ChainBlock) *VirtualSelectedParentChainChangedNotificationMessage {
|
||||||
|
|
||||||
|
return &VirtualSelectedParentChainChangedNotificationMessage{
|
||||||
|
RemovedChainBlockHashes: removedChainBlockHashes,
|
||||||
|
AddedChainBlocks: addedChainBlocks,
|
||||||
|
}
|
||||||
|
}
|
||||||
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{}
|
||||||
|
}
|
||||||
59
app/appmessage/rpc_submit_block.go
Normal file
59
app/appmessage/rpc_submit_block.go
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
// SubmitBlockRequestMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type SubmitBlockRequestMessage struct {
|
||||||
|
baseMessage
|
||||||
|
Block *MsgBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(block *MsgBlock) *SubmitBlockRequestMessage {
|
||||||
|
return &SubmitBlockRequestMessage{
|
||||||
|
Block: block,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RejectReason describes the reason why a block sent by SubmitBlock was rejected
|
||||||
|
type RejectReason byte
|
||||||
|
|
||||||
|
// RejectReason constants
|
||||||
|
// Not using iota, since in the .proto file those are hardcoded
|
||||||
|
const (
|
||||||
|
RejectReasonNone RejectReason = 0
|
||||||
|
RejectReasonBlockInvalid RejectReason = 1
|
||||||
|
RejectReasonIsInIBD RejectReason = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
var rejectReasonToString = map[RejectReason]string{
|
||||||
|
RejectReasonNone: "None",
|
||||||
|
RejectReasonBlockInvalid: "Block is invalid",
|
||||||
|
RejectReasonIsInIBD: "Node is in IBD",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rr RejectReason) String() string {
|
||||||
|
return rejectReasonToString[rr]
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubmitBlockResponseMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type SubmitBlockResponseMessage struct {
|
||||||
|
baseMessage
|
||||||
|
RejectReason RejectReason
|
||||||
|
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{}
|
||||||
|
}
|
||||||
91
app/appmessage/rpc_submit_transaction.go
Normal file
91
app/appmessage/rpc_submit_transaction.go
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
package appmessage
|
||||||
|
|
||||||
|
// SubmitTransactionRequestMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type SubmitTransactionRequestMessage struct {
|
||||||
|
baseMessage
|
||||||
|
Transaction *RPCTransaction
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(transaction *RPCTransaction) *SubmitTransactionRequestMessage {
|
||||||
|
return &SubmitTransactionRequestMessage{
|
||||||
|
Transaction: transaction,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubmitTransactionResponseMessage is an appmessage corresponding to
|
||||||
|
// its respective RPC message
|
||||||
|
type SubmitTransactionResponseMessage struct {
|
||||||
|
baseMessage
|
||||||
|
TransactionID 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(transactionID string) *SubmitTransactionResponseMessage {
|
||||||
|
return &SubmitTransactionResponseMessage{
|
||||||
|
TransactionID: transactionID,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RPCTransaction is a kaspad transaction representation meant to be
|
||||||
|
// used over RPC
|
||||||
|
type RPCTransaction struct {
|
||||||
|
Version uint16
|
||||||
|
Inputs []*RPCTransactionInput
|
||||||
|
Outputs []*RPCTransactionOutput
|
||||||
|
LockTime uint64
|
||||||
|
SubnetworkID string
|
||||||
|
Gas uint64
|
||||||
|
PayloadHash string
|
||||||
|
Payload string
|
||||||
|
}
|
||||||
|
|
||||||
|
// RPCTransactionInput is a kaspad transaction input representation
|
||||||
|
// meant to be used over RPC
|
||||||
|
type RPCTransactionInput struct {
|
||||||
|
PreviousOutpoint *RPCOutpoint
|
||||||
|
SignatureScript string
|
||||||
|
Sequence uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// RPCScriptPublicKey is a kaspad ScriptPublicKey representation
|
||||||
|
type RPCScriptPublicKey struct {
|
||||||
|
Version uint16
|
||||||
|
Script string
|
||||||
|
}
|
||||||
|
|
||||||
|
// RPCTransactionOutput is a kaspad transaction output representation
|
||||||
|
// meant to be used over RPC
|
||||||
|
type RPCTransactionOutput struct {
|
||||||
|
Amount uint64
|
||||||
|
ScriptPublicKey *RPCScriptPublicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// RPCOutpoint is a kaspad outpoint representation meant to be used
|
||||||
|
// over RPC
|
||||||
|
type RPCOutpoint struct {
|
||||||
|
TransactionID string
|
||||||
|
Index uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// RPCUTXOEntry is a kaspad utxo entry representation meant to be used
|
||||||
|
// over RPC
|
||||||
|
type RPCUTXOEntry struct {
|
||||||
|
Amount uint64
|
||||||
|
ScriptPublicKey *RPCScriptPublicKey
|
||||||
|
BlockBlueScore uint64
|
||||||
|
IsCoinbase bool
|
||||||
|
}
|
||||||
176
app/component_manager.go
Normal file
176
app/component_manager.go
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
package app
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/domain/utxoindex"
|
||||||
|
|
||||||
|
infrastructuredatabase "github.com/kaspanet/kaspad/infrastructure/db/database"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/domain"
|
||||||
|
|
||||||
|
"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/infrastructure/config"
|
||||||
|
"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, db infrastructuredatabase.Database, interrupt chan<- struct{}) (
|
||||||
|
*ComponentManager, error) {
|
||||||
|
|
||||||
|
domain, err := domain.New(cfg.ActiveNetParams, db, cfg.IsArchivalNode)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
netAdapter, err := netadapter.NewNetAdapter(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
addressManager, err := addressmanager.New(addressmanager.NewConfig(cfg))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var utxoIndex *utxoindex.UTXOIndex
|
||||||
|
if cfg.UTXOIndex {
|
||||||
|
utxoIndex = utxoindex.New(domain.Consensus(), db)
|
||||||
|
log.Infof("UTXO index started")
|
||||||
|
}
|
||||||
|
|
||||||
|
connectionManager, err := connmanager.New(cfg, netAdapter, addressManager)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
protocolManager, err := protocol.NewManager(cfg, domain, netAdapter, addressManager, connectionManager)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rpcManager := setupRPC(cfg, domain, netAdapter, protocolManager, connectionManager, addressManager, utxoIndex, interrupt)
|
||||||
|
|
||||||
|
return &ComponentManager{
|
||||||
|
cfg: cfg,
|
||||||
|
protocolManager: protocolManager,
|
||||||
|
rpcManager: rpcManager,
|
||||||
|
connectionManager: connectionManager,
|
||||||
|
netAdapter: netAdapter,
|
||||||
|
addressManager: addressManager,
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupRPC(
|
||||||
|
cfg *config.Config,
|
||||||
|
domain domain.Domain,
|
||||||
|
netAdapter *netadapter.NetAdapter,
|
||||||
|
protocolManager *protocol.Manager,
|
||||||
|
connectionManager *connmanager.ConnectionManager,
|
||||||
|
addressManager *addressmanager.AddressManager,
|
||||||
|
utxoIndex *utxoindex.UTXOIndex,
|
||||||
|
shutDownChan chan<- struct{},
|
||||||
|
) *rpc.Manager {
|
||||||
|
|
||||||
|
rpcManager := rpc.NewManager(
|
||||||
|
cfg,
|
||||||
|
domain,
|
||||||
|
netAdapter,
|
||||||
|
protocolManager,
|
||||||
|
connectionManager,
|
||||||
|
addressManager,
|
||||||
|
utxoIndex,
|
||||||
|
shutDownChan,
|
||||||
|
)
|
||||||
|
protocolManager.SetOnBlockAddedToDAGHandler(rpcManager.NotifyBlockAddedToDAG)
|
||||||
|
|
||||||
|
return rpcManager
|
||||||
|
}
|
||||||
|
|
||||||
|
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...)
|
||||||
|
})
|
||||||
|
|
||||||
|
dnsseed.SeedFromGRPC(a.cfg.NetParams(), a.cfg.GRPCSeed, appmessage.SFNodeNetwork, false, nil,
|
||||||
|
func(addresses []*appmessage.NetAddress) {
|
||||||
|
a.addressManager.AddAddresses(addresses...)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/logger"
|
"github.com/kaspanet/kaspad/infrastructure/logger"
|
||||||
"github.com/kaspanet/kaspad/util/panics"
|
"github.com/kaspanet/kaspad/util/panics"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
package blocklogger
|
package blocklogger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/util/mstime"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/util"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
|
"github.com/kaspanet/kaspad/util/mstime"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -22,17 +22,17 @@ var (
|
|||||||
// LogBlock logs a new block blue score as an information message
|
// LogBlock logs a new block blue score as an information message
|
||||||
// to show progress to the user. In order to prevent spam, it limits logging to
|
// to show progress to the user. In order to prevent spam, it limits logging to
|
||||||
// one message every 10 seconds with duration and totals included.
|
// one message every 10 seconds with duration and totals included.
|
||||||
func LogBlock(block *util.Block) error {
|
func LogBlock(block *externalapi.DomainBlock) {
|
||||||
mtx.Lock()
|
mtx.Lock()
|
||||||
defer mtx.Unlock()
|
defer mtx.Unlock()
|
||||||
|
|
||||||
receivedLogBlocks++
|
receivedLogBlocks++
|
||||||
receivedLogTx += int64(len(block.MsgBlock().Transactions))
|
receivedLogTx += int64(len(block.Transactions))
|
||||||
|
|
||||||
now := mstime.Now()
|
now := mstime.Now()
|
||||||
duration := now.Sub(lastBlockLogTime)
|
duration := now.Sub(lastBlockLogTime)
|
||||||
if duration < time.Second*10 {
|
if duration < time.Second*10 {
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Truncate the duration to 10s of milliseconds.
|
// Truncate the duration to 10s of milliseconds.
|
||||||
@@ -48,17 +48,11 @@ func LogBlock(block *util.Block) error {
|
|||||||
txStr = "transaction"
|
txStr = "transaction"
|
||||||
}
|
}
|
||||||
|
|
||||||
blueScore, err := block.BlueScore()
|
log.Infof("Processed %d %s in the last %s (%d %s, %s)",
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("Processed %d %s in the last %s (%d %s, blue score %d, %s)",
|
|
||||||
receivedLogBlocks, blockStr, tDuration, receivedLogTx,
|
receivedLogBlocks, blockStr, tDuration, receivedLogTx,
|
||||||
txStr, blueScore, block.MsgBlock().Header.Timestamp)
|
txStr, mstime.UnixMilliseconds(block.Header.TimeInMilliseconds()))
|
||||||
|
|
||||||
receivedLogBlocks = 0
|
receivedLogBlocks = 0
|
||||||
receivedLogTx = 0
|
receivedLogTx = 0
|
||||||
lastBlockLogTime = now
|
lastBlockLogTime = now
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
package blocklogger
|
package blocklogger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kaspanet/kaspad/logger"
|
"github.com/kaspanet/kaspad/infrastructure/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
var log, _ = logger.Get(logger.SubsystemTags.PROT)
|
var log, _ = logger.Get(logger.SubsystemTags.PROT)
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user