mirror of
https://github.com/kaspanet/kaspad.git
synced 2026-02-21 19:22:53 +00:00
Compare commits
1 Commits
rm
...
v0.0.6-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3dacba643d |
@@ -1,9 +0,0 @@
|
||||
coverage:
|
||||
status:
|
||||
patch: off
|
||||
|
||||
project:
|
||||
default:
|
||||
informational: true
|
||||
ignore:
|
||||
- "**/*.pb.go" # Ignore all auto generated protobuf structures.
|
||||
196
.github/workflows/SetPageFileSize.ps1
vendored
196
.github/workflows/SetPageFileSize.ps1
vendored
@@ -1,196 +0,0 @@
|
||||
<#
|
||||
# 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)
|
||||
49
.github/workflows/go-race.yml
vendored
49
.github/workflows/go-race.yml
vendored
@@ -1,49 +0,0 @@
|
||||
name: Go-Race
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
race_test:
|
||||
runs-on: ubuntu-20.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
branch: [ master, latest ]
|
||||
name: Race detection on ${{ matrix.branch }}
|
||||
steps:
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.15
|
||||
|
||||
- name: Set scheduled branch name
|
||||
shell: bash
|
||||
if: github.event_name == 'schedule'
|
||||
run: |
|
||||
if [ "${{ matrix.branch }}" == "master" ]; then
|
||||
echo "run_on=master" >> $GITHUB_ENV
|
||||
fi
|
||||
if [ "${{ matrix.branch }}" == "latest" ]; then
|
||||
branch=$(git branch -r | grep 'v\([0-9]\+\.\)\([0-9]\+\.\)\([0-9]\+\)-dev' | sort -Vr | head -1 | xargs)
|
||||
echo "run_on=${branch}" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Set manual branch name
|
||||
shell: bash
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
run: echo "run_on=${{ github.ref }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Test with race detector
|
||||
shell: bash
|
||||
run: |
|
||||
git checkout "${{ env.run_on }}"
|
||||
git status
|
||||
go test -race ./...
|
||||
70
.github/workflows/go.yml
vendored
70
.github/workflows/go.yml
vendored
@@ -1,70 +0,0 @@
|
||||
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:
|
||||
fail-fast: false
|
||||
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.16
|
||||
|
||||
|
||||
# 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 -v
|
||||
|
||||
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.16
|
||||
|
||||
- name: Create coverage file
|
||||
run: go test -v -covermode=atomic -coverpkg=./... -coverprofile coverage.txt ./...
|
||||
|
||||
- name: Upload coverage file
|
||||
run: bash <(curl -s https://codecov.io/bash)
|
||||
21
.gitignore
vendored
21
.gitignore
vendored
@@ -2,7 +2,7 @@
|
||||
*~
|
||||
|
||||
# Databases
|
||||
kaspad.db
|
||||
btcd.db
|
||||
*-shm
|
||||
*-wal
|
||||
|
||||
@@ -13,21 +13,6 @@ kaspad.db
|
||||
*.o
|
||||
*.a
|
||||
*.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
|
||||
_obj
|
||||
@@ -46,13 +31,13 @@ _cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
|
||||
*.exe
|
||||
|
||||
# IDE
|
||||
.idea
|
||||
.vscode
|
||||
debug
|
||||
debug.test
|
||||
__debug_bin
|
||||
|
||||
# CI
|
||||
version.txt
|
||||
|
||||
955
CHANGES
Normal file
955
CHANGES
Normal file
@@ -0,0 +1,955 @@
|
||||
============================================================================
|
||||
User visible changes for btcd
|
||||
A full-node bitcoin implementation written in Go
|
||||
============================================================================
|
||||
|
||||
Changes in 0.12.0 (Fri Nov 20 2015)
|
||||
- Protocol and network related changes:
|
||||
- Add a new checkpoint at block height 382320 (#555)
|
||||
- Implement BIP0065 which includes support for version 4 blocks, a new
|
||||
consensus opcode (OP_CHECKLOCKTIMEVERIFY) that enforces transaction
|
||||
lock times, and a double-threshold switchover mechanism (#535, #459,
|
||||
#455)
|
||||
- Implement BIP0111 which provides a new bloom filter service flag and
|
||||
hence provides support for protocol version 70011 (#499)
|
||||
- Add a new parameter --nopeerbloomfilters to allow disabling bloom
|
||||
filter support (#499)
|
||||
- Reject non-canonically encoded variable length integers (#507)
|
||||
- Add mainnet peer discovery DNS seed (seed.bitcoin.jonasschnelli.ch)
|
||||
(#496)
|
||||
- Correct reconnect handling for persistent peers (#463, #464)
|
||||
- Ignore requests for block headers if not fully synced (#444)
|
||||
- Add CLI support for specifying the zone id on IPv6 addresses (#538)
|
||||
- Fix a couple of issues where the initial block sync could stall (#518,
|
||||
#229, #486)
|
||||
- Fix an issue which prevented the --onion option from working as
|
||||
intended (#446)
|
||||
- Transaction relay (memory pool) changes:
|
||||
- Require transactions to only include signatures encoded with the
|
||||
canonical 'low-s' encoding (#512)
|
||||
- Add a new parameter --minrelaytxfee to allow the minimum transaction
|
||||
fee in BTC/kB to be overridden (#520)
|
||||
- Retain memory pool transactions when they redeem another one that is
|
||||
removed when a block is accepted (#539)
|
||||
- Do not send reject messages for a transaction if it is valid but
|
||||
causes an orphan transaction which depends on it to be determined
|
||||
as invalid (#546)
|
||||
- Refrain from attempting to add orphans to the memory pool multiple
|
||||
times when the transaction they redeem is added (#551)
|
||||
- Modify minimum transaction fee calculations to scale based on bytes
|
||||
instead of full kilobyte boundaries (#521, #537)
|
||||
- Implement signature cache:
|
||||
- Provides a limited memory cache of validated signatures which is a
|
||||
huge optimization when verifying blocks for transactions that are
|
||||
already in the memory pool (#506)
|
||||
- Add a new parameter '--sigcachemaxsize' which allows the size of the
|
||||
new cache to be manually changed if desired (#506)
|
||||
- Mining support changes:
|
||||
- Notify getblocktemplate long polling clients when a block is pushed
|
||||
via submitblock (#488)
|
||||
- Speed up getblocktemplate by making use of the new signature cache
|
||||
(#506)
|
||||
- RPC changes:
|
||||
- Implement getmempoolinfo command (#453)
|
||||
- Implement getblockheader command (#461)
|
||||
- Modify createrawtransaction command to accept a new optional parameter
|
||||
'locktime' (#529)
|
||||
- Modify listunspent result to include the 'spendable' field (#440)
|
||||
- Modify getinfo command to include 'errors' field (#511)
|
||||
- Add timestamps to blockconnected and blockdisconnected notifications
|
||||
(#450)
|
||||
- Several modifications to searchrawtranscations command:
|
||||
- Accept a new optional parameter 'vinextra' which causes the results
|
||||
to include information about the outputs referenced by a transaction's
|
||||
inputs (#485, #487)
|
||||
- Skip entries in the mempool too (#495)
|
||||
- Accept a new optional parameter 'reverse' to return the results in
|
||||
reverse order (most recent to oldest) (#497)
|
||||
- Accept a new optional parameter 'filteraddrs' which causes the
|
||||
results to only include inputs and outputs which involve the
|
||||
provided addresses (#516)
|
||||
- Change the notification order to notify clients about mined
|
||||
transactions (recvtx, redeemingtx) before the blockconnected
|
||||
notification (#449)
|
||||
- Update verifymessage RPC to use the standard algorithm so it is
|
||||
compatible with other implementations (#515)
|
||||
- Improve ping statistics by pinging on an interval (#517)
|
||||
- Websocket changes:
|
||||
- Implement session command which returns a per-session unique id (#500,
|
||||
#503)
|
||||
- btcctl utility changes:
|
||||
- Add getmempoolinfo command (#453)
|
||||
- Add getblockheader command (#461)
|
||||
- Add getwalletinfo command (#471)
|
||||
- Notable developer-related package changes:
|
||||
- Introduce a new peer package which acts a common base for creating and
|
||||
concurrently managing bitcoin network peers (#445)
|
||||
- Various cleanup of the new peer package (#528, #531, #524, #534,
|
||||
#549)
|
||||
- Blocks heights now consistently use int32 everywhere (#481)
|
||||
- The BlockHeader type in the wire package now provides the BtcDecode
|
||||
and BtcEncode methods (#467)
|
||||
- Update wire package to recognize BIP0064 (getutxo) service bit (#489)
|
||||
- Export LockTimeThreshold constant from txscript package (#454)
|
||||
- Export MaxDataCarrierSize constant from txscript package (#466)
|
||||
- Provide new IsUnspendable function from the txscript package (#478)
|
||||
- Export variable length string functions from the wire package (#514)
|
||||
- Export DNS Seeds for each network from the chaincfg package (#544)
|
||||
- Preliminary work towards separating the memory pool into a separate
|
||||
package (#525, #548)
|
||||
- Misc changes:
|
||||
- Various documentation updates (#442, #462, #465, #460, #470, #473,
|
||||
#505, #530, #545)
|
||||
- Add installation instructions for gentoo (#542)
|
||||
- Ensure an error is shown if OS limits can't be set at startup (#498)
|
||||
- Tighten the standardness checks for multisig scripts (#526)
|
||||
- Test coverage improvement (#468, #494, #527, #543, #550)
|
||||
- Several optimizations (#457, #474, #475, #476, #508, #509)
|
||||
- Minor code cleanup and refactoring (#472, #479, #482, #519, #540)
|
||||
- Contributors (alphabetical order):
|
||||
- Ben Echols
|
||||
- Bruno Clermont
|
||||
- danda
|
||||
- Daniel Krawisz
|
||||
- Dario Nieuwenhuis
|
||||
- Dave Collins
|
||||
- David Hill
|
||||
- Javed Khan
|
||||
- Jonathan Gillham
|
||||
- Joseph Becher
|
||||
- Josh Rickmar
|
||||
- Justus Ranvier
|
||||
- Mawuli Adzoe
|
||||
- Olaoluwa Osuntokun
|
||||
- Rune T. Aune
|
||||
|
||||
Changes in 0.11.1 (Wed May 27 2015)
|
||||
- Protocol and network related changes:
|
||||
- Use correct sub-command in reject message for rejected transactions
|
||||
(#436, #437)
|
||||
- Add a new parameter --torisolation which forces new circuits for each
|
||||
connection when using tor (#430)
|
||||
- Transaction relay (memory pool) changes:
|
||||
- Reduce the default number max number of allowed orphan transactions
|
||||
to 1000 (#419)
|
||||
- Add a new parameter --maxorphantx which allows the maximum number of
|
||||
orphan transactions stored in the mempool to be specified (#419)
|
||||
- RPC changes:
|
||||
- Modify listtransactions result to include the 'involveswatchonly' and
|
||||
'vout' fields (#427)
|
||||
- Update getrawtransaction result to omit the 'confirmations' field
|
||||
when it is 0 (#420, #422)
|
||||
- Update signrawtransaction result to include errors (#423)
|
||||
- btcctl utility changes:
|
||||
- Add gettxoutproof command (#428)
|
||||
- Add verifytxoutproof command (#428)
|
||||
- Notable developer-related package changes:
|
||||
- The btcec package now provides the ability to perform ECDH
|
||||
encryption and decryption (#375)
|
||||
- The block and header validation in the blockchain package has been
|
||||
split to help pave the way toward concurrent downloads (#386)
|
||||
- Misc changes:
|
||||
- Minor peer optimization (#433)
|
||||
- Contributors (alphabetical order):
|
||||
- Dave Collins
|
||||
- David Hill
|
||||
- Federico Bond
|
||||
- Ishbir Singh
|
||||
- Josh Rickmar
|
||||
|
||||
Changes in 0.11.0 (Wed May 06 2015)
|
||||
- Protocol and network related changes:
|
||||
- **IMPORTANT: Update is required due to the following point**
|
||||
- Correct a few corner cases in script handling which could result in
|
||||
forking from the network on non-standard transactions (#425)
|
||||
- Add a new checkpoint at block height 352940 (#418)
|
||||
- Optimized script execution (#395, #400, #404, #409)
|
||||
- Fix a case that could lead stalled syncs (#138, #296)
|
||||
- Network address manager changes:
|
||||
- Implement eclipse attack countermeasures as proposed in
|
||||
http://cs-people.bu.edu/heilman/eclipse (#370, #373)
|
||||
- Optional address indexing changes:
|
||||
- Fix an issue where a reorg could cause an orderly shutdown when the
|
||||
address index is active (#340, #357)
|
||||
- Transaction relay (memory pool) changes:
|
||||
- Increase maximum allowed space for nulldata transactions to 80 bytes
|
||||
(#331)
|
||||
- Implement support for the following rules specified by BIP0062:
|
||||
- The S value in ECDSA signature must be at most half the curve order
|
||||
(rule 5) (#349)
|
||||
- Script execution must result in a single non-zero value on the stack
|
||||
(rule 6) (#347)
|
||||
- NOTE: All 7 rules of BIP0062 are now implemented
|
||||
- Use network adjusted time in finalized transaction checks to improve
|
||||
consistency across nodes (#332)
|
||||
- Process orphan transactions on acceptance of new transactions (#345)
|
||||
- RPC changes:
|
||||
- Add support for a limited RPC user which is not allowed admin level
|
||||
operations on the server (#363)
|
||||
- Implement node command for more unified control over connected peers
|
||||
(#79, #341)
|
||||
- Implement generate command for regtest/simnet to support
|
||||
deterministically mining a specified number of blocks (#362, #407)
|
||||
- Update searchrawtransactions to return the matching transactions in
|
||||
order (#354)
|
||||
- Correct an issue with searchrawtransactions where it could return
|
||||
duplicates (#346, #354)
|
||||
- Increase precision of 'difficulty' field in getblock result to 8
|
||||
(#414, #415)
|
||||
- Omit 'nextblockhash' field from getblock result when it is empty
|
||||
(#416, #417)
|
||||
- Add 'id' and 'timeoffset' fields to getpeerinfo result (#335)
|
||||
- Websocket changes:
|
||||
- Implement new commands stopnotifyspent, stopnotifyreceived,
|
||||
stopnotifyblocks, and stopnotifynewtransactions to allow clients to
|
||||
cancel notification registrations (#122, #342)
|
||||
- btcctl utility changes:
|
||||
- A single dash can now be used as an argument to cause that argument to
|
||||
be read from stdin (#348)
|
||||
- Add generate command
|
||||
- Notable developer-related package changes:
|
||||
- The new version 2 btcjson package has now replaced the deprecated
|
||||
version 1 package (#368)
|
||||
- The btcec package now performs all signing using RFC6979 deterministic
|
||||
signatures (#358, #360)
|
||||
- The txscript package has been significantly cleaned up and had a few
|
||||
API changes (#387, #388, #389, #390, #391, #392, #393, #395, #396,
|
||||
#400, #403, #404, #405, #406, #408, #409, #410, #412)
|
||||
- A new PkScriptLocs function has been added to the wire package MsgTx
|
||||
type which provides callers that deal with scripts optimization
|
||||
opportunities (#343)
|
||||
- Misc changes:
|
||||
- Minor wire hashing optimizations (#366, #367)
|
||||
- Other minor internal optimizations
|
||||
- Contributors (alphabetical order):
|
||||
- Alex Akselrod
|
||||
- Arne Brutschy
|
||||
- Chris Jepson
|
||||
- Daniel Krawisz
|
||||
- Dave Collins
|
||||
- David Hill
|
||||
- Jimmy Song
|
||||
- Jonas Nick
|
||||
- Josh Rickmar
|
||||
- Olaoluwa Osuntokun
|
||||
- Oleg Andreev
|
||||
|
||||
Changes in 0.10.0 (Sun Mar 01 2015)
|
||||
- Protocol and network related changes:
|
||||
- Add a new checkpoint at block height 343185
|
||||
- Implement BIP066 which includes support for version 3 blocks, a new
|
||||
consensus rule which prevents non-DER encoded signatures, and a
|
||||
double-threshold switchover mechanism
|
||||
- Rather than announcing all known addresses on getaddr requests which
|
||||
can possibly result in multiple messages, randomize the results and
|
||||
limit them to the max allowed by a single message (1000 addresses)
|
||||
- Add more reserved IP spaces to the address manager
|
||||
- Transaction relay (memory pool) changes:
|
||||
- Make transactions which contain reserved opcodes nonstandard
|
||||
- No longer accept or relay free and low-fee transactions that have
|
||||
insufficient priority to be mined in the next block
|
||||
- Implement support for the following rules specified by BIP0062:
|
||||
- ECDSA signature must use strict DER encoding (rule 1)
|
||||
- The signature script must only contain push operations (rule 2)
|
||||
- All push operations must use the smallest possible encoding (rule 3)
|
||||
- All stack values interpreted as a number must be encoding using the
|
||||
shortest possible form (rule 4)
|
||||
- NOTE: Rule 1 was already enforced, however the entire script now
|
||||
evaluates to false rather than only the signature verification as
|
||||
required by BIP0062
|
||||
- Allow transactions with nulldata transaction outputs to be treated as
|
||||
standard
|
||||
- Mining support changes:
|
||||
- Modify the getblocktemplate RPC to generate and return block templates
|
||||
for version 3 blocks which are compatible with BIP0066
|
||||
- Allow getblocktemplate to serve blocks when the current time is
|
||||
less than the minimum allowed time for a generated block template
|
||||
(https://github.com/btcsuite/btcd/issues/209)
|
||||
- Crypto changes:
|
||||
- Optimize scalar multiplication by the base point by using a
|
||||
pre-computed table which results in approximately a 35% speedup
|
||||
(https://github.com/btcsuite/btcec/issues/2)
|
||||
- Optimize general scalar multiplication by using the secp256k1
|
||||
endomorphism which results in approximately a 17-20% speedup
|
||||
(https://github.com/btcsuite/btcec/issues/1)
|
||||
- Optimize general scalar multiplication by using non-adjacent form
|
||||
which results in approximately an additional 8% speedup
|
||||
(https://github.com/btcsuite/btcec/issues/3)
|
||||
- Implement optional address indexing:
|
||||
- Add a new parameter --addrindex which will enable the creation of an
|
||||
address index which can be queried to determine all transactions which
|
||||
involve a given address
|
||||
(https://github.com/btcsuite/btcd/issues/190)
|
||||
- Add a new logging subsystem for address index related operations
|
||||
- Support new searchrawtransactions RPC
|
||||
(https://github.com/btcsuite/btcd/issues/185)
|
||||
- RPC changes:
|
||||
- Require TLS version 1.2 as the minimum version for all TLS connections
|
||||
- Provide support for disabling TLS when only listening on localhost
|
||||
(https://github.com/btcsuite/btcd/pull/192)
|
||||
- Modify help output for all commands to provide much more consistent
|
||||
and detailed information
|
||||
- Correct case in getrawtransaction which would refuse to serve certain
|
||||
transactions with invalid scripts
|
||||
(https://github.com/btcsuite/btcd/issues/210)
|
||||
- Correct error handling in the getrawtransaction RPC which could lead
|
||||
to a crash in rare cases
|
||||
(https://github.com/btcsuite/btcd/issues/196)
|
||||
- Update getinfo RPC to include the appropriate 'timeoffset' calculated
|
||||
from the median network time
|
||||
- Modify listreceivedbyaddress result type to include txids field so it
|
||||
is compatible
|
||||
- Add 'iswatchonly' field to validateaddress result
|
||||
- Add 'startingpriority' and 'currentpriority' fields to getrawmempool
|
||||
(https://github.com/btcsuite/btcd/issues/178)
|
||||
- Don't omit the 'confirmations' field from getrawtransaction when it is
|
||||
zero
|
||||
- Websocket changes:
|
||||
- Modify the behavior of the rescan command to automatically register
|
||||
for notifications about transactions paying to rescanned addresses
|
||||
or spending outputs from the final rescan utxo set when the rescan
|
||||
is through the best block in the chain
|
||||
- btcctl utility changes:
|
||||
- Make the list of commands available via the -l option rather than
|
||||
dumping the entire list on usage errors
|
||||
- Alphabetize and categorize the list of commands by chain and wallet
|
||||
- Make the help option only show the help options instead of also
|
||||
dumping all of the commands
|
||||
- Make the usage syntax much more consistent and correct a few cases of
|
||||
misnamed fields
|
||||
(https://github.com/btcsuite/btcd/issues/305)
|
||||
- Improve usage errors to show the specific parameter number, reason,
|
||||
and error code
|
||||
- Only show the usage for specific command is shown when a valid command
|
||||
is provided with invalid parameters
|
||||
- Add support for a SOCK5 proxy
|
||||
- Modify output for integer fields (such as timestamps) to display
|
||||
normally instead in scientific notation
|
||||
- Add invalidateblock command
|
||||
- Add reconsiderblock command
|
||||
- Add createnewaccount command
|
||||
- Add renameaccount command
|
||||
- Add searchrawtransactions command
|
||||
- Add importaddress command
|
||||
- Add importpubkey command
|
||||
- showblock utility changes:
|
||||
- Remove utility in favor of the RPC getblock method
|
||||
- Notable developer-related package changes:
|
||||
- Many of the core packages have been relocated into the btcd repository
|
||||
(https://github.com/btcsuite/btcd/issues/214)
|
||||
- A new version of the btcjson package that has been completely
|
||||
redesigned from the ground up based based upon how the project has
|
||||
evolved and lessons learned while using it since it was first written
|
||||
is now available in the btcjson/v2/btcjson directory
|
||||
- This will ultimately replace the current version so anyone making
|
||||
use of this package will need to update their code accordingly
|
||||
- The btcec package now provides better facilities for working directly
|
||||
with its public and private keys without having to mix elements from
|
||||
the ecdsa package
|
||||
- Update the script builder to ensure all rules specified by BIP0062 are
|
||||
adhered to when creating scripts
|
||||
- The blockchain package now provides a MedianTimeSource interface and
|
||||
concrete implementation for providing time samples from remote peers
|
||||
and using that data to calculate an offset against the local time
|
||||
- Misc changes:
|
||||
- Fix a slow memory leak due to tickers not being stopped
|
||||
(https://github.com/btcsuite/btcd/issues/189)
|
||||
- Fix an issue where a mix of orphans and SPV clients could trigger a
|
||||
condition where peers would no longer be served
|
||||
(https://github.com/btcsuite/btcd/issues/231)
|
||||
- The RPC username and password can now contain symbols which previously
|
||||
conflicted with special symbols used in URLs
|
||||
- Improve handling of obtaining random nonces to prevent cases where it
|
||||
could error when not enough entropy was available
|
||||
- Improve handling of home directory creation errors such as in the case
|
||||
of unmounted symlinks (https://github.com/btcsuite/btcd/issues/193)
|
||||
- Improve the error reporting for rejected transactions to include the
|
||||
inputs which are missing and/or being double spent
|
||||
- Update sample config file with new options and correct a comment
|
||||
regarding the fact the RPC server only listens on localhost by default
|
||||
(https://github.com/btcsuite/btcd/issues/218)
|
||||
- Update the continuous integration builds to run several tools which
|
||||
help keep code quality high
|
||||
- Significant amount of internal code cleanup and improvements
|
||||
- Other minor internal optimizations
|
||||
- Code Contributors (alphabetical order):
|
||||
- Beldur
|
||||
- Ben Holden-Crowther
|
||||
- Dave Collins
|
||||
- David Evans
|
||||
- David Hill
|
||||
- Guilherme Salgado
|
||||
- Javed Khan
|
||||
- Jimmy Song
|
||||
- John C. Vernaleo
|
||||
- Jonathan Gillham
|
||||
- Josh Rickmar
|
||||
- Michael Ford
|
||||
- Michail Kargakis
|
||||
- kac
|
||||
- Olaoluwa Osuntokun
|
||||
|
||||
Changes in 0.9.0 (Sat Sep 20 2014)
|
||||
- Protocol and network related changes:
|
||||
- Add a new checkpoint at block height 319400
|
||||
- Add support for BIP0037 bloom filters
|
||||
(https://github.com/conformal/btcd/issues/132)
|
||||
- Implement BIP0061 reject handling and hence support for protocol
|
||||
version 70002 (https://github.com/conformal/btcd/issues/133)
|
||||
- Add testnet DNS seeds for peer discovery (testnet-seed.alexykot.me
|
||||
and testnet-seed.bitcoin.schildbach.de)
|
||||
- Add mainnet DNS seed for peer discovery (seeds.bitcoin.open-nodes.org)
|
||||
- Make multisig transactions with non-null dummy data nonstandard
|
||||
(https://github.com/conformal/btcd/issues/131)
|
||||
- Make transactions with an excessive number of signature operations
|
||||
nonstandard
|
||||
- Perform initial DNS lookups concurrently which allows connections
|
||||
more quickly
|
||||
- Improve the address manager to significantly reduce memory usage and
|
||||
add tests
|
||||
- Remove orphan transactions when they appear in a mined block
|
||||
(https://github.com/conformal/btcd/issues/166)
|
||||
- Apply incremental back off on connection retries for persistent peers
|
||||
that give invalid replies to mirror the logic used for failed
|
||||
connections (https://github.com/conformal/btcd/issues/103)
|
||||
- Correct rate-limiting of free and low-fee transactions
|
||||
- Mining support changes:
|
||||
- Implement getblocktemplate RPC with the following support:
|
||||
(https://github.com/conformal/btcd/issues/124)
|
||||
- BIP0022 Non-Optional Sections
|
||||
- BIP0022 Long Polling
|
||||
- BIP0023 Basic Pool Extensions
|
||||
- BIP0023 Mutation coinbase/append
|
||||
- BIP0023 Mutations time, time/increment, and time/decrement
|
||||
- BIP0023 Mutation transactions/add
|
||||
- BIP0023 Mutations prevblock, coinbase, and generation
|
||||
- BIP0023 Block Proposals
|
||||
- Implement built-in concurrent CPU miner
|
||||
(https://github.com/conformal/btcd/issues/137)
|
||||
NOTE: CPU mining on mainnet is pointless. This has been provided
|
||||
for testing purposes such as for the new simulation test network
|
||||
- Add --generate flag to enable CPU mining
|
||||
- Deprecate the --getworkkey flag in favor of --miningaddr which
|
||||
specifies which addresses generated blocks will choose from to pay
|
||||
the subsidy to
|
||||
- RPC changes:
|
||||
- Implement gettxout command
|
||||
(https://github.com/conformal/btcd/issues/141)
|
||||
- Implement validateaddress command
|
||||
- Implement verifymessage command
|
||||
- Mark getunconfirmedbalance RPC as wallet-only
|
||||
- Mark getwalletinfo RPC as wallet-only
|
||||
- Update getgenerate, setgenerate, gethashespersec, and getmininginfo
|
||||
to return the appropriate information about new CPU mining status
|
||||
- Modify getpeerinfo pingtime and pingwait field types to float64 so
|
||||
they are compatible
|
||||
- Improve disconnect handling for normal HTTP clients
|
||||
- Make error code returns for invalid hex more consistent
|
||||
- Websocket changes:
|
||||
- Switch to a new more efficient websocket package
|
||||
(https://github.com/conformal/btcd/issues/134)
|
||||
- Add rescanfinished notification
|
||||
- Modify the rescanprogress notification to include block hash as well
|
||||
as height (https://github.com/conformal/btcd/issues/151)
|
||||
- btcctl utility changes:
|
||||
- Accept --simnet flag which automatically selects the appropriate port
|
||||
and TLS certificates needed to communicate with btcd and btcwallet on
|
||||
the simulation test network
|
||||
- Fix createrawtransaction command to send amounts denominated in BTC
|
||||
- Add estimatefee command
|
||||
- Add estimatepriority command
|
||||
- Add getmininginfo command
|
||||
- Add getnetworkinfo command
|
||||
- Add gettxout command
|
||||
- Add lockunspent command
|
||||
- Add signrawtransaction command
|
||||
- addblock utility changes:
|
||||
- Accept --simnet flag which automatically selects the appropriate port
|
||||
and TLS certificates needed to communicate with btcd and btcwallet on
|
||||
the simulation test network
|
||||
- Notable developer-related package changes:
|
||||
- Provide a new bloom package in btcutil which allows creating and
|
||||
working with BIP0037 bloom filters
|
||||
- Provide a new hdkeychain package in btcutil which allows working with
|
||||
BIP0032 hierarchical deterministic key chains
|
||||
- Introduce a new btcnet package which houses network parameters
|
||||
- Provide new simnet network (--simnet) which is useful for private
|
||||
simulation testing
|
||||
- Enforce low S values in serialized signatures as detailed in BIP0062
|
||||
- Return errors from all methods on the btcdb.Db interface
|
||||
(https://github.com/conformal/btcdb/issues/5)
|
||||
- Allow behavior flags to alter btcchain.ProcessBlock
|
||||
(https://github.com/conformal/btcchain/issues/5)
|
||||
- Provide a new SerializeSize API for blocks
|
||||
(https://github.com/conformal/btcwire/issues/19)
|
||||
- Several of the core packages now work with Google App Engine
|
||||
- Misc changes:
|
||||
- Correct an issue where the database could corrupt under certain
|
||||
circumstances which would require a new chain download
|
||||
- Slightly optimize deserialization
|
||||
- Use the correct IP block for he.net
|
||||
- Fix an issue where it was possible the block manager could hang on
|
||||
shutdown
|
||||
- Update sample config file so the comments are on a separate line
|
||||
rather than the end of a line so they are not interpreted as settings
|
||||
(https://github.com/conformal/btcd/issues/135)
|
||||
- Correct an issue where getdata requests were not being properly
|
||||
throttled which could lead to larger than necessary memory usage
|
||||
- Always show help when given the help flag even when the config file
|
||||
contains invalid entries
|
||||
- General code cleanup and minor optimizations
|
||||
|
||||
Changes in 0.8.0-beta (Sun May 25 2014)
|
||||
- Btcd is now Beta (https://github.com/conformal/btcd/issues/130)
|
||||
- Add a new checkpoint at block height 300255
|
||||
- Protocol and network related changes:
|
||||
- Lower the minimum transaction relay fee to 1000 satoshi to match
|
||||
recent reference client changes
|
||||
(https://github.com/conformal/btcd/issues/100)
|
||||
- Raise the maximum signature script size to support standard 15-of-15
|
||||
multi-signature pay-to-sript-hash transactions with compressed pubkeys
|
||||
to remain compatible with the reference client
|
||||
(https://github.com/conformal/btcd/issues/128)
|
||||
- Reduce max bytes allowed for a standard nulldata transaction to 40 for
|
||||
compatibility with the reference client
|
||||
- Introduce a new btcnet package which houses all of the network params
|
||||
for each network (mainnet, testnet3, regtest) to ultimately enable
|
||||
easier addition and tweaking of networks without needing to change
|
||||
several packages
|
||||
- Fix several script discrepancies found by reference client test data
|
||||
- Add new DNS seed for peer discovery (seed.bitnodes.io)
|
||||
- Reduce the max known inventory cache from 20000 items to 1000 items
|
||||
- Fix an issue where unknown inventory types could lead to a hung peer
|
||||
- Implement inventory rebroadcast handler for sendrawtransaction
|
||||
(https://github.com/conformal/btcd/issues/99)
|
||||
- Update user agent to fully support BIP0014
|
||||
(https://github.com/conformal/btcwire/issues/10)
|
||||
- Implement initial mining support:
|
||||
- Add a new logging subsystem for mining related operations
|
||||
- Implement infrastructure for creating block templates
|
||||
- Provide options to control block template creation settings
|
||||
- Support the getwork RPC
|
||||
- Allow address identifiers to apply to more than one network since both
|
||||
testnet3 and the regression test network unfortunately use the same
|
||||
identifier
|
||||
- RPC changes:
|
||||
- Set the content type for HTTP POST RPC connections to application/json
|
||||
(https://github.com/conformal/btcd/issues/121)
|
||||
- Modified the RPC server startup so it only requires at least one valid
|
||||
listen interface
|
||||
- Correct an error path where it was possible certain errors would not
|
||||
be returned
|
||||
- Implement getwork command
|
||||
(https://github.com/conformal/btcd/issues/125)
|
||||
- Update sendrawtransaction command to reject orphans
|
||||
- Update sendrawtransaction command to include the reason a transaction
|
||||
was rejected
|
||||
- Update getinfo command to populate connection count field
|
||||
- Update getinfo command to include relay fee field
|
||||
(https://github.com/conformal/btcd/issues/107)
|
||||
- Allow transactions submitted with sendrawtransaction to bypass the
|
||||
rate limiter
|
||||
- Allow the getcurrentnet and getbestblock extensions to be accessed via
|
||||
HTTP POST in addition to Websockets
|
||||
(https://github.com/conformal/btcd/issues/127)
|
||||
- Websocket changes:
|
||||
- Rework notifications to ensure they are delivered in the order they
|
||||
occur
|
||||
- Rename notifynewtxs command to notifyreceived (funds received)
|
||||
- Rename notifyallnewtxs command to notifynewtransactions
|
||||
- Rename alltx notification to txaccepted
|
||||
- Rename allverbosetx notification to txacceptedverbose
|
||||
(https://github.com/conformal/btcd/issues/98)
|
||||
- Add rescan progress notification
|
||||
- Add recvtx notification
|
||||
- Add redeemingtx notification
|
||||
- Modify notifyspent command to accept an array of outpoints
|
||||
(https://github.com/conformal/btcd/issues/123)
|
||||
- Significantly optimize the rescan command to yield up to a 60x speed
|
||||
increase
|
||||
- btcctl utility changes:
|
||||
- Add createencryptedwallet command
|
||||
- Add getblockchaininfo command
|
||||
- Add importwallet command
|
||||
- Add addmultisigaddress command
|
||||
- Add setgenerate command
|
||||
- Accept --testnet and --wallet flags which automatically select
|
||||
the appropriate port and TLS certificates needed to communicate
|
||||
with btcd and btcwallet (https://github.com/conformal/btcd/issues/112)
|
||||
- Allow path expansion from config file entries
|
||||
(https://github.com/conformal/btcd/issues/113)
|
||||
- Minor refactor simplify handling of options
|
||||
- addblock utility changes:
|
||||
- Improve logging by making it consistent with the logging provided by
|
||||
btcd (https://github.com/conformal/btcd/issues/90)
|
||||
- Improve several package APIs for developers:
|
||||
- Add new amount type for consistently handling monetary values
|
||||
- Add new coin selector API
|
||||
- Add new WIF (Wallet Import Format) API
|
||||
- Add new crypto types for private keys and signatures
|
||||
- Add new API to sign transactions including script merging and hash
|
||||
types
|
||||
- Expose function to extract all pushed data from a script
|
||||
(https://github.com/conformal/btcscript/issues/8)
|
||||
- Misc changes:
|
||||
- Optimize address manager shuffling to do 67% less work on average
|
||||
- Resolve a couple of benign data races found by the race detector
|
||||
(https://github.com/conformal/btcd/issues/101)
|
||||
- Add IP address to all peer related errors to clarify which peer is the
|
||||
cause (https://github.com/conformal/btcd/issues/102)
|
||||
- Fix a UPNP case issue that prevented the --upnp option from working
|
||||
with some UPNP servers
|
||||
- Update documentation in the sample config file regarding debug levels
|
||||
- Adjust some logging levels to improve debug messages
|
||||
- Improve the throughput of query messages to the block manager
|
||||
- Several minor optimizations to reduce GC churn and enhance speed
|
||||
- Other minor refactoring
|
||||
- General code cleanup
|
||||
|
||||
Changes in 0.7.0 (Thu Feb 20 2014)
|
||||
- Fix an issue when parsing scripts which contain a multi-signature script
|
||||
which require zero signatures such as testnet block
|
||||
000000001881dccfeda317393c261f76d09e399e15e27d280e5368420f442632
|
||||
(https://github.com/conformal/btcscript/issues/7)
|
||||
- Add check to ensure all transactions accepted to mempool only contain
|
||||
canonical data pushes (https://github.com/conformal/btcscript/issues/6)
|
||||
- Fix an issue causing excessive memory consumption
|
||||
- Significantly rework and improve the websocket notification system:
|
||||
- Each client is now independent so slow clients no longer limit the
|
||||
speed of other connected clients
|
||||
- Potentially long-running operations such as rescans are now run in
|
||||
their own handler and rate-limited to one operation at a time without
|
||||
preventing simultaneous requests from the same client for the faster
|
||||
requests or notifications
|
||||
- A couple of scenarios which could cause shutdown to hang have been
|
||||
resolved
|
||||
- Update notifynewtx notifications to support all address types instead
|
||||
of only pay-to-pubkey-hash
|
||||
- Provide a --rpcmaxwebsockets option to allow limiting the number of
|
||||
concurrent websocket clients
|
||||
- Add a new websocket command notifyallnewtxs to request notifications
|
||||
(https://github.com/conformal/btcd/issues/86) (thanks @flammit)
|
||||
- Improve btcctl utility in the following ways:
|
||||
- Add getnetworkhashps command
|
||||
- Add gettransaction command (wallet-specific)
|
||||
- Add signmessage command (wallet-specific)
|
||||
- Update getwork command to accept
|
||||
- Continue cleanup and work on implementing the RPC API:
|
||||
- Implement getnettotals command
|
||||
(https://github.com/conformal/btcd/issues/84)
|
||||
- Implement networkhashps command
|
||||
(https://github.com/conformal/btcd/issues/87)
|
||||
- Update getpeerinfo to always include syncnode field even when false
|
||||
- Remove help addenda for getpeerinfo now that it supports all fields
|
||||
- Close standard RPC connections on auth failure
|
||||
- Provide a --rpcmaxclients option to allow limiting the number of
|
||||
concurrent RPC clients (https://github.com/conformal/btcd/issues/68)
|
||||
- Include IP address in RPC auth failure log messages
|
||||
- Resolve a rather harmless data races found by the race detector
|
||||
(https://github.com/conformal/btcd/issues/94)
|
||||
- Increase block priority size and max standard transaction size to 50k
|
||||
and 100k, respectively (https://github.com/conformal/btcd/issues/71)
|
||||
- Add rate limiting of free transactions to the memory pool to prevent
|
||||
penny flooding (https://github.com/conformal/btcd/issues/40)
|
||||
- Provide a --logdir option (https://github.com/conformal/btcd/issues/95)
|
||||
- Change the default log file path to include the network
|
||||
- Add a new ScriptBuilder interface to btcscript to support creation of
|
||||
custom scripts (https://github.com/conformal/btcscript/issues/5)
|
||||
- General code cleanup
|
||||
|
||||
Changes in 0.6.0 (Tue Feb 04 2014)
|
||||
- Fix an issue when parsing scripts which contain invalid signatures that
|
||||
caused a chain fork on block
|
||||
0000000000000001e4241fd0b3469a713f41c5682605451c05d3033288fb2244
|
||||
- Correct an issue which could lead to an error in removeBlockNode
|
||||
(https://github.com/conformal/btcchain/issues/4)
|
||||
- Improve addblock utility as follows:
|
||||
- Check imported blocks against all chain rules and checkpoints
|
||||
- Skip blocks which are already known so you can stop and restart the
|
||||
import or start the import after you have already downloaded a portion
|
||||
of the chain
|
||||
- Correct an issue where the utility did not shutdown cleanly after
|
||||
processing all blocks
|
||||
- Add error on attempt to import orphan blocks
|
||||
- Improve error handling and reporting
|
||||
- Display statistics after input file has been fully processed
|
||||
- Rework, optimize, and improve headers-first mode:
|
||||
- Resuming the chain sync from any point before the final checkpoint
|
||||
will now use headers-first mode
|
||||
(https://github.com/conformal/btcd/issues/69)
|
||||
- Verify all checkpoints as opposed to only the final one
|
||||
- Reduce and bound memory usage
|
||||
- Rollback to the last known good point when a header does not match a
|
||||
checkpoint
|
||||
- Log information about what is happening with headers
|
||||
- Improve btcctl utility in the following ways:
|
||||
- Add getaddednodeinfo command
|
||||
- Add getnettotals command
|
||||
- Add getblocktemplate command (wallet-specific)
|
||||
- Add getwork command (wallet-specific)
|
||||
- Add getnewaddress command (wallet-specific)
|
||||
- Add walletpassphrasechange command (wallet-specific)
|
||||
- Add walletlock command (wallet-specific)
|
||||
- Add sendfrom command (wallet-specific)
|
||||
- Add sendmany command (wallet-specific)
|
||||
- Add settxfee command (wallet-specific)
|
||||
- Add listsinceblock command (wallet-specific)
|
||||
- Add listaccounts command (wallet-specific)
|
||||
- Add keypoolrefill command (wallet-specific)
|
||||
- Add getreceivedbyaccount command (wallet-specific)
|
||||
- Add getrawchangeaddress command (wallet-specific)
|
||||
- Add gettxoutsetinfo command (wallet-specific)
|
||||
- Add listaddressgroupings command (wallet-specific)
|
||||
- Add listlockunspent command (wallet-specific)
|
||||
- Add listlock command (wallet-specific)
|
||||
- Add listreceivedbyaccount command (wallet-specific)
|
||||
- Add validateaddress command (wallet-specific)
|
||||
- Add verifymessage command (wallet-specific)
|
||||
- Add sendtoaddress command (wallet-specific)
|
||||
- Continue cleanup and work on implementing the RPC API:
|
||||
- Implement submitblock command
|
||||
(https://github.com/conformal/btcd/issues/61)
|
||||
- Implement help command
|
||||
- Implement ping command
|
||||
- Implement getaddednodeinfo command
|
||||
(https://github.com/conformal/btcd/issues/78)
|
||||
- Implement getinfo command
|
||||
- Update getpeerinfo to support bytesrecv and bytessent
|
||||
(https://github.com/conformal/btcd/issues/83)
|
||||
- Improve and correct several RPC server and websocket areas:
|
||||
- Change the connection endpoint for websockets from /wallet to /ws
|
||||
(https://github.com/conformal/btcd/issues/80)
|
||||
- Implement an alternative authentication for websockets so clients
|
||||
such as javascript from browsers that don't support setting HTTP
|
||||
headers can authenticate (https://github.com/conformal/btcd/issues/77)
|
||||
- Add an authentication deadline for RPC connections
|
||||
(https://github.com/conformal/btcd/issues/68)
|
||||
- Use standard authentication failure responses for RPC connections
|
||||
- Make automatically generated certificate more standard so it works
|
||||
from client such as node.js and Firefox
|
||||
- Correct some minor issues which could prevent the RPC server from
|
||||
shutting down in an orderly fashion
|
||||
- Make all websocket notifications require registration
|
||||
- Change the data sent over websockets to text since it is JSON-RPC
|
||||
- Allow connections that do not have an Origin header set
|
||||
- Expose and track the number of bytes read and written per peer
|
||||
(https://github.com/conformal/btcwire/issues/6)
|
||||
- Correct an issue with sendrawtransaction when invoked via websockets
|
||||
which prevented a minedtx notification from being added
|
||||
- Rescan operations issued from remote wallets are no stopped when
|
||||
the wallet disconnects mid-operation
|
||||
(https://github.com/conformal/btcd/issues/66)
|
||||
- Several optimizations related to fetching block information from the
|
||||
database
|
||||
- General code cleanup
|
||||
|
||||
Changes in 0.5.0 (Mon Jan 13 2014)
|
||||
- Optimize initial block download by introducing a new mode which
|
||||
downloads the block headers first (up to the final checkpoint)
|
||||
- Improve peer handling to remove the potential for slow peers to cause
|
||||
sluggishness amongst all peers
|
||||
(https://github.com/conformal/btcd/issues/63)
|
||||
- Fix an issue where the initial block sync could stall when the sync peer
|
||||
disconnects (https://github.com/conformal/btcd/issues/62)
|
||||
- Correct an issue where --externalip was doing a DNS lookup on the full
|
||||
host:port instead of just the host portion
|
||||
(https://github.com/conformal/btcd/issues/38)
|
||||
- Fix an issue which could lead to a panic on chain switches
|
||||
(https://github.com/conformal/btcd/issues/70)
|
||||
- Improve btcctl utility in the following ways:
|
||||
- Show getdifficulty output as floating point to 6 digits of precision
|
||||
- Show all JSON object replies formatted as standard JSON
|
||||
- Allow btcctl getblock to accept optional params
|
||||
- Add getaccount command (wallet-specific)
|
||||
- Add getaccountaddress command (wallet-specific)
|
||||
- Add sendrawtransaction command
|
||||
- Continue cleanup and work on implementing RPC API calls
|
||||
- Update getrawmempool to support new optional verbose flag
|
||||
- Update getrawtransaction to match the reference client
|
||||
- Update getblock to support new optional verbose flag
|
||||
- Update raw transactions to fully match the reference client including
|
||||
support for all transaction types and address types
|
||||
- Correct getrawmempool fee field to return BTC instead of Satoshi
|
||||
- Correct getpeerinfo service flag to return 8 digit string so it
|
||||
matches the reference client
|
||||
- Correct verifychain to return a boolean
|
||||
- Implement decoderawtransaction command
|
||||
- Implement createrawtransaction command
|
||||
- Implement decodescript command
|
||||
- Implement gethashespersec command
|
||||
- Allow RPC handler overrides when invoked via a websocket versus
|
||||
legacy connection
|
||||
- Add new DNS seed for peer discovery
|
||||
- Display user agent on new valid peer log message
|
||||
(https://github.com/conformal/btcd/issues/64)
|
||||
- Notify wallet when new transactions that pay to registered addresses
|
||||
show up in the mempool before being mined into a block
|
||||
- Support a tor-specific proxy in addition to a normal proxy
|
||||
(https://github.com/conformal/btcd/issues/47)
|
||||
- Remove deprecated sqlite3 imports from utilities
|
||||
- Remove leftover profile write from addblock utility
|
||||
- Quite a bit of code cleanup and refactoring to improve maintainability
|
||||
|
||||
Changes in 0.4.0 (Thu Dec 12 2013)
|
||||
- Allow listen interfaces to be specified via --listen instead of only the
|
||||
port (https://github.com/conformal/btcd/issues/33)
|
||||
- Allow listen interfaces for the RPC server to be specified via
|
||||
--rpclisten instead of only the port
|
||||
(https://github.com/conformal/btcd/issues/34)
|
||||
- Only disable listening when --connect or --proxy are used when no
|
||||
--listen interface are specified
|
||||
(https://github.com/conformal/btcd/issues/10)
|
||||
- Add several new standard transaction checks to transaction memory pool:
|
||||
- Support nulldata scripts as standard
|
||||
- Only allow a max of one nulldata output per transaction
|
||||
- Enforce a maximum of 3 public keys in multi-signature transactions
|
||||
- The number of signatures in multi-signature transactions must not
|
||||
exceed the number of public keys
|
||||
- The number of inputs to a signature script must match the expected
|
||||
number of inputs for the script type
|
||||
- The number of inputs pushed onto the stack by a redeeming signature
|
||||
script must match the number of inputs consumed by the referenced
|
||||
public key script
|
||||
- When a block is connected, remove any transactions from the memory pool
|
||||
which are now double spends as a result of the newly connected
|
||||
transactions
|
||||
- Don't relay transactions resurrected during a chain switch since
|
||||
other peers will also be switching chains and therefore already know
|
||||
about them
|
||||
- Cleanup a few cases where rejected transactions showed as an error
|
||||
rather than as a rejected transaction
|
||||
- Ignore the default configuration file when --regtest (regression test
|
||||
mode) is specified
|
||||
- Implement TLS support for RPC including automatic certificate generation
|
||||
- Support HTTP authentication headers for web sockets
|
||||
- Update address manager to recognize and properly work with Tor
|
||||
addresses (https://github.com/conformal/btcd/issues/36) and
|
||||
(https://github.com/conformal/btcd/issues/37)
|
||||
- Improve btcctl utility in the following ways:
|
||||
- Add the ability to specify a configuration file
|
||||
- Add a default entry for the RPC cert to point to the location
|
||||
it will likely be in the btcd home directory
|
||||
- Implement --version flag
|
||||
- Provide a --notls option to support non-TLS configurations
|
||||
- Fix a couple of minor races found by the Go race detector
|
||||
- Improve logging
|
||||
- Allow logging level to be specified on a per subsystem basis
|
||||
(https://github.com/conformal/btcd/issues/48)
|
||||
- Allow logging levels to be dynamically changed via RPC
|
||||
(https://github.com/conformal/btcd/issues/15)
|
||||
- Implement a rolling log file with a max of 10MB per file and a
|
||||
rotation size of 3 which results in a max logging size of 30 MB
|
||||
- Correct a minor issue with the rescanning websocket call
|
||||
(https://github.com/conformal/btcd/issues/54)
|
||||
- Fix a race with pushing address messages that could lead to a panic
|
||||
(https://github.com/conformal/btcd/issues/58)
|
||||
- Improve which external IP address is reported to peers based on which
|
||||
interface they are connected through
|
||||
(https://github.com/conformal/btcd/issues/35)
|
||||
- Add --externalip option to allow an external IP address to be specified
|
||||
for cases such as tor hidden services or advanced network configurations
|
||||
(https://github.com/conformal/btcd/issues/38)
|
||||
- Add --upnp option to support automatic port mapping via UPnP
|
||||
(https://github.com/conformal/btcd/issues/51)
|
||||
- Update Ctrl+C interrupt handler to properly sync address manager and
|
||||
remove the UPnP port mapping (if needed)
|
||||
- Continue cleanup and work on implementing RPC API calls
|
||||
- Add importprivkey (import private key) command to btcctl
|
||||
- Update getrawtransaction to provide addresses properly, support
|
||||
new verbose param, and match the reference implementation with the
|
||||
exception of MULTISIG (thanks @flammit)
|
||||
- Update getblock with new verbose flag (thanks @flammit)
|
||||
- Add listtransactions command to btcctl
|
||||
- Add getbalance command to btcctl
|
||||
- Add basic support for btcd to run as a native Windows service
|
||||
(https://github.com/conformal/btcd/issues/42)
|
||||
- Package addblock utility with Windows MSIs
|
||||
- Add support for TravisCI (continuous build integration)
|
||||
- Cleanup some documentation and usage
|
||||
- Several other minor bug fixes and general code cleanup
|
||||
|
||||
Changes in 0.3.3 (Wed Nov 13 2013)
|
||||
- Significantly improve initial block chain download speed
|
||||
(https://github.com/conformal/btcd/issues/20)
|
||||
- Add a new checkpoint at block height 267300
|
||||
- Optimize most recently used inventory handling
|
||||
(https://github.com/conformal/btcd/issues/21)
|
||||
- Optimize duplicate transaction input check
|
||||
(https://github.com/conformal/btcchain/issues/2)
|
||||
- Optimize transaction hashing
|
||||
(https://github.com/conformal/btcd/issues/25)
|
||||
- Rework and optimize wallet listener notifications
|
||||
(https://github.com/conformal/btcd/issues/22)
|
||||
- Optimize serialization and deserialization
|
||||
(https://github.com/conformal/btcd/issues/27)
|
||||
- Add support for minimum transaction fee to memory pool acceptance
|
||||
(https://github.com/conformal/btcd/issues/29)
|
||||
- Improve leveldb database performance by removing explicit GC call
|
||||
- Fix an issue where Ctrl+C was not always finishing orderly database
|
||||
shutdown
|
||||
- Fix an issue in the script handling for OP_CHECKSIG
|
||||
- Impose max limits on all variable length protocol entries to prevent
|
||||
abuse from malicious peers
|
||||
- Enforce DER signatures for transactions allowed into the memory pool
|
||||
- Separate the debug profile http server from the RPC server
|
||||
- Rework of the RPC code to improve performance and make the code cleaner
|
||||
- The getrawtransaction RPC call now properly checks the memory pool
|
||||
before consulting the db (https://github.com/conformal/btcd/issues/26)
|
||||
- Add support for the following RPC calls: getpeerinfo, getconnectedcount,
|
||||
addnode, verifychain
|
||||
(https://github.com/conformal/btcd/issues/13)
|
||||
(https://github.com/conformal/btcd/issues/17)
|
||||
- Implement rescan websocket extension to allow wallet rescans
|
||||
- Use correct paths for application data storage for all supported
|
||||
operating systems (https://github.com/conformal/btcd/issues/30)
|
||||
- Add a default redirect to the http profiling page when accessing the
|
||||
http profile server
|
||||
- Add a new --cpuprofile option which can be used to generate CPU
|
||||
profiling data on platforms that support it
|
||||
- Several other minor performance optimizations
|
||||
- Other minor bug fixes and general code cleanup
|
||||
|
||||
Changes in 0.3.2 (Tue Oct 22 2013)
|
||||
- Fix an issue that could cause the download of the block chain to stall
|
||||
(https://github.com/conformal/btcd/issues/12)
|
||||
- Remove deprecated sqlite as an available database backend
|
||||
- Close sqlite compile issue as sqlite has now been removed
|
||||
(https://github.com/conformal/btcd/issues/11)
|
||||
- Change default RPC ports to 8334 (mainnet) and 18334 (testnet)
|
||||
- Continue cleanup and work on implementing RPC API calls
|
||||
- Add support for the following RPC calls: getrawmempool,
|
||||
getbestblockhash, decoderawtransaction, getdifficulty,
|
||||
getconnectioncount, getpeerinfo, and addnode
|
||||
- Improve the btcctl utility that is used to issue JSON-RPC commands
|
||||
- Fix an issue preventing btcd from cleanly shutting down with the RPC
|
||||
stop command
|
||||
- Add a number of database interface tests to ensure backends implement
|
||||
the expected interface
|
||||
- Expose some additional information from btcscript to be used for
|
||||
identifying "standard"" transactions
|
||||
- Add support for plan9 - thanks @mischief
|
||||
(https://github.com/conformal/btcd/pull/19)
|
||||
- Other minor bug fixes and general code cleanup
|
||||
|
||||
Changes in 0.3.1-alpha (Tue Oct 15 2013)
|
||||
- Change default database to leveldb
|
||||
NOTE: This does mean you will have to redownload the block chain. Since we
|
||||
are still in alpha, we didn't feel writing a converter was worth the time as
|
||||
it would take away from more important issues at this stage
|
||||
- Add a warning if there are multiple block chain databases of different types
|
||||
- Fix issue with unexpected EOF in leveldb -- https://github.com/conformal/btcd/issues/18
|
||||
- Fix issue preventing block 21066 on testnet -- https://github.com/conformal/btcchain/issues/1
|
||||
- Fix issue preventing block 96464 on testnet -- https://github.com/conformal/btcscript/issues/1
|
||||
- Optimize transaction lookups
|
||||
- Correct a few cases of list removal that could result in improper cleanup
|
||||
of no longer needed orphans
|
||||
- Add functionality to increase ulimits on non-Windows platforms
|
||||
- Add support for mempool command which allows remote peers to query the
|
||||
transaction memory pool via the bitcoin protocol
|
||||
- Clean up logging a bit
|
||||
- Add a flag to disable checkpoints for developers
|
||||
- Add a lot of useful debug logging such as message summaries
|
||||
- Other minor bug fixes and general code cleanup
|
||||
|
||||
Initial Release 0.3.0-alpha (Sat Oct 05 2013):
|
||||
- Initial release
|
||||
@@ -1,19 +0,0 @@
|
||||
# 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.
|
||||
105
Gopkg.lock
generated
Normal file
105
Gopkg.lock
generated
Normal file
@@ -0,0 +1,105 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
name = "bou.ke/monkey"
|
||||
packages = ["."]
|
||||
revision = "bdf6dea004c6fd1cdf4b25da8ad45a606c09409a"
|
||||
version = "v1.0.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/aead/siphash"
|
||||
packages = ["."]
|
||||
revision = "83563a290f60225eb120d724600b9690c3fb536f"
|
||||
version = "v1.0.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/btcsuite/btclog"
|
||||
packages = ["."]
|
||||
revision = "84c8d2346e9fc8c7b947e243b9c24e6df9fd206a"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/btcsuite/go-socks"
|
||||
packages = ["socks"]
|
||||
revision = "4720035b7bfd2a9bb130b1c184f8bbe41b6f0d0f"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/btcsuite/goleveldb"
|
||||
packages = ["leveldb","leveldb/cache","leveldb/comparer","leveldb/errors","leveldb/filter","leveldb/iterator","leveldb/journal","leveldb/memdb","leveldb/opt","leveldb/storage","leveldb/table","leveldb/util"]
|
||||
revision = "3fd0373267b6461dbefe91cef614278064d05465"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/btcsuite/snappy-go"
|
||||
packages = ["."]
|
||||
revision = "b3db38edf0a9a11a115eb6b022d8c946024a9ac0"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/btcsuite/websocket"
|
||||
packages = ["."]
|
||||
revision = "31079b6807923eb23992c421b114992b95131b55"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/btcsuite/winsvc"
|
||||
packages = ["eventlog","mgr","registry","svc","winapi"]
|
||||
revision = "f8fb11f83f7e860e3769a08e6811d1b399a43722"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/davecgh/go-spew"
|
||||
packages = ["spew"]
|
||||
revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
|
||||
version = "v1.1.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/jessevdk/go-flags"
|
||||
packages = ["."]
|
||||
revision = "c6ca198ec95c841fdb89fc0de7496fed11ab854e"
|
||||
version = "v1.4.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/jrick/logrotate"
|
||||
packages = ["rotator"]
|
||||
revision = "a93b200c26cbae3bb09dd0dc2c7c7fe1468a034a"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/kkdai/bstream"
|
||||
packages = ["."]
|
||||
revision = "b3251f7901ec4dd4ec66b3210e8f4bd5c0f1c5a3"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/miekg/dns"
|
||||
packages = ["."]
|
||||
revision = "cc8cd02140663157ce797c6650488d6c8563f31f"
|
||||
version = "v1.1.6"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = ["ed25519","ed25519/internal/edwards25519","ripemd160"]
|
||||
revision = "c2843e01d9a2bc60bb26ad24e09734fdc2d9ec58"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = ["bpf","internal/iana","internal/socket","ipv4","ipv6"]
|
||||
revision = "d8887717615a059821345a5c23649351b52a1c0b"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["unix"]
|
||||
revision = "fead79001313d15903fb4605b4a1b781532cd93e"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "00392a00928f96fc94e2c8c65ce3a98cc6f5e2f93dda64d3c4502f2f38026e96"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
78
Gopkg.toml
Normal file
78
Gopkg.toml
Normal file
@@ -0,0 +1,78 @@
|
||||
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
|
||||
|
||||
[[constraint]]
|
||||
name = "bou.ke/monkey"
|
||||
version = "1.0.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/aead/siphash"
|
||||
version = "1.0.1"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/btcsuite/btclog"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/btcsuite/go-socks"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/btcsuite/goleveldb"
|
||||
version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/btcsuite/websocket"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/btcsuite/winsvc"
|
||||
version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/davecgh/go-spew"
|
||||
version = "1.1.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/jessevdk/go-flags"
|
||||
version = "1.4.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/jrick/logrotate"
|
||||
version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/kkdai/bstream"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/miekg/dns"
|
||||
version = "1.1.6"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
||||
10
Jenkinsfile
vendored
Normal file
10
Jenkinsfile
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
node {
|
||||
stage 'Checkout'
|
||||
checkout scm
|
||||
|
||||
stage 'Version'
|
||||
sh './deploy.sh version'
|
||||
|
||||
stage 'Build'
|
||||
sh "./deploy.sh build"
|
||||
}
|
||||
3
LICENSE
3
LICENSE
@@ -1,9 +1,8 @@
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2018-2019 The kaspanet developers
|
||||
Copyright (c) 2018-2019 DAGLabs
|
||||
Copyright (c) 2013-2018 The btcsuite developers
|
||||
Copyright (c) 2015-2016 The Decred developers
|
||||
Copyright (c) 2013-2014 Conformal Systems LLC.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
|
||||
126
README.md
126
README.md
@@ -1,28 +1,49 @@
|
||||
|
||||
Kaspad
|
||||
====
|
||||
Warning: This is pre-alpha software. There's no guarantee anything works.
|
||||
btcd
|
||||
====
|
||||
|
||||
[](https://choosealicense.com/licenses/isc/)
|
||||
[](http://godoc.org/github.com/kaspanet/kaspad)
|
||||
[](https://travis-ci.org/btcsuite/btcd)
|
||||
[](http://copyfree.org)
|
||||
[](http://godoc.org/github.com/daglabs/btcd)
|
||||
|
||||
Kaspad is the reference full node Kaspa implementation written in Go (golang).
|
||||
btcd is an alternative full node bitcoin implementation written in Go (golang).
|
||||
|
||||
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.
|
||||
This project is currently under active development and is in a Beta state. It
|
||||
is extremely stable and has been in production use since October 2013.
|
||||
|
||||
## What is kaspa
|
||||
It properly downloads, validates, and serves the block chain using the exact
|
||||
rules (including consensus bugs) for block acceptance as Bitcoin Core. We have
|
||||
taken great care to avoid btcd causing a fork to the block chain. It includes a
|
||||
full block validation testing framework which contains all of the 'official'
|
||||
block acceptance tests (and some additional ones) that is run on every pull
|
||||
request to help ensure it properly follows consensus. Also, it passes all of
|
||||
the JSON test data in the Bitcoin Core code.
|
||||
|
||||
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.
|
||||
It also properly relays newly mined blocks, maintains a transaction pool, and
|
||||
relays individual transactions that have not yet made it into a block. It
|
||||
ensures all individual transactions admitted to the pool follow the rules
|
||||
required by the block chain and also includes more strict checks which filter
|
||||
transactions based on miner requirements ("standard" transactions).
|
||||
|
||||
One key difference between btcd and Bitcoin Core is that btcd does *NOT* include
|
||||
wallet functionality and this was a very intentional design decision. See the
|
||||
blog entry [here](https://blog.conformal.com/btcd-not-your-moms-bitcoin-daemon)
|
||||
for more details. This means you can't actually make or receive payments
|
||||
directly with btcd. That functionality is provided by the
|
||||
[btcwallet](https://github.com/btcsuite/btcwallet) and
|
||||
[Paymetheus](https://github.com/btcsuite/Paymetheus) (Windows-only) projects
|
||||
which are both under active development.
|
||||
|
||||
## Requirements
|
||||
|
||||
Go 1.16 or later.
|
||||
[Go](http://golang.org) 1.8 or newer.
|
||||
|
||||
## Installation
|
||||
|
||||
#### Build from Source
|
||||
#### Windows - MSI Available
|
||||
|
||||
https://github.com/daglabs/btcd/releases
|
||||
|
||||
#### Linux/BSD/MacOSX/POSIX - Build from Source
|
||||
|
||||
- Install Go according to the installation instructions here:
|
||||
http://golang.org/doc/install
|
||||
@@ -31,42 +52,95 @@ Go 1.16 or later.
|
||||
|
||||
```bash
|
||||
$ go version
|
||||
$ go env GOROOT GOPATH
|
||||
```
|
||||
|
||||
- Run the following commands to obtain and install kaspad including all dependencies:
|
||||
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
|
||||
`~/goprojects` 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 btcd, all dependencies, and install it:
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/kaspanet/kaspad
|
||||
$ cd kaspad
|
||||
$ # Install dep: https://golang.github.io/dep/docs/installation.html
|
||||
$ git clone https://github.com/daglabs/btcd $GOPATH/src/github.com/daglabs/btcd
|
||||
$ cd $GOPATH/src/github.com/daglabs/btcd
|
||||
$ dep ensure
|
||||
$ go install . ./cmd/...
|
||||
```
|
||||
|
||||
- Kaspad (and utilities) should now be installed in `$(go env GOPATH)/bin`. If you did
|
||||
- btcd (and utilities) will now be installed in ```$GOPATH/bin```. If you did
|
||||
not already add the bin directory to your system path during Go installation,
|
||||
you are encouraged to do so now.
|
||||
we recommend you do so now.
|
||||
|
||||
## Updating
|
||||
|
||||
#### Windows
|
||||
|
||||
Install a newer MSI
|
||||
|
||||
#### Linux/BSD/MacOSX/POSIX - Build from Source
|
||||
|
||||
- Run the following commands to update btcd, all dependencies, and install it:
|
||||
|
||||
```bash
|
||||
$ cd $GOPATH/src/github.com/daglabs/btcd
|
||||
$ git pull && dep ensure
|
||||
$ go install . ./cmd/...
|
||||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
Kaspad has several configuration options available to tweak how it runs, but all
|
||||
of the basic operations work with zero configuration.
|
||||
btcd has several configuration options available to tweak how it runs, but all
|
||||
of the basic operations described in the intro section work with zero
|
||||
configuration.
|
||||
|
||||
#### Windows (Installed from MSI)
|
||||
|
||||
Launch btcd from your Start menu.
|
||||
|
||||
#### Linux/BSD/POSIX/Source
|
||||
|
||||
```bash
|
||||
$ kaspad
|
||||
$ ./btcd
|
||||
```
|
||||
|
||||
## Discord
|
||||
Join our discord server using the following link: https://discord.gg/WmGhhzk
|
||||
## IRC
|
||||
|
||||
- irc.freenode.net
|
||||
- channel #btcd
|
||||
- [webchat](https://webchat.freenode.net/?channels=btcd)
|
||||
|
||||
## Issue Tracker
|
||||
|
||||
The [integrated github issue tracker](https://github.com/kaspanet/kaspad/issues)
|
||||
The [integrated github issue tracker](https://github.com/daglabs/btcd/issues)
|
||||
is used for this project.
|
||||
|
||||
## Documentation
|
||||
|
||||
The [documentation](https://github.com/kaspanet/docs) is a work-in-progress
|
||||
The documentation is a work-in-progress. It is located in the [docs](https://github.com/daglabs/btcd/tree/master/docs) folder.
|
||||
|
||||
## GPG Verification Key
|
||||
|
||||
All official release tags are signed by Conformal so users can ensure the code
|
||||
has not been tampered with and is coming from the btcsuite developers. To
|
||||
verify the signature perform the following:
|
||||
|
||||
- Download the Conformal public key:
|
||||
https://raw.githubusercontent.com/btcsuite/btcd/master/release/GIT-GPG-KEY-conformal.txt
|
||||
|
||||
- Import the public key into your GPG keyring:
|
||||
```bash
|
||||
gpg --import GIT-GPG-KEY-conformal.txt
|
||||
```
|
||||
|
||||
- Verify the release tag with the following command where `TAG_NAME` is a
|
||||
placeholder for the specific tag:
|
||||
```bash
|
||||
git tag -v TAG_NAME
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
Kaspad is licensed under the copyfree [ISC License](https://choosealicense.com/licenses/isc/).
|
||||
btcd is licensed under the [copyfree](http://copyfree.org) ISC License.
|
||||
|
||||
1379
addrmgr/addrmanager.go
Normal file
1379
addrmgr/addrmanager.go
Normal file
File diff suppressed because it is too large
Load Diff
590
addrmgr/addrmanager_test.go
Normal file
590
addrmgr/addrmanager_test.go
Normal file
@@ -0,0 +1,590 @@
|
||||
// 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 addrmgr
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/daglabs/btcd/util/subnetworkid"
|
||||
|
||||
"github.com/daglabs/btcd/wire"
|
||||
)
|
||||
|
||||
// naTest is used to describe a test to be performed against the NetAddressKey
|
||||
// method.
|
||||
type naTest struct {
|
||||
in wire.NetAddress
|
||||
want string
|
||||
}
|
||||
|
||||
// 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", 8333, "127.0.0.1:8333")
|
||||
addNaTest("127.0.0.1", 8334, "127.0.0.1:8334")
|
||||
|
||||
// Class A
|
||||
addNaTest("1.0.0.1", 8333, "1.0.0.1:8333")
|
||||
addNaTest("2.2.2.2", 8334, "2.2.2.2:8334")
|
||||
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", 8333, "10.0.0.1:8333")
|
||||
addNaTest("10.1.1.1", 8334, "10.1.1.1:8334")
|
||||
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", 8333, "128.0.0.1:8333")
|
||||
addNaTest("129.1.1.1", 8334, "129.1.1.1:8334")
|
||||
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", 8333, "172.16.0.1:8333")
|
||||
addNaTest("172.16.1.1", 8334, "172.16.1.1:8334")
|
||||
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", 8333, "193.0.0.1:8333")
|
||||
addNaTest("200.1.1.1", 8334, "200.1.1.1:8334")
|
||||
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", 8333, "192.168.0.1:8333")
|
||||
addNaTest("192.168.1.1", 8334, "192.168.1.1:8334")
|
||||
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", 8333, "[::1]:8333")
|
||||
addNaTest("fe80::1", 8334, "[fe80::1]:8334")
|
||||
|
||||
// Link-local
|
||||
addNaTest("fe80::1:1", 8333, "[fe80::1:1]:8333")
|
||||
addNaTest("fe91::2:2", 8334, "[fe91::2:2]:8334")
|
||||
addNaTest("fea2::3:3", 8335, "[fea2::3:3]:8335")
|
||||
addNaTest("feb3::4:4", 8336, "[feb3::4:4]:8336")
|
||||
|
||||
// Site-local
|
||||
addNaTest("fec0::1:1", 8333, "[fec0::1:1]:8333")
|
||||
addNaTest("fed1::2:2", 8334, "[fed1::2:2]:8334")
|
||||
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 string) {
|
||||
nip := net.ParseIP(ip)
|
||||
na := *wire.NewNetAddressIPPort(nip, port, wire.SFNodeNetwork)
|
||||
test := naTest{na, want}
|
||||
naTests = append(naTests, test)
|
||||
}
|
||||
|
||||
func lookupFunc(host string) ([]net.IP, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func TestStartStop(t *testing.T) {
|
||||
n := New("teststartstop", lookupFunc, nil)
|
||||
n.Start()
|
||||
err := n.Stop()
|
||||
if err != nil {
|
||||
t.Fatalf("Address Manager failed to stop: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddAddressByIP(t *testing.T) {
|
||||
fmtErr := fmt.Errorf("")
|
||||
addrErr := &net.AddrError{}
|
||||
var tests = []struct {
|
||||
addrIP string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
someIP + ":8333",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
someIP,
|
||||
addrErr,
|
||||
},
|
||||
{
|
||||
someIP[:12] + ":8333",
|
||||
fmtErr,
|
||||
},
|
||||
{
|
||||
someIP + ":abcd",
|
||||
fmtErr,
|
||||
},
|
||||
}
|
||||
|
||||
amgr := New("testaddressbyip", nil, nil)
|
||||
for i, test := range tests {
|
||||
err := amgr.AddAddressByIP(test.addrIP, nil)
|
||||
if test.err != nil && err == nil {
|
||||
t.Errorf("TestGood test %d failed expected an error and got none", i)
|
||||
continue
|
||||
}
|
||||
if test.err == nil && err != nil {
|
||||
t.Errorf("TestGood test %d failed expected no error and got one", i)
|
||||
continue
|
||||
}
|
||||
if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
|
||||
t.Errorf("TestGood 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 wire.NetAddress
|
||||
priority AddressPriority
|
||||
valid bool
|
||||
}{
|
||||
{
|
||||
wire.NetAddress{IP: net.ParseIP("192.168.0.100")},
|
||||
InterfacePrio,
|
||||
false,
|
||||
},
|
||||
{
|
||||
wire.NetAddress{IP: net.ParseIP("204.124.1.1")},
|
||||
InterfacePrio,
|
||||
true,
|
||||
},
|
||||
{
|
||||
wire.NetAddress{IP: net.ParseIP("204.124.1.1")},
|
||||
BoundPrio,
|
||||
true,
|
||||
},
|
||||
{
|
||||
wire.NetAddress{IP: net.ParseIP("::1")},
|
||||
InterfacePrio,
|
||||
false,
|
||||
},
|
||||
{
|
||||
wire.NetAddress{IP: net.ParseIP("fe80::1")},
|
||||
InterfacePrio,
|
||||
false,
|
||||
},
|
||||
{
|
||||
wire.NetAddress{IP: net.ParseIP("2620:100::1")},
|
||||
InterfacePrio,
|
||||
true,
|
||||
},
|
||||
}
|
||||
amgr := New("testaddlocaladdress", nil, nil)
|
||||
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) {
|
||||
n := New("testattempt", lookupFunc, nil)
|
||||
|
||||
// Add a new address and get it
|
||||
err := n.AddAddressByIP(someIP+":8333", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Adding address failed: %v", err)
|
||||
}
|
||||
ka := n.GetAddress()
|
||||
|
||||
if !ka.LastAttempt().IsZero() {
|
||||
t.Errorf("Address should not have attempts, but does")
|
||||
}
|
||||
|
||||
na := ka.NetAddress()
|
||||
n.Attempt(na)
|
||||
|
||||
if ka.LastAttempt().IsZero() {
|
||||
t.Errorf("Address should have an attempt, but does not")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnected(t *testing.T) {
|
||||
n := New("testconnected", lookupFunc, nil)
|
||||
|
||||
// Add a new address and get it
|
||||
err := n.AddAddressByIP(someIP+":8333", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Adding address failed: %v", err)
|
||||
}
|
||||
ka := n.GetAddress()
|
||||
na := ka.NetAddress()
|
||||
// make it an hour ago
|
||||
na.Timestamp = time.Unix(time.Now().Add(time.Hour*-1).Unix(), 0)
|
||||
|
||||
n.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) {
|
||||
n := New("testneedmoreaddresses", lookupFunc, nil)
|
||||
addrsToAdd := 1500
|
||||
b := n.NeedMoreAddresses()
|
||||
if !b {
|
||||
t.Errorf("Expected that we need more addresses")
|
||||
}
|
||||
addrs := make([]*wire.NetAddress, addrsToAdd)
|
||||
|
||||
var err error
|
||||
for i := 0; i < addrsToAdd; i++ {
|
||||
s := fmt.Sprintf("%d.%d.173.147:8333", i/128+60, i%128+60)
|
||||
addrs[i], err = n.DeserializeNetAddress(s)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to turn %s into an address: %v", s, err)
|
||||
}
|
||||
}
|
||||
|
||||
srcAddr := wire.NewNetAddressIPPort(net.IPv4(173, 144, 173, 111), 8333, 0)
|
||||
|
||||
n.AddAddresses(addrs, srcAddr, nil)
|
||||
numAddrs := n.TotalNumAddresses()
|
||||
if numAddrs > addrsToAdd {
|
||||
t.Errorf("Number of addresses is too many %d vs %d", numAddrs, addrsToAdd)
|
||||
}
|
||||
|
||||
b = n.NeedMoreAddresses()
|
||||
if b {
|
||||
t.Errorf("Expected that we don't need more addresses")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGood(t *testing.T) {
|
||||
n := New("testgood", lookupFunc, nil)
|
||||
addrsToAdd := 64 * 64
|
||||
addrs := make([]*wire.NetAddress, addrsToAdd)
|
||||
subnetworkCount := 32
|
||||
subnetworkIDs := make([]*subnetworkid.SubnetworkID, subnetworkCount)
|
||||
|
||||
var err error
|
||||
for i := 0; i < addrsToAdd; i++ {
|
||||
s := fmt.Sprintf("%d.173.147.%d:8333", i/64+60, i%64+60)
|
||||
addrs[i], err = n.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 := wire.NewNetAddressIPPort(net.IPv4(173, 144, 173, 111), 8333, 0)
|
||||
|
||||
n.AddAddresses(addrs, srcAddr, nil)
|
||||
for i, addr := range addrs {
|
||||
n.Good(addr, subnetworkIDs[i%subnetworkCount])
|
||||
}
|
||||
|
||||
numAddrs := n.TotalNumAddresses()
|
||||
if numAddrs >= addrsToAdd {
|
||||
t.Errorf("Number of addresses is too many: %d vs %d", numAddrs, addrsToAdd)
|
||||
}
|
||||
|
||||
numCache := len(n.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(n.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) {
|
||||
n := New("test_good_change_subnetwork_id", lookupFunc, nil)
|
||||
addr := wire.NewNetAddressIPPort(net.IPv4(173, 144, 173, 111), 8333, 0)
|
||||
addrKey := NetAddressKey(addr)
|
||||
srcAddr := wire.NewNetAddressIPPort(net.IPv4(173, 144, 173, 111), 8333, 0)
|
||||
|
||||
oldSubnetwork := subnetworkid.SubnetworkIDNative
|
||||
n.AddAddress(addr, srcAddr, oldSubnetwork)
|
||||
n.Good(addr, oldSubnetwork)
|
||||
|
||||
// make sure address was saved to addrIndex under oldSubnetwork
|
||||
ka := n.find(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 := n.addrTried[*oldSubnetwork][n.getTriedBucket(addr)]
|
||||
wasFound := false
|
||||
for e := bucket.Front(); e != nil; e = e.Next() {
|
||||
if NetAddressKey(e.Value.(*KnownAddress).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
|
||||
n.Good(addr, newSubnetwork)
|
||||
|
||||
// make sure address was updated in addrIndex under newSubnetwork
|
||||
ka = n.find(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 = n.addrTried[*oldSubnetwork][n.getTriedBucket(addr)]
|
||||
wasFound = false
|
||||
for e := bucket.Front(); e != nil; e = e.Next() {
|
||||
if NetAddressKey(e.Value.(*KnownAddress).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 = n.addrTried[*newSubnetwork][n.getTriedBucket(addr)]
|
||||
wasFound = false
|
||||
for e := bucket.Front(); e != nil; e = e.Next() {
|
||||
if NetAddressKey(e.Value.(*KnownAddress).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}
|
||||
n := New("testgetaddress", lookupFunc, localSubnetworkID)
|
||||
|
||||
// Get an address from an empty set (should error)
|
||||
if rv := n.GetAddress(); rv != nil {
|
||||
t.Errorf("GetAddress failed: got: %v want: %v\n", rv, nil)
|
||||
}
|
||||
|
||||
// Add a new address and get it
|
||||
err := n.AddAddressByIP(someIP+":8332", localSubnetworkID)
|
||||
if err != nil {
|
||||
t.Fatalf("Adding address failed: %v", err)
|
||||
}
|
||||
ka := n.GetAddress()
|
||||
if ka == nil {
|
||||
t.Fatalf("Did not get an address where there is one in the pool")
|
||||
}
|
||||
|
||||
// Checks that we don't get it if we find that it has other subnetwork ID than expected.
|
||||
actualSubnetworkID := &subnetworkid.SubnetworkID{0xfe}
|
||||
n.Good(ka.NetAddress(), actualSubnetworkID)
|
||||
ka = n.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 := n.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 = n.AddAddressByIP(someIP+":8333", localSubnetworkID)
|
||||
if err != nil {
|
||||
t.Fatalf("Adding address failed: %v", err)
|
||||
}
|
||||
ka = n.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)
|
||||
}
|
||||
|
||||
// Mark this as a good address and get it
|
||||
n.Good(ka.NetAddress(), localSubnetworkID)
|
||||
ka = n.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 = n.TotalNumAddresses()
|
||||
if numAddrs != 2 {
|
||||
t.Errorf("Wrong number of addresses: got %d, want %d", numAddrs, 1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetBestLocalAddress(t *testing.T) {
|
||||
localAddrs := []wire.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 wire.NetAddress
|
||||
want0 wire.NetAddress
|
||||
want1 wire.NetAddress
|
||||
want2 wire.NetAddress
|
||||
want3 wire.NetAddress
|
||||
}{
|
||||
{
|
||||
// Remote connection from public IPv4
|
||||
wire.NetAddress{IP: net.ParseIP("204.124.8.1")},
|
||||
wire.NetAddress{IP: net.IPv4zero},
|
||||
wire.NetAddress{IP: net.IPv4zero},
|
||||
wire.NetAddress{IP: net.ParseIP("204.124.8.100")},
|
||||
wire.NetAddress{IP: net.ParseIP("fd87:d87e:eb43:25::1")},
|
||||
},
|
||||
{
|
||||
// Remote connection from private IPv4
|
||||
wire.NetAddress{IP: net.ParseIP("172.16.0.254")},
|
||||
wire.NetAddress{IP: net.IPv4zero},
|
||||
wire.NetAddress{IP: net.IPv4zero},
|
||||
wire.NetAddress{IP: net.IPv4zero},
|
||||
wire.NetAddress{IP: net.IPv4zero},
|
||||
},
|
||||
{
|
||||
// Remote connection from public IPv6
|
||||
wire.NetAddress{IP: net.ParseIP("2602:100:abcd::102")},
|
||||
wire.NetAddress{IP: net.IPv6zero},
|
||||
wire.NetAddress{IP: net.ParseIP("2001:470::1")},
|
||||
wire.NetAddress{IP: net.ParseIP("2001:470::1")},
|
||||
wire.NetAddress{IP: net.ParseIP("2001:470::1")},
|
||||
},
|
||||
/* XXX
|
||||
{
|
||||
// Remote connection from Tor
|
||||
wire.NetAddress{IP: net.ParseIP("fd87:d87e:eb43::100")},
|
||||
wire.NetAddress{IP: net.IPv4zero},
|
||||
wire.NetAddress{IP: net.ParseIP("204.124.8.100")},
|
||||
wire.NetAddress{IP: net.ParseIP("fd87:d87e:eb43:25::1")},
|
||||
},
|
||||
*/
|
||||
}
|
||||
|
||||
amgr := New("testgetbestlocaladdress", nil, nil)
|
||||
|
||||
// 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 := wire.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 = wire.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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
17
addrmgr/cov_report.sh
Normal file
17
addrmgr/cov_report.sh
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This script uses gocov to generate a test coverage report.
|
||||
# The gocov tool my be obtained with the following command:
|
||||
# go get github.com/axw/gocov/gocov
|
||||
#
|
||||
# It will be installed to $GOPATH/bin, so ensure that location is in your $PATH.
|
||||
|
||||
# Check for gocov.
|
||||
type gocov >/dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo >&2 "This script requires the gocov tool."
|
||||
echo >&2 "You may obtain it with the following command:"
|
||||
echo >&2 "go get github.com/axw/gocov/gocov"
|
||||
exit 1
|
||||
fi
|
||||
gocov test | gocov report
|
||||
38
addrmgr/doc.go
Normal file
38
addrmgr/doc.go
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2014 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package addrmgr implements concurrency safe Bitcoin address manager.
|
||||
|
||||
Address Manager Overview
|
||||
|
||||
In order maintain the peer-to-peer Bitcoin network, there needs to be a source
|
||||
of addresses to connect to as nodes come and go. The Bitcoin protocol provides
|
||||
the getaddr and addr messages to allow peers to communicate known addresses with
|
||||
each other. However, there needs to a mechanism to store those results and
|
||||
select peers from them. It is also important to note that remote peers can't
|
||||
be trusted to send valid peers nor attempt to provide you with only peers they
|
||||
control with malicious intent.
|
||||
|
||||
With that in mind, this package provides a concurrency safe address manager for
|
||||
caching and selecting peers in a non-deterministic manner. The general idea is
|
||||
the caller adds addresses to the address manager and notifies it when addresses
|
||||
are connected, known good, and attempted. The caller also requests addresses as
|
||||
it needs them.
|
||||
|
||||
The address manager internally segregates the addresses into groups and
|
||||
non-deterministically selects groups in a cryptographically random manner. This
|
||||
reduce the chances multiple addresses from the same nets are selected which
|
||||
generally helps provide greater peer diversity, and perhaps more importantly,
|
||||
drastically reduces the chances an attacker is able to coerce your peer into
|
||||
only connecting to nodes they control.
|
||||
|
||||
The address manager also understands routability and Tor addresses and tries
|
||||
hard to only return routable addresses. In addition, it uses the information
|
||||
provided by the caller about connected, known good, and attempted addresses to
|
||||
periodically purge peers which no longer appear to be good peers as well as
|
||||
bias the selection toward known good peers. The general idea is to make a best
|
||||
effort at only providing usable addresses.
|
||||
*/
|
||||
package addrmgr
|
||||
25
addrmgr/internal_test.go
Normal file
25
addrmgr/internal_test.go
Normal file
@@ -0,0 +1,25 @@
|
||||
// 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 addrmgr
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/daglabs/btcd/wire"
|
||||
)
|
||||
|
||||
func TstKnownAddressIsBad(ka *KnownAddress) bool {
|
||||
return ka.isBad()
|
||||
}
|
||||
|
||||
func TstKnownAddressChance(ka *KnownAddress) float64 {
|
||||
return ka.chance()
|
||||
}
|
||||
|
||||
func TstNewKnownAddress(na *wire.NetAddress, attempts int,
|
||||
lastattempt, lastsuccess time.Time, tried bool, refs int) *KnownAddress {
|
||||
return &KnownAddress{na: na, attempts: attempts, lastattempt: lastattempt,
|
||||
lastsuccess: lastsuccess, tried: tried, refs: refs}
|
||||
}
|
||||
105
addrmgr/knownaddress.go
Normal file
105
addrmgr/knownaddress.go
Normal file
@@ -0,0 +1,105 @@
|
||||
// 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 addrmgr
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/daglabs/btcd/util/subnetworkid"
|
||||
|
||||
"github.com/daglabs/btcd/wire"
|
||||
)
|
||||
|
||||
// KnownAddress tracks information about a known network address that is used
|
||||
// to determine how viable an address is.
|
||||
type KnownAddress struct {
|
||||
na *wire.NetAddress
|
||||
srcAddr *wire.NetAddress
|
||||
attempts int
|
||||
lastattempt time.Time
|
||||
lastsuccess time.Time
|
||||
tried bool
|
||||
refs int // reference count of new buckets
|
||||
subnetworkID *subnetworkid.SubnetworkID
|
||||
}
|
||||
|
||||
// NetAddress returns the underlying wire.NetAddress associated with the
|
||||
// known address.
|
||||
func (ka *KnownAddress) NetAddress() *wire.NetAddress {
|
||||
return ka.na
|
||||
}
|
||||
|
||||
// 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() time.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 := time.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(time.Now().Add(-1 * time.Minute)) {
|
||||
return false
|
||||
}
|
||||
|
||||
// From the future?
|
||||
if ka.na.Timestamp.After(time.Now().Add(10 * time.Minute)) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Over a month old?
|
||||
if ka.na.Timestamp.Before(time.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(time.Now().Add(-1*minBadDays*time.Hour*24)) &&
|
||||
ka.attempts >= maxFailures {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
114
addrmgr/knownaddress_test.go
Normal file
114
addrmgr/knownaddress_test.go
Normal file
@@ -0,0 +1,114 @@
|
||||
// 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 addrmgr_test
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/daglabs/btcd/addrmgr"
|
||||
"github.com/daglabs/btcd/wire"
|
||||
)
|
||||
|
||||
func TestChance(t *testing.T) {
|
||||
now := time.Unix(time.Now().Unix(), 0)
|
||||
var tests = []struct {
|
||||
addr *addrmgr.KnownAddress
|
||||
expected float64
|
||||
}{
|
||||
{
|
||||
//Test normal case
|
||||
addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(-35 * time.Second)},
|
||||
0, time.Now().Add(-30*time.Minute), time.Now(), false, 0),
|
||||
1.0,
|
||||
}, {
|
||||
//Test case in which lastseen < 0
|
||||
addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(20 * time.Second)},
|
||||
0, time.Now().Add(-30*time.Minute), time.Now(), false, 0),
|
||||
1.0,
|
||||
}, {
|
||||
//Test case in which lastattempt < 0
|
||||
addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(-35 * time.Second)},
|
||||
0, time.Now().Add(30*time.Minute), time.Now(), false, 0),
|
||||
1.0 * .01,
|
||||
}, {
|
||||
//Test case in which lastattempt < ten minutes
|
||||
addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(-35 * time.Second)},
|
||||
0, time.Now().Add(-5*time.Minute), time.Now(), false, 0),
|
||||
1.0 * .01,
|
||||
}, {
|
||||
//Test case with several failed attempts.
|
||||
addrmgr.TstNewKnownAddress(&wire.NetAddress{Timestamp: now.Add(-35 * time.Second)},
|
||||
2, time.Now().Add(-30*time.Minute), time.Now(), false, 0),
|
||||
1 / 1.5 / 1.5,
|
||||
},
|
||||
}
|
||||
|
||||
err := .0001
|
||||
for i, test := range tests {
|
||||
chance := addrmgr.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 := time.Unix(time.Now().Unix(), 0)
|
||||
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 := time.Time{}
|
||||
|
||||
futureNa := &wire.NetAddress{Timestamp: future}
|
||||
minutesOldNa := &wire.NetAddress{Timestamp: minutesOld}
|
||||
monthOldNa := &wire.NetAddress{Timestamp: monthOld}
|
||||
currentNa := &wire.NetAddress{Timestamp: secondsOld}
|
||||
|
||||
//Test addresses that have been tried in the last minute.
|
||||
if addrmgr.TstKnownAddressIsBad(addrmgr.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 addrmgr.TstKnownAddressIsBad(addrmgr.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 addrmgr.TstKnownAddressIsBad(addrmgr.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 addrmgr.TstKnownAddressIsBad(addrmgr.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 addrmgr.TstKnownAddressIsBad(addrmgr.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 !addrmgr.TstKnownAddressIsBad(addrmgr.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 !addrmgr.TstKnownAddressIsBad(addrmgr.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 !addrmgr.TstKnownAddressIsBad(addrmgr.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 !addrmgr.TstKnownAddressIsBad(addrmgr.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 addrmgr.TstKnownAddressIsBad(addrmgr.TstNewKnownAddress(minutesOldNa, 2, minutesOld, hoursOld, true, 0)) {
|
||||
t.Errorf("test case 10: This should be a valid address.")
|
||||
}
|
||||
}
|
||||
19
addrmgr/log.go
Normal file
19
addrmgr/log.go
Normal file
@@ -0,0 +1,19 @@
|
||||
// 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 addrmgr
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btclog"
|
||||
"github.com/daglabs/btcd/logger"
|
||||
)
|
||||
|
||||
// log is a logger that is initialized with no output filters. This
|
||||
// means the package will not perform any logging by default until the caller
|
||||
// requests it.
|
||||
var log btclog.Logger
|
||||
|
||||
func init() {
|
||||
log, _ = logger.Get(logger.SubsystemTags.ADXR)
|
||||
}
|
||||
@@ -2,12 +2,14 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package addressmanager
|
||||
package addrmgr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/daglabs/btcd/config"
|
||||
"net"
|
||||
|
||||
"github.com/kaspanet/kaspad/app/appmessage"
|
||||
"github.com/daglabs/btcd/wire"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -70,6 +72,19 @@ var (
|
||||
// rfc6598Net specifies the IPv4 block as defined by RFC6598 (100.64.0.0/10)
|
||||
rfc6598Net = ipNet("100.64.0.0", 10, 32)
|
||||
|
||||
// onionCatNet defines the IPv6 address block used to support Tor.
|
||||
// bitcoind encodes a .onion address as a 16 byte number by decoding the
|
||||
// address prior to the .onion (i.e. the key hash) base32 into a ten
|
||||
// byte number. It then stores the first 6 bytes of the address as
|
||||
// 0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43.
|
||||
//
|
||||
// This is the same range used by OnionCat, which is part part of the
|
||||
// RFC4193 unique local IPv6 range.
|
||||
//
|
||||
// In summary the format is:
|
||||
// { magic 6 bytes, 10 bytes base32 decode of key hash }
|
||||
onionCatNet = ipNet("fd87:d87e:eb43::", 48, 128)
|
||||
|
||||
// zero4Net defines the IPv4 address block for address staring with 0
|
||||
// (0.0.0.0/8).
|
||||
zero4Net = ipNet("0.0.0.0", 8, 32)
|
||||
@@ -78,13 +93,6 @@ var (
|
||||
heNet = ipNet("2001:470::", 32, 128)
|
||||
)
|
||||
|
||||
const (
|
||||
// GetAddressesMax is the most addresses that we will send in response
|
||||
// to a getAddress (in practise the most addresses we will return from a
|
||||
// call to AddressCache()).
|
||||
GetAddressesMax = 2500
|
||||
)
|
||||
|
||||
// ipNet returns a net.IPNet struct given the passed IP address string, number
|
||||
// of one bits to include at the start of the mask, and the total number of bits
|
||||
// for the mask.
|
||||
@@ -93,19 +101,27 @@ func ipNet(ip string, ones, bits int) net.IPNet {
|
||||
}
|
||||
|
||||
// IsIPv4 returns whether or not the given address is an IPv4 address.
|
||||
func IsIPv4(na *appmessage.NetAddress) bool {
|
||||
func IsIPv4(na *wire.NetAddress) bool {
|
||||
return na.IP.To4() != nil
|
||||
}
|
||||
|
||||
// IsLocal returns whether or not the given address is a local address.
|
||||
func IsLocal(na *appmessage.NetAddress) bool {
|
||||
func IsLocal(na *wire.NetAddress) bool {
|
||||
return na.IP.IsLoopback() || zero4Net.Contains(na.IP)
|
||||
}
|
||||
|
||||
// IsOnionCatTor returns whether or not the passed address is in the IPv6 range
|
||||
// used by bitcoin to support Tor (fd87:d87e:eb43::/48). Note that this range
|
||||
// is the same range used by OnionCat, which is part of the RFC4193 unique local
|
||||
// IPv6 range.
|
||||
func IsOnionCatTor(na *wire.NetAddress) bool {
|
||||
return onionCatNet.Contains(na.IP)
|
||||
}
|
||||
|
||||
// IsRFC1918 returns whether or not the passed address is part of the IPv4
|
||||
// private network address space as defined by RFC1918 (10.0.0.0/8,
|
||||
// 172.16.0.0/12, or 192.168.0.0/16).
|
||||
func IsRFC1918(na *appmessage.NetAddress) bool {
|
||||
func IsRFC1918(na *wire.NetAddress) bool {
|
||||
for _, rfc := range rfc1918Nets {
|
||||
if rfc.Contains(na.IP) {
|
||||
return true
|
||||
@@ -116,56 +132,56 @@ func IsRFC1918(na *appmessage.NetAddress) bool {
|
||||
|
||||
// IsRFC2544 returns whether or not the passed address is part of the IPv4
|
||||
// address space as defined by RFC2544 (198.18.0.0/15)
|
||||
func IsRFC2544(na *appmessage.NetAddress) bool {
|
||||
func IsRFC2544(na *wire.NetAddress) bool {
|
||||
return rfc2544Net.Contains(na.IP)
|
||||
}
|
||||
|
||||
// IsRFC3849 returns whether or not the passed address is part of the IPv6
|
||||
// documentation range as defined by RFC3849 (2001:DB8::/32).
|
||||
func IsRFC3849(na *appmessage.NetAddress) bool {
|
||||
func IsRFC3849(na *wire.NetAddress) bool {
|
||||
return rfc3849Net.Contains(na.IP)
|
||||
}
|
||||
|
||||
// IsRFC3927 returns whether or not the passed address is part of the IPv4
|
||||
// autoconfiguration range as defined by RFC3927 (169.254.0.0/16).
|
||||
func IsRFC3927(na *appmessage.NetAddress) bool {
|
||||
func IsRFC3927(na *wire.NetAddress) bool {
|
||||
return rfc3927Net.Contains(na.IP)
|
||||
}
|
||||
|
||||
// IsRFC3964 returns whether or not the passed address is part of the IPv6 to
|
||||
// IPv4 encapsulation range as defined by RFC3964 (2002::/16).
|
||||
func IsRFC3964(na *appmessage.NetAddress) bool {
|
||||
func IsRFC3964(na *wire.NetAddress) bool {
|
||||
return rfc3964Net.Contains(na.IP)
|
||||
}
|
||||
|
||||
// IsRFC4193 returns whether or not the passed address is part of the IPv6
|
||||
// unique local range as defined by RFC4193 (FC00::/7).
|
||||
func IsRFC4193(na *appmessage.NetAddress) bool {
|
||||
func IsRFC4193(na *wire.NetAddress) bool {
|
||||
return rfc4193Net.Contains(na.IP)
|
||||
}
|
||||
|
||||
// IsRFC4380 returns whether or not the passed address is part of the IPv6
|
||||
// teredo tunneling over UDP range as defined by RFC4380 (2001::/32).
|
||||
func IsRFC4380(na *appmessage.NetAddress) bool {
|
||||
func IsRFC4380(na *wire.NetAddress) bool {
|
||||
return rfc4380Net.Contains(na.IP)
|
||||
}
|
||||
|
||||
// IsRFC4843 returns whether or not the passed address is part of the IPv6
|
||||
// ORCHID range as defined by RFC4843 (2001:10::/28).
|
||||
func IsRFC4843(na *appmessage.NetAddress) bool {
|
||||
func IsRFC4843(na *wire.NetAddress) bool {
|
||||
return rfc4843Net.Contains(na.IP)
|
||||
}
|
||||
|
||||
// IsRFC4862 returns whether or not the passed address is part of the IPv6
|
||||
// stateless address autoconfiguration range as defined by RFC4862 (FE80::/64).
|
||||
func IsRFC4862(na *appmessage.NetAddress) bool {
|
||||
func IsRFC4862(na *wire.NetAddress) bool {
|
||||
return rfc4862Net.Contains(na.IP)
|
||||
}
|
||||
|
||||
// IsRFC5737 returns whether or not the passed address is part of the IPv4
|
||||
// documentation address space as defined by RFC5737 (192.0.2.0/24,
|
||||
// 198.51.100.0/24, 203.0.113.0/24)
|
||||
func IsRFC5737(na *appmessage.NetAddress) bool {
|
||||
func IsRFC5737(na *wire.NetAddress) bool {
|
||||
for _, rfc := range rfc5737Net {
|
||||
if rfc.Contains(na.IP) {
|
||||
return true
|
||||
@@ -177,27 +193,27 @@ func IsRFC5737(na *appmessage.NetAddress) bool {
|
||||
|
||||
// IsRFC6052 returns whether or not the passed address is part of the IPv6
|
||||
// well-known prefix range as defined by RFC6052 (64:FF9B::/96).
|
||||
func IsRFC6052(na *appmessage.NetAddress) bool {
|
||||
func IsRFC6052(na *wire.NetAddress) bool {
|
||||
return rfc6052Net.Contains(na.IP)
|
||||
}
|
||||
|
||||
// IsRFC6145 returns whether or not the passed address is part of the IPv6 to
|
||||
// IPv4 translated address range as defined by RFC6145 (::FFFF:0:0:0/96).
|
||||
func IsRFC6145(na *appmessage.NetAddress) bool {
|
||||
func IsRFC6145(na *wire.NetAddress) bool {
|
||||
return rfc6145Net.Contains(na.IP)
|
||||
}
|
||||
|
||||
// IsRFC6598 returns whether or not the passed address is part of the IPv4
|
||||
// shared address space specified by RFC6598 (100.64.0.0/10)
|
||||
func IsRFC6598(na *appmessage.NetAddress) bool {
|
||||
func IsRFC6598(na *wire.NetAddress) bool {
|
||||
return rfc6598Net.Contains(na.IP)
|
||||
}
|
||||
|
||||
// IsValid returns whether or not the passed address is valid. The address is
|
||||
// IsValid returns whether or not the passed address is valid. The address is
|
||||
// considered invalid under the following circumstances:
|
||||
// IPv4: It is either a zero or all bits set address.
|
||||
// IPv6: It is either a zero or RFC3849 documentation address.
|
||||
func IsValid(na *appmessage.NetAddress) bool {
|
||||
func IsValid(na *wire.NetAddress) bool {
|
||||
// IsUnspecified returns if address is 0, so only all bits set, and
|
||||
// RFC3849 need to be explicitly checked.
|
||||
return na.IP != nil && !(na.IP.IsUnspecified() ||
|
||||
@@ -205,28 +221,29 @@ func IsValid(na *appmessage.NetAddress) bool {
|
||||
}
|
||||
|
||||
// IsRoutable returns whether or not the passed address is routable over
|
||||
// the public internet. This is true as long as the address is valid and is not
|
||||
// the public internet. This is true as long as the address is valid and is not
|
||||
// in any reserved ranges.
|
||||
func IsRoutable(na *appmessage.NetAddress, acceptUnroutable bool) bool {
|
||||
if acceptUnroutable {
|
||||
return !IsLocal(na)
|
||||
func IsRoutable(na *wire.NetAddress) bool {
|
||||
if config.ActiveNetParams().AcceptUnroutable {
|
||||
return true
|
||||
}
|
||||
|
||||
return IsValid(na) && !(IsRFC1918(na) || IsRFC2544(na) ||
|
||||
IsRFC3927(na) || IsRFC4862(na) || IsRFC3849(na) ||
|
||||
IsRFC4843(na) || IsRFC5737(na) || IsRFC6598(na) ||
|
||||
IsLocal(na) || (IsRFC4193(na)))
|
||||
IsLocal(na) || (IsRFC4193(na) && !IsOnionCatTor(na)))
|
||||
}
|
||||
|
||||
// GroupKey returns a string representing the network group an address is part
|
||||
// of. This is the /16 for IPv4, the /32 (/36 for he.net) for IPv6, the string
|
||||
// "local" for a local address, and the string "unroutable" for an unroutable
|
||||
// of. This is the /16 for IPv4, the /32 (/36 for he.net) for IPv6, the string
|
||||
// "local" for a local address, the string "tor:key" where key is the /4 of the
|
||||
// onion address for Tor address, and the string "unroutable" for an unroutable
|
||||
// address.
|
||||
func (am *AddressManager) GroupKey(na *appmessage.NetAddress) string {
|
||||
func GroupKey(na *wire.NetAddress) string {
|
||||
if IsLocal(na) {
|
||||
return "local"
|
||||
}
|
||||
if !IsRoutable(na, am.cfg.AcceptUnroutable) {
|
||||
if !IsRoutable(na) {
|
||||
return "unroutable"
|
||||
}
|
||||
if IsIPv4(na) {
|
||||
@@ -252,10 +269,14 @@ func (am *AddressManager) GroupKey(na *appmessage.NetAddress) string {
|
||||
}
|
||||
return ip.Mask(net.CIDRMask(16, 32)).String()
|
||||
}
|
||||
if IsOnionCatTor(na) {
|
||||
// group is keyed off the first 4 bits of the actual onion key.
|
||||
return fmt.Sprintf("tor:%d", na.IP[6]&((1<<4)-1))
|
||||
}
|
||||
|
||||
// OK, so now we know ourselves to be a IPv6 address.
|
||||
// We use /32 for everything, except for Hurricane Electric's
|
||||
// (he.net) IP range, which we use /36 for.
|
||||
// bitcoind uses /32 for everything, except for Hurricane Electric's
|
||||
// (he.net) IP range, which it uses /36 for.
|
||||
bits := 32
|
||||
if heNet.Contains(na.IP) {
|
||||
bits = 36
|
||||
@@ -2,22 +2,21 @@
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package addressmanager
|
||||
package addrmgr_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/kaspanet/kaspad/app/appmessage"
|
||||
"github.com/daglabs/btcd/addrmgr"
|
||||
"github.com/daglabs/btcd/wire"
|
||||
)
|
||||
|
||||
// TestIPTypes ensures the various functions which determine the type of an IP
|
||||
// address based on RFCs work as intended.
|
||||
func TestIPTypes(t *testing.T) {
|
||||
amgr, teardown := newAddressManagerForTest(t, "TestAddAddressByIP")
|
||||
defer teardown()
|
||||
type ipTest struct {
|
||||
in appmessage.NetAddress
|
||||
in wire.NetAddress
|
||||
rfc1918 bool
|
||||
rfc2544 bool
|
||||
rfc3849 bool
|
||||
@@ -40,7 +39,7 @@ func TestIPTypes(t *testing.T) {
|
||||
rfc4193, rfc4380, rfc4843, rfc4862, rfc5737, rfc6052, rfc6145, rfc6598,
|
||||
local, valid, routable bool) ipTest {
|
||||
nip := net.ParseIP(ip)
|
||||
na := *appmessage.NewNetAddressIPPort(nip, 16111, appmessage.SFNodeNetwork)
|
||||
na := *wire.NewNetAddressIPPort(nip, 8333, wire.SFNodeNetwork)
|
||||
test := ipTest{na, rfc1918, rfc2544, rfc3849, rfc3927, rfc3964, rfc4193, rfc4380,
|
||||
rfc4843, rfc4862, rfc5737, rfc6052, rfc6145, rfc6598, local, valid, routable}
|
||||
return test
|
||||
@@ -89,55 +88,55 @@ func TestIPTypes(t *testing.T) {
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for _, test := range tests {
|
||||
if rv := IsRFC1918(&test.in); rv != test.rfc1918 {
|
||||
if rv := addrmgr.IsRFC1918(&test.in); rv != test.rfc1918 {
|
||||
t.Errorf("IsRFC1918 %s\n got: %v want: %v", test.in.IP, rv, test.rfc1918)
|
||||
}
|
||||
|
||||
if rv := IsRFC3849(&test.in); rv != test.rfc3849 {
|
||||
if rv := addrmgr.IsRFC3849(&test.in); rv != test.rfc3849 {
|
||||
t.Errorf("IsRFC3849 %s\n got: %v want: %v", test.in.IP, rv, test.rfc3849)
|
||||
}
|
||||
|
||||
if rv := IsRFC3927(&test.in); rv != test.rfc3927 {
|
||||
if rv := addrmgr.IsRFC3927(&test.in); rv != test.rfc3927 {
|
||||
t.Errorf("IsRFC3927 %s\n got: %v want: %v", test.in.IP, rv, test.rfc3927)
|
||||
}
|
||||
|
||||
if rv := IsRFC3964(&test.in); rv != test.rfc3964 {
|
||||
if rv := addrmgr.IsRFC3964(&test.in); rv != test.rfc3964 {
|
||||
t.Errorf("IsRFC3964 %s\n got: %v want: %v", test.in.IP, rv, test.rfc3964)
|
||||
}
|
||||
|
||||
if rv := IsRFC4193(&test.in); rv != test.rfc4193 {
|
||||
if rv := addrmgr.IsRFC4193(&test.in); rv != test.rfc4193 {
|
||||
t.Errorf("IsRFC4193 %s\n got: %v want: %v", test.in.IP, rv, test.rfc4193)
|
||||
}
|
||||
|
||||
if rv := IsRFC4380(&test.in); rv != test.rfc4380 {
|
||||
if rv := addrmgr.IsRFC4380(&test.in); rv != test.rfc4380 {
|
||||
t.Errorf("IsRFC4380 %s\n got: %v want: %v", test.in.IP, rv, test.rfc4380)
|
||||
}
|
||||
|
||||
if rv := IsRFC4843(&test.in); rv != test.rfc4843 {
|
||||
if rv := addrmgr.IsRFC4843(&test.in); rv != test.rfc4843 {
|
||||
t.Errorf("IsRFC4843 %s\n got: %v want: %v", test.in.IP, rv, test.rfc4843)
|
||||
}
|
||||
|
||||
if rv := IsRFC4862(&test.in); rv != test.rfc4862 {
|
||||
if rv := addrmgr.IsRFC4862(&test.in); rv != test.rfc4862 {
|
||||
t.Errorf("IsRFC4862 %s\n got: %v want: %v", test.in.IP, rv, test.rfc4862)
|
||||
}
|
||||
|
||||
if rv := IsRFC6052(&test.in); rv != test.rfc6052 {
|
||||
if rv := addrmgr.IsRFC6052(&test.in); rv != test.rfc6052 {
|
||||
t.Errorf("isRFC6052 %s\n got: %v want: %v", test.in.IP, rv, test.rfc6052)
|
||||
}
|
||||
|
||||
if rv := IsRFC6145(&test.in); rv != test.rfc6145 {
|
||||
if rv := addrmgr.IsRFC6145(&test.in); rv != test.rfc6145 {
|
||||
t.Errorf("IsRFC1918 %s\n got: %v want: %v", test.in.IP, rv, test.rfc6145)
|
||||
}
|
||||
|
||||
if rv := IsLocal(&test.in); rv != test.local {
|
||||
if rv := addrmgr.IsLocal(&test.in); rv != test.local {
|
||||
t.Errorf("IsLocal %s\n got: %v want: %v", test.in.IP, rv, test.local)
|
||||
}
|
||||
|
||||
if rv := IsValid(&test.in); rv != test.valid {
|
||||
if rv := addrmgr.IsValid(&test.in); rv != test.valid {
|
||||
t.Errorf("IsValid %s\n got: %v want: %v", test.in.IP, rv, test.valid)
|
||||
}
|
||||
|
||||
if rv := IsRoutable(&test.in, amgr.cfg.AcceptUnroutable); rv != test.routable {
|
||||
if rv := addrmgr.IsRoutable(&test.in); rv != test.routable {
|
||||
t.Errorf("IsRoutable %s\n got: %v want: %v", test.in.IP, rv, test.routable)
|
||||
}
|
||||
}
|
||||
@@ -146,9 +145,6 @@ func TestIPTypes(t *testing.T) {
|
||||
// TestGroupKey tests the GroupKey function to ensure it properly groups various
|
||||
// IP addresses.
|
||||
func TestGroupKey(t *testing.T) {
|
||||
amgr, teardown := newAddressManagerForTest(t, "TestAddAddressByIP")
|
||||
defer teardown()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
ip string
|
||||
@@ -183,9 +179,9 @@ func TestGroupKey(t *testing.T) {
|
||||
{name: "ipv6 rfc6145 translated ipv4", ip: "::ffff:0:0c01:0203", expected: "12.1.0.0"},
|
||||
|
||||
// Tor.
|
||||
{name: "ipv6 tor onioncat", ip: "fd87:d87e:eb43:1234::5678", expected: "unroutable"},
|
||||
{name: "ipv6 tor onioncat 2", ip: "fd87:d87e:eb43:1245::6789", expected: "unroutable"},
|
||||
{name: "ipv6 tor onioncat 3", ip: "fd87:d87e:eb43:1345::6789", expected: "unroutable"},
|
||||
{name: "ipv6 tor onioncat", ip: "fd87:d87e:eb43:1234::5678", expected: "tor:2"},
|
||||
{name: "ipv6 tor onioncat 2", ip: "fd87:d87e:eb43:1245::6789", expected: "tor:2"},
|
||||
{name: "ipv6 tor onioncat 3", ip: "fd87:d87e:eb43:1345::6789", expected: "tor:3"},
|
||||
|
||||
// IPv6 normal.
|
||||
{name: "ipv6 normal", ip: "2602:100::1", expected: "2602:100::"},
|
||||
@@ -196,8 +192,8 @@ func TestGroupKey(t *testing.T) {
|
||||
|
||||
for i, test := range tests {
|
||||
nip := net.ParseIP(test.ip)
|
||||
na := *appmessage.NewNetAddressIPPort(nip, 8333, appmessage.SFNodeNetwork)
|
||||
if key := amgr.GroupKey(&na); key != test.expected {
|
||||
na := *wire.NewNetAddressIPPort(nip, 8333, wire.SFNodeNetwork)
|
||||
if key := addrmgr.GroupKey(&na); key != test.expected {
|
||||
t.Errorf("TestGroupKey #%d (%s): unexpected group key "+
|
||||
"- got '%s', want '%s'", i, test.name,
|
||||
key, test.expected)
|
||||
62
addrmgr/test_coverage.txt
Normal file
62
addrmgr/test_coverage.txt
Normal file
@@ -0,0 +1,62 @@
|
||||
|
||||
github.com/conformal/btcd/addrmgr/network.go GroupKey 100.00% (23/23)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.reset 100.00% (6/6)
|
||||
github.com/conformal/btcd/addrmgr/network.go IsRFC5737 100.00% (4/4)
|
||||
github.com/conformal/btcd/addrmgr/network.go IsRFC1918 100.00% (4/4)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go New 100.00% (3/3)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go NetAddressKey 100.00% (2/2)
|
||||
github.com/conformal/btcd/addrmgr/network.go IsRFC4862 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.numAddresses 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/log.go init 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/log.go DisableLog 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/network.go ipNet 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/network.go IsIPv4 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/network.go IsLocal 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/network.go IsOnionCatTor 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/network.go IsRFC2544 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/network.go IsRFC3849 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/network.go IsRFC3927 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/network.go IsRFC3964 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/network.go IsRFC4193 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/network.go IsRFC4380 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/network.go IsRFC4843 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/network.go IsRFC6052 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/network.go IsRFC6145 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/network.go IsRFC6598 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/network.go IsValid 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/network.go IsRoutable 100.00% (1/1)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.GetBestLocalAddress 94.74% (18/19)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.AddLocalAddress 90.91% (10/11)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go getReachabilityFrom 51.52% (17/33)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go ipString 50.00% (2/4)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.GetAddress 9.30% (4/43)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.deserializePeers 0.00% (0/50)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.Good 0.00% (0/44)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.savePeers 0.00% (0/39)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.updateAddress 0.00% (0/30)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.expireNew 0.00% (0/22)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.AddressCache 0.00% (0/16)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.HostToNetAddress 0.00% (0/15)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.getNewBucket 0.00% (0/15)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.AddAddressByIP 0.00% (0/14)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.getTriedBucket 0.00% (0/14)
|
||||
github.com/conformal/btcd/addrmgr/knownaddress.go knownAddress.chance 0.00% (0/13)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.loadPeers 0.00% (0/11)
|
||||
github.com/conformal/btcd/addrmgr/knownaddress.go knownAddress.isBad 0.00% (0/11)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.Connected 0.00% (0/10)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.addressHandler 0.00% (0/9)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.pickTried 0.00% (0/8)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.DeserializeNetAddress 0.00% (0/7)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.Stop 0.00% (0/7)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.Attempt 0.00% (0/7)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.Start 0.00% (0/6)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.AddAddresses 0.00% (0/4)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.NeedMoreAddresses 0.00% (0/3)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.NumAddresses 0.00% (0/3)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.AddAddress 0.00% (0/3)
|
||||
github.com/conformal/btcd/addrmgr/knownaddress.go knownAddress.LastAttempt 0.00% (0/1)
|
||||
github.com/conformal/btcd/addrmgr/knownaddress.go knownAddress.NetAddress 0.00% (0/1)
|
||||
github.com/conformal/btcd/addrmgr/addrmanager.go AddrManager.find 0.00% (0/1)
|
||||
github.com/conformal/btcd/addrmgr/log.go UseLogger 0.00% (0/1)
|
||||
github.com/conformal/btcd/addrmgr --------------------------------- 21.04% (113/537)
|
||||
|
||||
186
app/app.go
186
app/app.go
@@ -1,186 +0,0 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/kaspanet/kaspad/infrastructure/config"
|
||||
"github.com/kaspanet/kaspad/infrastructure/db/database"
|
||||
"github.com/kaspanet/kaspad/infrastructure/db/database/ldb"
|
||||
"github.com/kaspanet/kaspad/infrastructure/logger"
|
||||
"github.com/kaspanet/kaspad/infrastructure/os/execenv"
|
||||
"github.com/kaspanet/kaspad/infrastructure/os/limits"
|
||||
"github.com/kaspanet/kaspad/infrastructure/os/signal"
|
||||
"github.com/kaspanet/kaspad/infrastructure/os/winservice"
|
||||
"github.com/kaspanet/kaspad/util/panics"
|
||||
"github.com/kaspanet/kaspad/util/profiling"
|
||||
"github.com/kaspanet/kaspad/version"
|
||||
)
|
||||
|
||||
const leveldbCacheSizeMiB = 256
|
||||
|
||||
var desiredLimits = &limits.DesiredLimits{
|
||||
FileLimitWant: 2048,
|
||||
FileLimitMin: 1024,
|
||||
}
|
||||
|
||||
var serviceDescription = &winservice.ServiceDescription{
|
||||
Name: "kaspadsvc",
|
||||
DisplayName: "Kaspad Service",
|
||||
Description: "Downloads and stays synchronized with the Kaspa blockDAG and " +
|
||||
"provides DAG services to applications.",
|
||||
}
|
||||
|
||||
type kaspadApp struct {
|
||||
cfg *config.Config
|
||||
}
|
||||
|
||||
// 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 {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return err
|
||||
}
|
||||
defer logger.BackendLog.Close()
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
return app.main(nil)
|
||||
}
|
||||
|
||||
func (app *kaspadApp) main(startedChan chan<- struct{}) error {
|
||||
// Get a channel that will be closed when a shutdown signal has been
|
||||
// triggered either from an OS signal such as SIGINT (Ctrl+C) or from
|
||||
// another subsystem such as the RPC server.
|
||||
interrupt := signal.InterruptListener()
|
||||
defer log.Info("Shutdown complete")
|
||||
|
||||
// Show version at startup.
|
||||
log.Infof("Version %s", version.Version())
|
||||
|
||||
// Enable http profiling server if requested.
|
||||
if app.cfg.Profile != "" {
|
||||
profiling.Start(app.cfg.Profile, log)
|
||||
}
|
||||
|
||||
// Perform upgrades to kaspad as new versions require it.
|
||||
if err := doUpgrades(); err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Return now if an interrupt signal was triggered.
|
||||
if signal.InterruptRequested(interrupt) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if app.cfg.ResetDatabase {
|
||||
err := removeDatabase(app.cfg)
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
// doUpgrades performs upgrades to kaspad as new versions require it.
|
||||
// currently it's a placeholder we got from kaspad upstream, that does nothing
|
||||
func doUpgrades() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// dbPath returns the path to the block database given a database type.
|
||||
func databasePath(cfg *config.Config) string {
|
||||
return filepath.Join(cfg.DataDir, "db")
|
||||
}
|
||||
|
||||
func removeDatabase(cfg *config.Config) error {
|
||||
dbPath := databasePath(cfg)
|
||||
return os.RemoveAll(dbPath)
|
||||
}
|
||||
|
||||
func openDB(cfg *config.Config) (database.Database, error) {
|
||||
dbPath := databasePath(cfg)
|
||||
log.Infof("Loading database from '%s'", dbPath)
|
||||
return ldb.NewLevelDB(dbPath, leveldbCacheSizeMiB)
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
wire
|
||||
====
|
||||
|
||||
[](https://choosealicense.com/licenses/isc/)
|
||||
[](http://godoc.org/github.com/kaspanet/kaspad/wire)
|
||||
=======
|
||||
|
||||
Package wire implements the kaspa wire protocol.
|
||||
|
||||
## Kaspa Message Overview
|
||||
|
||||
The kaspa protocol consists of exchanging messages between peers. Each message
|
||||
is preceded by a header which identifies information about it such as which
|
||||
kaspa network it is a part of, its type, how big it is, and a checksum to
|
||||
verify validity. All encoding and decoding of message headers is handled by this
|
||||
package.
|
||||
|
||||
To accomplish this, there is a generic interface for kaspa messages named
|
||||
`Message` which allows messages of any type to be read, written, or passed
|
||||
around through channels, functions, etc. In addition, concrete implementations
|
||||
of most all kaspa messages are provided. All of the details of marshalling and
|
||||
unmarshalling to and from the wire using kaspa encoding are handled so the
|
||||
caller doesn't have to concern themselves with the specifics.
|
||||
|
||||
## Reading Messages Example
|
||||
|
||||
In order to unmarshal kaspa messages from the wire, use the `ReadMessage`
|
||||
function. It accepts any `io.Reader`, but typically this will be a `net.Conn`
|
||||
to a remote node running a kaspa peer. Example syntax is:
|
||||
|
||||
```Go
|
||||
// Use the most recent protocol version supported by the package and the
|
||||
// main kaspa network.
|
||||
pver := wire.ProtocolVersion
|
||||
kaspanet := wire.Mainnet
|
||||
|
||||
// Reads and validates the next kaspa message from conn using the
|
||||
// protocol version pver and the kaspa network kaspanet. The returns
|
||||
// are a appmessage.Message, a []byte which contains the unmarshalled
|
||||
// raw payload, and a possible error.
|
||||
msg, rawPayload, err := wire.ReadMessage(conn, pver, kaspanet)
|
||||
if err != nil {
|
||||
// Log and handle the error
|
||||
}
|
||||
```
|
||||
|
||||
See the package documentation for details on determining the message type.
|
||||
|
||||
## Writing Messages Example
|
||||
|
||||
In order to marshal kaspa messages to the wire, use the `WriteMessage`
|
||||
function. It accepts any `io.Writer`, but typically this will be a `net.Conn`
|
||||
to a remote node running a kaspa peer. Example syntax to request addresses
|
||||
from a remote peer is:
|
||||
|
||||
```Go
|
||||
// Use the most recent protocol version supported by the package and the
|
||||
// main bitcoin network.
|
||||
pver := wire.ProtocolVersion
|
||||
kaspanet := wire.Mainnet
|
||||
|
||||
// Create a new getaddr kaspa message.
|
||||
msg := wire.NewMsgGetAddr()
|
||||
|
||||
// Writes a kaspa message msg to conn using the protocol version
|
||||
// pver, and the kaspa network kaspanet. The return is a possible
|
||||
// error.
|
||||
err := wire.WriteMessage(conn, msg, pver, kaspanet)
|
||||
if err != nil {
|
||||
// Log and handle the error
|
||||
}
|
||||
```
|
||||
@@ -1,24 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
import "time"
|
||||
|
||||
type baseMessage struct {
|
||||
messageNumber uint64
|
||||
receivedAt time.Time
|
||||
}
|
||||
|
||||
func (b *baseMessage) MessageNumber() uint64 {
|
||||
return b.messageNumber
|
||||
}
|
||||
|
||||
func (b *baseMessage) SetMessageNumber(messageNumber uint64) {
|
||||
b.messageNumber = messageNumber
|
||||
}
|
||||
|
||||
func (b *baseMessage) ReceivedAt() time.Time {
|
||||
return b.receivedAt
|
||||
}
|
||||
|
||||
func (b *baseMessage) SetReceivedAt(receivedAt time.Time) {
|
||||
b.receivedAt = receivedAt
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
// 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")
|
||||
@@ -1,44 +0,0 @@
|
||||
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,133 +0,0 @@
|
||||
/*
|
||||
Package appmessage implements the kaspa appmessage protocol.
|
||||
|
||||
At a high level, this package provides support for marshalling and unmarshalling
|
||||
supported kaspa messages to and from the appmessage. This package does not deal
|
||||
with the specifics of message handling such as what to do when a message is
|
||||
received. This provides the caller with a high level of flexibility.
|
||||
|
||||
Kaspa Message Overview
|
||||
|
||||
The kaspa protocol consists of exchanging messages between peers. Each
|
||||
message is preceded by a header which identifies information about it such as
|
||||
which kaspa network it is a part of, its type, how big it is, and a checksum
|
||||
to verify validity. All encoding and decoding of message headers is handled by
|
||||
this package.
|
||||
|
||||
To accomplish this, there is a generic interface for kaspa messages named
|
||||
Message which allows messages of any type to be read, written, or passed around
|
||||
through channels, functions, etc. In addition, concrete implementations of most
|
||||
of the currently supported kaspa messages are provided. For these supported
|
||||
messages, all of the details of marshalling and unmarshalling to and from the
|
||||
appmessage using kaspa encoding are handled so the caller doesn't have to concern
|
||||
themselves with the specifics.
|
||||
|
||||
Message Interaction
|
||||
|
||||
The following provides a quick summary of how the kaspa messages are intended
|
||||
to interact with one another. As stated above, these interactions are not
|
||||
directly handled by this package.
|
||||
|
||||
The initial handshake consists of two peers sending each other a version message
|
||||
(MsgVersion) followed by responding with a verack message (MsgVerAck). Both
|
||||
peers use the information in the version message (MsgVersion) to negotiate
|
||||
things such as protocol version and supported services with each other. Once
|
||||
the initial handshake is complete, the following chart indicates message
|
||||
interactions in no particular order.
|
||||
|
||||
Peer A Sends Peer B Responds
|
||||
----------------------------------------------------------------------------
|
||||
getaddr message (MsgRequestAddresses) addr message (MsgAddresses)
|
||||
getblockinvs message (MsgGetBlockInvs) inv message (MsgInv)
|
||||
inv message (MsgInv) getdata message (MsgGetData)
|
||||
getdata message (MsgGetData) block message (MsgBlock) -or-
|
||||
tx message (MsgTx) -or-
|
||||
notfound message (MsgNotFound)
|
||||
ping message (MsgPing) pong message (MsgPong)
|
||||
|
||||
Common Parameters
|
||||
|
||||
There are several common parameters that arise when using this package to read
|
||||
and write kaspa messages. The following sections provide a quick overview of
|
||||
these parameters so the next sections can build on them.
|
||||
|
||||
Protocol Version
|
||||
|
||||
The protocol version should be negotiated with the remote peer at a higher
|
||||
level than this package via the version (MsgVersion) message exchange, however,
|
||||
this package provides the appmessage.ProtocolVersion constant which indicates the
|
||||
latest protocol version this package supports and is typically the value to use
|
||||
for all outbound connections before a potentially lower protocol version is
|
||||
negotiated.
|
||||
|
||||
Kaspa Network
|
||||
|
||||
The kaspa network is a magic number which is used to identify the start of a
|
||||
message and which kaspa network the message applies to. This package provides
|
||||
the following constants:
|
||||
|
||||
appmessage.Mainnet
|
||||
appmessage.Testnet (Test network)
|
||||
appmessage.Simnet (Simulation test network)
|
||||
appmessage.Devnet (Development network)
|
||||
|
||||
Determining Message Type
|
||||
|
||||
As discussed in the kaspa message overview section, this package reads
|
||||
and writes kaspa messages using a generic interface named Message. In
|
||||
order to determine the actual concrete type of the message, use a type
|
||||
switch or type assertion. An example of a type switch follows:
|
||||
|
||||
// Assumes msg is already a valid concrete message such as one created
|
||||
// via NewMsgVersion or read via ReadMessage.
|
||||
switch msg := msg.(type) {
|
||||
case *appmessage.MsgVersion:
|
||||
// The message is a pointer to a MsgVersion struct.
|
||||
fmt.Printf("Protocol version: %d", msg.ProtocolVersion)
|
||||
case *appmessage.MsgBlock:
|
||||
// The message is a pointer to a MsgBlock struct.
|
||||
fmt.Printf("Number of tx in block: %d", msg.Header.TxnCount)
|
||||
}
|
||||
|
||||
Reading Messages
|
||||
|
||||
In order to unmarshall kaspa messages from the appmessage, use the ReadMessage
|
||||
function. It accepts any io.Reader, but typically this will be a net.Conn to
|
||||
a remote node running a kaspa peer. Example syntax is:
|
||||
|
||||
// Reads and validates the next kaspa message from conn using the
|
||||
// protocol version pver and the kaspa network kaspaNet. The returns
|
||||
// are a appmessage.Message, a []byte which contains the unmarshalled
|
||||
// raw payload, and a possible error.
|
||||
msg, rawPayload, err := appmessage.ReadMessage(conn, pver, kaspaNet)
|
||||
if err != nil {
|
||||
// Log and handle the error
|
||||
}
|
||||
|
||||
Writing Messages
|
||||
|
||||
In order to marshall kaspa messages to the appmessage, use the WriteMessage
|
||||
function. It accepts any io.Writer, but typically this will be a net.Conn to
|
||||
a remote node running a kaspa peer. Example syntax to request addresses
|
||||
from a remote peer is:
|
||||
|
||||
// Create a new getaddr kaspa message.
|
||||
msg := appmessage.NewMsgRequestAddresses()
|
||||
|
||||
// Writes a kaspa message msg to conn using the protocol version
|
||||
// pver, and the kaspa network kaspaNet. The return is a possible
|
||||
// error.
|
||||
err := appmessage.WriteMessage(conn, msg, pver, kaspaNet)
|
||||
if err != nil {
|
||||
// Log and handle the error
|
||||
}
|
||||
|
||||
Errors
|
||||
|
||||
Errors returned by this package are either the raw errors provided by underlying
|
||||
calls to read/write from streams such as io.EOF, io.ErrUnexpectedEOF, and
|
||||
io.ErrShortWrite, or of type appmessage.MessageError. This allows the caller to
|
||||
differentiate between general IO errors and malformed messages through type
|
||||
assertions.
|
||||
*/
|
||||
package appmessage
|
||||
@@ -1,305 +0,0 @@
|
||||
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 {
|
||||
transactionID, err := transactionid.FromString(input.PreviousOutpoint.TransactionID)
|
||||
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},
|
||||
}
|
||||
}
|
||||
|
||||
subnetworkID, err := subnetworks.FromString(rpcTransaction.SubnetworkID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
payloadHash, err := externalapi.NewDomainHashFromString(rpcTransaction.PayloadHash)
|
||||
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 := transaction.SubnetworkID.String()
|
||||
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
|
||||
}
|
||||
@@ -1,263 +0,0 @@
|
||||
// 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
|
||||
CmdIBDBlockLocatorHighestHashNotFound
|
||||
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
|
||||
CmdStopNotifyingUTXOsChangedRequestMessage
|
||||
CmdStopNotifyingUTXOsChangedResponseMessage
|
||||
CmdGetUTXOsByAddressesRequestMessage
|
||||
CmdGetUTXOsByAddressesResponseMessage
|
||||
CmdGetVirtualSelectedParentBlueScoreRequestMessage
|
||||
CmdGetVirtualSelectedParentBlueScoreResponseMessage
|
||||
CmdNotifyVirtualSelectedParentBlueScoreChangedRequestMessage
|
||||
CmdNotifyVirtualSelectedParentBlueScoreChangedResponseMessage
|
||||
CmdVirtualSelectedParentBlueScoreChangedNotificationMessage
|
||||
CmdBanRequestMessage
|
||||
CmdBanResponseMessage
|
||||
CmdUnbanRequestMessage
|
||||
CmdUnbanResponseMessage
|
||||
CmdGetInfoRequestMessage
|
||||
CmdGetInfoResponseMessage
|
||||
CmdNotifyPruningPointUTXOSetOverrideRequestMessage
|
||||
CmdNotifyPruningPointUTXOSetOverrideResponseMessage
|
||||
CmdPruningPointUTXOSetOverrideNotificationMessage
|
||||
CmdStopNotifyingPruningPointUTXOSetOverrideRequestMessage
|
||||
CmdStopNotifyingPruningPointUTXOSetOverrideResponseMessage
|
||||
)
|
||||
|
||||
// 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",
|
||||
CmdIBDBlockLocatorHighestHashNotFound: "IBDBlockLocatorHighestHashNotFound",
|
||||
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",
|
||||
CmdStopNotifyingUTXOsChangedRequestMessage: "StopNotifyingUTXOsChangedRequest",
|
||||
CmdStopNotifyingUTXOsChangedResponseMessage: "StopNotifyingUTXOsChangedResponse",
|
||||
CmdGetUTXOsByAddressesRequestMessage: "GetUTXOsByAddressesRequest",
|
||||
CmdGetUTXOsByAddressesResponseMessage: "GetUTXOsByAddressesResponse",
|
||||
CmdGetVirtualSelectedParentBlueScoreRequestMessage: "GetVirtualSelectedParentBlueScoreRequest",
|
||||
CmdGetVirtualSelectedParentBlueScoreResponseMessage: "GetVirtualSelectedParentBlueScoreResponse",
|
||||
CmdNotifyVirtualSelectedParentBlueScoreChangedRequestMessage: "NotifyVirtualSelectedParentBlueScoreChangedRequest",
|
||||
CmdNotifyVirtualSelectedParentBlueScoreChangedResponseMessage: "NotifyVirtualSelectedParentBlueScoreChangedResponse",
|
||||
CmdVirtualSelectedParentBlueScoreChangedNotificationMessage: "VirtualSelectedParentBlueScoreChangedNotification",
|
||||
CmdBanRequestMessage: "BanRequest",
|
||||
CmdBanResponseMessage: "BanResponse",
|
||||
CmdUnbanRequestMessage: "UnbanRequest",
|
||||
CmdUnbanResponseMessage: "UnbanResponse",
|
||||
CmdGetInfoRequestMessage: "GetInfoRequest",
|
||||
CmdGetInfoResponseMessage: "GeInfoResponse",
|
||||
CmdNotifyPruningPointUTXOSetOverrideRequestMessage: "NotifyPruningPointUTXOSetOverrideRequest",
|
||||
CmdNotifyPruningPointUTXOSetOverrideResponseMessage: "NotifyPruningPointUTXOSetOverrideResponse",
|
||||
CmdPruningPointUTXOSetOverrideNotificationMessage: "PruningPointUTXOSetOverrideNotification",
|
||||
CmdStopNotifyingPruningPointUTXOSetOverrideRequestMessage: "StopNotifyingPruningPointUTXOSetOverrideRequest",
|
||||
CmdStopNotifyingPruningPointUTXOSetOverrideResponseMessage: "StopNotifyingPruningPointUTXOSetOverrideResponse",
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -1,30 +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 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,
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
// 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),
|
||||
}
|
||||
}
|
||||
@@ -1,240 +0,0 @@
|
||||
// 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},
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
// 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,
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
// TestBlockHeader tests the MsgBlockHeader API.
|
||||
func TestBlockHeader(t *testing.T) {
|
||||
nonce := uint64(0xba4d87a69924a93d)
|
||||
|
||||
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,31 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
)
|
||||
|
||||
// MaxBlockLocatorsPerMsg is the maximum number of block locator hashes allowed
|
||||
// per message.
|
||||
const MaxBlockLocatorsPerMsg = 500
|
||||
|
||||
// MsgBlockLocator implements the Message interface and represents a kaspa
|
||||
// locator message. It is used to find the blockLocator of a peer that is
|
||||
// syncing with you.
|
||||
type MsgBlockLocator struct {
|
||||
baseMessage
|
||||
BlockLocatorHashes []*externalapi.DomainHash
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgBlockLocator) Command() MessageCommand {
|
||||
return CmdBlockLocator
|
||||
}
|
||||
|
||||
// NewMsgBlockLocator returns a new kaspa locator message that conforms to
|
||||
// the Message interface. See MsgBlockLocator for details.
|
||||
func NewMsgBlockLocator(locatorHashes []*externalapi.DomainHash) *MsgBlockLocator {
|
||||
return &MsgBlockLocator{
|
||||
BlockLocatorHashes: locatorHashes,
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
)
|
||||
|
||||
// TestBlockLocator tests the MsgBlockLocator API.
|
||||
func TestBlockLocator(t *testing.T) {
|
||||
hashStr := "000000000002e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0"
|
||||
locatorHash, err := externalapi.NewDomainHashFromString(hashStr)
|
||||
if err != nil {
|
||||
t.Errorf("NewHashFromStr: %v", err)
|
||||
}
|
||||
|
||||
msg := NewMsgBlockLocator([]*externalapi.DomainHash{locatorHash})
|
||||
|
||||
// Ensure the command is expected value.
|
||||
wantCmd := MessageCommand(10)
|
||||
if cmd := msg.Command(); cmd != wantCmd {
|
||||
t.Errorf("NewMsgBlockLocator: wrong command - got %v want %v",
|
||||
cmd, wantCmd)
|
||||
}
|
||||
|
||||
// Ensure block locator hashes are added properly.
|
||||
if msg.BlockLocatorHashes[0] != locatorHash {
|
||||
t.Errorf("AddBlockLocatorHash: wrong block locator added - "+
|
||||
"got %v, want %v",
|
||||
spew.Sprint(msg.BlockLocatorHashes[0]),
|
||||
spew.Sprint(locatorHash))
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
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{}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
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{}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
// 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
|
||||
|
||||
// MsgIBDBlock implements the Message interface and represents a kaspa
|
||||
// ibdblock message. It is used to deliver block and transaction information in
|
||||
// response to a RequestIBDBlocks message (MsgRequestIBDBlocks).
|
||||
type MsgIBDBlock struct {
|
||||
baseMessage
|
||||
*MsgBlock
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgIBDBlock) Command() MessageCommand {
|
||||
return CmdIBDBlock
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum length the payload can be for the
|
||||
// receiver. This is part of the Message interface implementation.
|
||||
func (msg *MsgIBDBlock) MaxPayloadLength(pver uint32) uint32 {
|
||||
return MaxMessagePayload
|
||||
}
|
||||
|
||||
// NewMsgIBDBlock returns a new kaspa ibdblock message that conforms to the
|
||||
// Message interface. See MsgIBDBlock for details.
|
||||
func NewMsgIBDBlock(msgBlock *MsgBlock) *MsgIBDBlock {
|
||||
return &MsgIBDBlock{MsgBlock: msgBlock}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
// TestIBDBlock tests the MsgIBDBlock API.
|
||||
func TestIBDBlock(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(15)
|
||||
msg := NewMsgIBDBlock(NewMsgBlock(bh))
|
||||
if cmd := msg.Command(); cmd != wantCmd {
|
||||
t.Errorf("NewMsgIBDBlock: 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("NewMsgIBDBlock: 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)
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
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,16 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// MsgIBDBlockLocatorHighestHashNotFound represents a kaspa BlockLocatorHighestHashNotFound message
|
||||
type MsgIBDBlockLocatorHighestHashNotFound struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *MsgIBDBlockLocatorHighestHashNotFound) Command() MessageCommand {
|
||||
return CmdIBDBlockLocatorHighestHashNotFound
|
||||
}
|
||||
|
||||
// NewMsgIBDBlockLocatorHighestHashNotFound returns a new IBDBlockLocatorHighestHashNotFound message
|
||||
func NewMsgIBDBlockLocatorHighestHashNotFound() *MsgIBDBlockLocatorHighestHashNotFound {
|
||||
return &MsgIBDBlockLocatorHighestHashNotFound{}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
)
|
||||
|
||||
// MsgInvRelayBlock implements the Message interface and represents a kaspa
|
||||
// block inventory message. It is used to notify the network about new block
|
||||
// by sending their hash, and let the receiving node decide if it needs it.
|
||||
type MsgInvRelayBlock struct {
|
||||
baseMessage
|
||||
Hash *externalapi.DomainHash
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgInvRelayBlock) Command() MessageCommand {
|
||||
return CmdInvRelayBlock
|
||||
}
|
||||
|
||||
// NewMsgInvBlock returns a new kaspa invrelblk message that conforms to
|
||||
// the Message interface. See MsgInvRelayBlock for details.
|
||||
func NewMsgInvBlock(hash *externalapi.DomainHash) *MsgInvRelayBlock {
|
||||
return &MsgInvRelayBlock{
|
||||
Hash: hash,
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
)
|
||||
|
||||
// MaxInvPerTxInvMsg is the maximum number of hashes that can
|
||||
// be in a single CmdInvTransaction message.
|
||||
const MaxInvPerTxInvMsg = MaxInvPerMsg
|
||||
|
||||
// MsgInvTransaction implements the Message interface and represents a kaspa
|
||||
// TxInv message. It is used to notify the network about new transactions
|
||||
// by sending their ID, and let the receiving node decide if it needs it.
|
||||
type MsgInvTransaction struct {
|
||||
baseMessage
|
||||
TxIDs []*externalapi.DomainTransactionID
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgInvTransaction) Command() MessageCommand {
|
||||
return CmdInvTransaction
|
||||
}
|
||||
|
||||
// NewMsgInvTransaction returns a new kaspa TxInv message that conforms to
|
||||
// the Message interface. See MsgInvTransaction for details.
|
||||
func NewMsgInvTransaction(ids []*externalapi.DomainTransactionID) *MsgInvTransaction {
|
||||
return &MsgInvTransaction{
|
||||
TxIDs: ids,
|
||||
}
|
||||
}
|
||||
@@ -1,37 +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 appmessage
|
||||
|
||||
// MsgPing implements the Message interface and represents a kaspa ping
|
||||
// message.
|
||||
//
|
||||
// For versions BIP0031Version and earlier, it is used primarily to confirm
|
||||
// that a connection is still valid. A transmission error is typically
|
||||
// interpreted as a closed connection and that the peer should be removed.
|
||||
// For versions AFTER BIP0031Version it contains an identifier which can be
|
||||
// returned in the pong message to determine network timing.
|
||||
//
|
||||
// The payload for this message just consists of a nonce used for identifying
|
||||
// it later.
|
||||
type MsgPing struct {
|
||||
baseMessage
|
||||
// Unique value associated with message that is used to identify
|
||||
// specific ping message.
|
||||
Nonce uint64
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgPing) Command() MessageCommand {
|
||||
return CmdPing
|
||||
}
|
||||
|
||||
// NewMsgPing returns a new kaspa ping message that conforms to the Message
|
||||
// interface. See MsgPing for details.
|
||||
func NewMsgPing(nonce uint64) *MsgPing {
|
||||
return &MsgPing{
|
||||
Nonce: nonce,
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// 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 (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestPing tests the MsgPing API against the latest protocol version.
|
||||
func TestPing(t *testing.T) {
|
||||
// Ensure we get the same nonce back out.
|
||||
nonce := uint64(0x61c2c5535902862)
|
||||
msg := NewMsgPing(nonce)
|
||||
if msg.Nonce != nonce {
|
||||
t.Errorf("NewMsgPing: wrong nonce - got %v, want %v",
|
||||
msg.Nonce, nonce)
|
||||
}
|
||||
|
||||
// Ensure the command is expected value.
|
||||
wantCmd := MessageCommand(7)
|
||||
if cmd := msg.Command(); cmd != wantCmd {
|
||||
t.Errorf("NewMsgPing: wrong command - got %v want %v",
|
||||
cmd, wantCmd)
|
||||
}
|
||||
}
|
||||
@@ -1,31 +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 appmessage
|
||||
|
||||
// MsgPong implements the Message interface and represents a kaspa pong
|
||||
// message which is used primarily to confirm that a connection is still valid
|
||||
// in response to a kaspa ping message (MsgPing).
|
||||
//
|
||||
// This message was not added until protocol versions AFTER BIP0031Version.
|
||||
type MsgPong struct {
|
||||
baseMessage
|
||||
// Unique value associated with message that is used to identify
|
||||
// specific ping message.
|
||||
Nonce uint64
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgPong) Command() MessageCommand {
|
||||
return CmdPong
|
||||
}
|
||||
|
||||
// NewMsgPong returns a new kaspa pong message that conforms to the Message
|
||||
// interface. See MsgPong for details.
|
||||
func NewMsgPong(nonce uint64) *MsgPong {
|
||||
return &MsgPong{
|
||||
Nonce: nonce,
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
// 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 (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestPongLatest tests the MsgPong API against the latest protocol version.
|
||||
func TestPongLatest(t *testing.T) {
|
||||
nonce := uint64(0x1a05b581a5182c)
|
||||
msg := NewMsgPong(nonce)
|
||||
if msg.Nonce != nonce {
|
||||
t.Errorf("NewMsgPong: wrong nonce - got %v, want %v",
|
||||
msg.Nonce, nonce)
|
||||
}
|
||||
|
||||
// Ensure the command is expected value.
|
||||
wantCmd := MessageCommand(8)
|
||||
if cmd := msg.Command(); cmd != wantCmd {
|
||||
t.Errorf("NewMsgPong: wrong command - got %v want %v",
|
||||
cmd, wantCmd)
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
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
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -1,36 +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 appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
)
|
||||
|
||||
// MsgRequestAddresses implements the Message interface and represents a kaspa
|
||||
// RequestAddresses message. It is used to request a list of known active peers on the
|
||||
// network from a peer to help identify potential nodes. The list is returned
|
||||
// via one or more addr messages (MsgAddresses).
|
||||
//
|
||||
// This message has no payload.
|
||||
type MsgRequestAddresses struct {
|
||||
baseMessage
|
||||
IncludeAllSubnetworks bool
|
||||
SubnetworkID *externalapi.DomainSubnetworkID
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgRequestAddresses) Command() MessageCommand {
|
||||
return CmdRequestAddresses
|
||||
}
|
||||
|
||||
// NewMsgRequestAddresses returns a new kaspa RequestAddresses message that conforms to the
|
||||
// Message interface. See MsgRequestAddresses for details.
|
||||
func NewMsgRequestAddresses(includeAllSubnetworks bool, subnetworkID *externalapi.DomainSubnetworkID) *MsgRequestAddresses {
|
||||
return &MsgRequestAddresses{
|
||||
IncludeAllSubnetworks: includeAllSubnetworks,
|
||||
SubnetworkID: subnetworkID,
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
// 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 (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestRequestAddresses tests the MsgRequestAddresses API.
|
||||
func TestRequestAddresses(t *testing.T) {
|
||||
// Ensure the command is expected value.
|
||||
wantCmd := MessageCommand(2)
|
||||
msg := NewMsgRequestAddresses(false, nil)
|
||||
if cmd := msg.Command(); cmd != wantCmd {
|
||||
t.Errorf("NewMsgRequestAddresses: wrong command - got %v want %v",
|
||||
cmd, wantCmd)
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
)
|
||||
|
||||
// MsgRequestBlockLocator implements the Message interface and represents a kaspa
|
||||
// RequestBlockLocator message. It is used to request a block locator between low
|
||||
// and high hash.
|
||||
// The locator is returned via a locator message (MsgBlockLocator).
|
||||
type MsgRequestBlockLocator struct {
|
||||
baseMessage
|
||||
LowHash *externalapi.DomainHash
|
||||
HighHash *externalapi.DomainHash
|
||||
Limit uint32
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgRequestBlockLocator) Command() MessageCommand {
|
||||
return CmdRequestBlockLocator
|
||||
}
|
||||
|
||||
// NewMsgRequestBlockLocator returns a new RequestBlockLocator message that conforms to the
|
||||
// Message interface using the passed parameters and defaults for the remaining
|
||||
// fields.
|
||||
func NewMsgRequestBlockLocator(lowHash, highHash *externalapi.DomainHash, limit uint32) *MsgRequestBlockLocator {
|
||||
return &MsgRequestBlockLocator{
|
||||
LowHash: lowHash,
|
||||
HighHash: highHash,
|
||||
Limit: limit,
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
)
|
||||
|
||||
// TestRequestBlockLocator tests the MsgRequestBlockLocator API.
|
||||
func TestRequestBlockLocator(t *testing.T) {
|
||||
hashStr := "000000000002e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0"
|
||||
highHash, err := externalapi.NewDomainHashFromString(hashStr)
|
||||
if err != nil {
|
||||
t.Errorf("NewHashFromStr: %v", err)
|
||||
}
|
||||
|
||||
// Ensure the command is expected value.
|
||||
wantCmd := MessageCommand(9)
|
||||
msg := NewMsgRequestBlockLocator(highHash, &externalapi.DomainHash{}, 0)
|
||||
if cmd := msg.Command(); cmd != wantCmd {
|
||||
t.Errorf("NewMsgRequestBlockLocator: wrong command - got %v want %v",
|
||||
cmd, wantCmd)
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
// 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,
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
// 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 (
|
||||
"testing"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
)
|
||||
|
||||
// TestRequstIBDBlocks tests the MsgRequestHeaders API.
|
||||
func TestRequstIBDBlocks(t *testing.T) {
|
||||
hashStr := "000000000002e7ad7b9eef9479e4aabc65cb831269cc20d2632c13684406dee0"
|
||||
lowHash, err := externalapi.NewDomainHashFromString(hashStr)
|
||||
if err != nil {
|
||||
t.Errorf("NewHashFromStr: %v", err)
|
||||
}
|
||||
|
||||
hashStr = "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506"
|
||||
highHash, err := externalapi.NewDomainHashFromString(hashStr)
|
||||
if err != nil {
|
||||
t.Errorf("NewHashFromStr: %v", err)
|
||||
}
|
||||
|
||||
// Ensure we get the same data back out.
|
||||
msg := NewMsgRequstHeaders(lowHash, highHash)
|
||||
if !msg.HighHash.Equal(highHash) {
|
||||
t.Errorf("NewMsgRequstHeaders: wrong high hash - got %v, want %v",
|
||||
msg.HighHash, highHash)
|
||||
}
|
||||
|
||||
// Ensure the command is expected value.
|
||||
wantCmd := MessageCommand(4)
|
||||
if cmd := msg.Command(); cmd != wantCmd {
|
||||
t.Errorf("NewMsgRequstHeaders: wrong command - got %v want %v",
|
||||
cmd, wantCmd)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
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{}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
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{}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
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,31 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
)
|
||||
|
||||
// MaxRequestRelayBlocksHashes is the maximum number of hashes that can
|
||||
// be in a single RequestRelayBlocks message.
|
||||
const MaxRequestRelayBlocksHashes = MaxInvPerMsg
|
||||
|
||||
// MsgRequestRelayBlocks implements the Message interface and represents a kaspa
|
||||
// RequestRelayBlocks message. It is used to request blocks as part of the block
|
||||
// relay protocol.
|
||||
type MsgRequestRelayBlocks struct {
|
||||
baseMessage
|
||||
Hashes []*externalapi.DomainHash
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgRequestRelayBlocks) Command() MessageCommand {
|
||||
return CmdRequestRelayBlocks
|
||||
}
|
||||
|
||||
// NewMsgRequestRelayBlocks returns a new kaspa RequestRelayBlocks message that conforms to
|
||||
// the Message interface. See MsgRequestRelayBlocks for details.
|
||||
func NewMsgRequestRelayBlocks(hashes []*externalapi.DomainHash) *MsgRequestRelayBlocks {
|
||||
return &MsgRequestRelayBlocks{
|
||||
Hashes: hashes,
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
)
|
||||
|
||||
// MaxInvPerRequestTransactionsMsg is the maximum number of hashes that can
|
||||
// be in a single CmdInvTransaction message.
|
||||
const MaxInvPerRequestTransactionsMsg = MaxInvPerMsg
|
||||
|
||||
// MsgRequestTransactions implements the Message interface and represents a kaspa
|
||||
// RequestTransactions message. It is used to request transactions as part of the
|
||||
// transactions relay protocol.
|
||||
type MsgRequestTransactions struct {
|
||||
baseMessage
|
||||
IDs []*externalapi.DomainTransactionID
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgRequestTransactions) Command() MessageCommand {
|
||||
return CmdRequestTransactions
|
||||
}
|
||||
|
||||
// NewMsgRequestTransactions returns a new kaspa RequestTransactions message that conforms to
|
||||
// the Message interface. See MsgRequestTransactions for details.
|
||||
func NewMsgRequestTransactions(ids []*externalapi.DomainTransactionID) *MsgRequestTransactions {
|
||||
return &MsgRequestTransactions{
|
||||
IDs: ids,
|
||||
}
|
||||
}
|
||||
@@ -1,30 +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 appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
)
|
||||
|
||||
// MsgTransactionNotFound defines a kaspa TransactionNotFound message which is sent in response to
|
||||
// a RequestTransactions message if any of the requested data in not available on the peer.
|
||||
type MsgTransactionNotFound struct {
|
||||
baseMessage
|
||||
ID *externalapi.DomainTransactionID
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgTransactionNotFound) Command() MessageCommand {
|
||||
return CmdTransactionNotFound
|
||||
}
|
||||
|
||||
// NewMsgTransactionNotFound returns a new kaspa transactionsnotfound message that conforms to the
|
||||
// Message interface. See MsgTransactionNotFound for details.
|
||||
func NewMsgTransactionNotFound(id *externalapi.DomainTransactionID) *MsgTransactionNotFound {
|
||||
return &MsgTransactionNotFound{
|
||||
ID: id,
|
||||
}
|
||||
}
|
||||
@@ -1,325 +0,0 @@
|
||||
// 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)
|
||||
}
|
||||
@@ -1,261 +0,0 @@
|
||||
// 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")
|
||||
}
|
||||
}
|
||||
@@ -1,26 +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 appmessage
|
||||
|
||||
// MsgVerAck defines a kaspa verack message which is used for a peer to
|
||||
// acknowledge a version message (MsgVersion) after it has used the information
|
||||
// to negotiate parameters. It implements the Message interface.
|
||||
//
|
||||
// This message has no payload.
|
||||
type MsgVerAck struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgVerAck) Command() MessageCommand {
|
||||
return CmdVerAck
|
||||
}
|
||||
|
||||
// NewMsgVerAck returns a new kaspa verack message that conforms to the
|
||||
// Message interface.
|
||||
func NewMsgVerAck() *MsgVerAck {
|
||||
return &MsgVerAck{}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
// 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 (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestVerAck tests the MsgVerAck API.
|
||||
func TestVerAck(t *testing.T) {
|
||||
// Ensure the command is expected value.
|
||||
wantCmd := MessageCommand(1)
|
||||
msg := NewMsgVerAck()
|
||||
if cmd := msg.Command(); cmd != wantCmd {
|
||||
t.Errorf("NewMsgVerAck: wrong command - got %v want %v",
|
||||
cmd, wantCmd)
|
||||
}
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
// 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"
|
||||
"strings"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/version"
|
||||
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/id"
|
||||
"github.com/kaspanet/kaspad/util/mstime"
|
||||
)
|
||||
|
||||
// MaxUserAgentLen is the maximum allowed length for the user agent field in a
|
||||
// version message (MsgVersion).
|
||||
const MaxUserAgentLen = 256
|
||||
|
||||
// DefaultUserAgent for appmessage in the stack
|
||||
var DefaultUserAgent = fmt.Sprintf("/kaspad:%s/", version.Version())
|
||||
|
||||
// MsgVersion implements the Message interface and represents a kaspa version
|
||||
// message. It is used for a peer to advertise itself as soon as an outbound
|
||||
// connection is made. The remote peer then uses this information along with
|
||||
// its own to negotiate. The remote peer must then respond with a version
|
||||
// message of its own containing the negotiated values followed by a verack
|
||||
// message (MsgVerAck). This exchange must take place before any further
|
||||
// communication is allowed to proceed.
|
||||
type MsgVersion struct {
|
||||
baseMessage
|
||||
// Version of the protocol the node is using.
|
||||
ProtocolVersion uint32
|
||||
|
||||
// The peer's network (mainnet, testnet, etc.)
|
||||
Network string
|
||||
|
||||
// Bitfield which identifies the enabled services.
|
||||
Services ServiceFlag
|
||||
|
||||
// Time the message was generated. This is encoded as an int64 on the appmessage.
|
||||
Timestamp mstime.Time
|
||||
|
||||
// Address of the local peer.
|
||||
Address *NetAddress
|
||||
|
||||
// The peer unique ID
|
||||
ID *id.ID
|
||||
|
||||
// The user agent that generated messsage. This is a encoded as a varString
|
||||
// on the appmessage. This has a max length of MaxUserAgentLen.
|
||||
UserAgent string
|
||||
|
||||
// Don't announce transactions to peer.
|
||||
DisableRelayTx bool
|
||||
|
||||
// The subnetwork of the generator of the version message. Should be nil in full nodes
|
||||
SubnetworkID *externalapi.DomainSubnetworkID
|
||||
}
|
||||
|
||||
// HasService returns whether the specified service is supported by the peer
|
||||
// that generated the message.
|
||||
func (msg *MsgVersion) HasService(service ServiceFlag) bool {
|
||||
return msg.Services&service == service
|
||||
}
|
||||
|
||||
// AddService adds service as a supported service by the peer generating the
|
||||
// message.
|
||||
func (msg *MsgVersion) AddService(service ServiceFlag) {
|
||||
msg.Services |= service
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgVersion) Command() MessageCommand {
|
||||
return CmdVersion
|
||||
}
|
||||
|
||||
// NewMsgVersion returns a new kaspa version message that conforms to the
|
||||
// Message interface using the passed parameters and defaults for the remaining
|
||||
// fields.
|
||||
func NewMsgVersion(addr *NetAddress, id *id.ID, network string,
|
||||
subnetworkID *externalapi.DomainSubnetworkID) *MsgVersion {
|
||||
|
||||
// Limit the timestamp to one millisecond precision since the protocol
|
||||
// doesn't support better.
|
||||
return &MsgVersion{
|
||||
ProtocolVersion: ProtocolVersion,
|
||||
Network: network,
|
||||
Services: 0,
|
||||
Timestamp: mstime.Now(),
|
||||
Address: addr,
|
||||
ID: id,
|
||||
UserAgent: DefaultUserAgent,
|
||||
DisableRelayTx: false,
|
||||
SubnetworkID: subnetworkID,
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateUserAgent checks userAgent length against MaxUserAgentLen
|
||||
func ValidateUserAgent(userAgent string) error {
|
||||
if len(userAgent) > MaxUserAgentLen {
|
||||
str := fmt.Sprintf("user agent too long [len %d, max %d]",
|
||||
len(userAgent), MaxUserAgentLen)
|
||||
return messageError("MsgVersion", str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddUserAgent adds a user agent to the user agent string for the version
|
||||
// message. The version string is not defined to any strict format, although
|
||||
// it is recommended to use the form "major.minor.revision" e.g. "2.6.41".
|
||||
func (msg *MsgVersion) AddUserAgent(name string, version string,
|
||||
comments ...string) {
|
||||
|
||||
newUserAgent := fmt.Sprintf("%s:%s", name, version)
|
||||
if len(comments) != 0 {
|
||||
newUserAgent = fmt.Sprintf("%s(%s)", newUserAgent,
|
||||
strings.Join(comments, "; "))
|
||||
}
|
||||
newUserAgent = fmt.Sprintf("%s%s/", msg.UserAgent, newUserAgent)
|
||||
msg.UserAgent = newUserAgent
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
// 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 (
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/id"
|
||||
)
|
||||
|
||||
// TestVersion tests the MsgVersion API.
|
||||
func TestVersion(t *testing.T) {
|
||||
pver := ProtocolVersion
|
||||
|
||||
// Create version message data.
|
||||
tcpAddrMe := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 16111}
|
||||
me := NewNetAddress(tcpAddrMe, SFNodeNetwork)
|
||||
generatedID, err := id.GenerateID()
|
||||
if err != nil {
|
||||
t.Fatalf("id.GenerateID: %s", err)
|
||||
}
|
||||
|
||||
// Ensure we get the correct data back out.
|
||||
msg := NewMsgVersion(me, generatedID, "mainnet", nil)
|
||||
if msg.ProtocolVersion != pver {
|
||||
t.Errorf("NewMsgVersion: wrong protocol version - got %v, want %v",
|
||||
msg.ProtocolVersion, pver)
|
||||
}
|
||||
if !reflect.DeepEqual(msg.Address, me) {
|
||||
t.Errorf("NewMsgVersion: wrong me address - got %v, want %v",
|
||||
spew.Sdump(&msg.Address), spew.Sdump(me))
|
||||
}
|
||||
if msg.ID.String() != generatedID.String() {
|
||||
t.Errorf("NewMsgVersion: wrong nonce - got %s, want %s",
|
||||
msg.ID, generatedID)
|
||||
}
|
||||
if msg.UserAgent != DefaultUserAgent {
|
||||
t.Errorf("NewMsgVersion: wrong user agent - got %v, want %v",
|
||||
msg.UserAgent, DefaultUserAgent)
|
||||
}
|
||||
if msg.DisableRelayTx {
|
||||
t.Errorf("NewMsgVersion: disable relay tx is not false by "+
|
||||
"default - got %v, want %v", msg.DisableRelayTx, false)
|
||||
}
|
||||
|
||||
msg.AddUserAgent("myclient", "1.2.3", "optional", "comments")
|
||||
customUserAgent := DefaultUserAgent + "myclient:1.2.3(optional; comments)/"
|
||||
if msg.UserAgent != customUserAgent {
|
||||
t.Errorf("AddUserAgent: wrong user agent - got %s, want %s",
|
||||
msg.UserAgent, customUserAgent)
|
||||
}
|
||||
|
||||
msg.AddUserAgent("mygui", "3.4.5")
|
||||
customUserAgent += "mygui:3.4.5/"
|
||||
if msg.UserAgent != customUserAgent {
|
||||
t.Errorf("AddUserAgent: wrong user agent - got %s, want %s",
|
||||
msg.UserAgent, customUserAgent)
|
||||
}
|
||||
|
||||
// Version message should not have any services set by default.
|
||||
if msg.Services != 0 {
|
||||
t.Errorf("NewMsgVersion: wrong default services - got %v, want %v",
|
||||
msg.Services, 0)
|
||||
|
||||
}
|
||||
if msg.HasService(SFNodeNetwork) {
|
||||
t.Errorf("HasService: SFNodeNetwork service is set")
|
||||
}
|
||||
|
||||
// Ensure the command is expected value.
|
||||
wantCmd := MessageCommand(0)
|
||||
if cmd := msg.Command(); cmd != wantCmd {
|
||||
t.Errorf("NewMsgVersion: wrong command - got %v want %v",
|
||||
cmd, wantCmd)
|
||||
}
|
||||
|
||||
// Ensure adding the full service node flag works.
|
||||
msg.AddService(SFNodeNetwork)
|
||||
if msg.Services != SFNodeNetwork {
|
||||
t.Errorf("AddService: wrong services - got %v, want %v",
|
||||
msg.Services, SFNodeNetwork)
|
||||
}
|
||||
if !msg.HasService(SFNodeNetwork) {
|
||||
t.Errorf("HasService: SFNodeNetwork service not set")
|
||||
}
|
||||
}
|
||||
@@ -1,74 +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 appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/util/mstime"
|
||||
"net"
|
||||
)
|
||||
|
||||
// NetAddress defines information about a peer on the network including the time
|
||||
// it was last seen, the services it supports, its IP address, and port.
|
||||
type NetAddress struct {
|
||||
// Last time the address was seen.
|
||||
Timestamp mstime.Time
|
||||
|
||||
// Bitfield which identifies the services supported by the address.
|
||||
Services ServiceFlag
|
||||
|
||||
// IP address of the peer.
|
||||
IP net.IP
|
||||
|
||||
// Port the peer is using. This is encoded in big endian on the appmessage
|
||||
// which differs from most everything else.
|
||||
Port uint16
|
||||
}
|
||||
|
||||
// HasService returns whether the specified service is supported by the address.
|
||||
func (na *NetAddress) HasService(service ServiceFlag) bool {
|
||||
return na.Services&service == service
|
||||
}
|
||||
|
||||
// AddService adds service as a supported service by the peer generating the
|
||||
// message.
|
||||
func (na *NetAddress) AddService(service ServiceFlag) {
|
||||
na.Services |= service
|
||||
}
|
||||
|
||||
// TCPAddress converts the NetAddress to *net.TCPAddr
|
||||
func (na *NetAddress) TCPAddress() *net.TCPAddr {
|
||||
return &net.TCPAddr{
|
||||
IP: na.IP,
|
||||
Port: int(na.Port),
|
||||
}
|
||||
}
|
||||
|
||||
// NewNetAddressIPPort returns a new NetAddress using the provided IP, port, and
|
||||
// supported services with defaults for the remaining fields.
|
||||
func NewNetAddressIPPort(ip net.IP, port uint16, services ServiceFlag) *NetAddress {
|
||||
return NewNetAddressTimestamp(mstime.Now(), services, ip, port)
|
||||
}
|
||||
|
||||
// NewNetAddressTimestamp returns a new NetAddress using the provided
|
||||
// timestamp, IP, port, and supported services. The timestamp is rounded to
|
||||
// single millisecond precision.
|
||||
func NewNetAddressTimestamp(
|
||||
timestamp mstime.Time, services ServiceFlag, ip net.IP, port uint16) *NetAddress {
|
||||
// Limit the timestamp to one millisecond precision since the protocol
|
||||
// doesn't support better.
|
||||
na := NetAddress{
|
||||
Timestamp: timestamp,
|
||||
Services: services,
|
||||
IP: ip,
|
||||
Port: port,
|
||||
}
|
||||
return &na
|
||||
}
|
||||
|
||||
// NewNetAddress returns a new NetAddress using the provided TCP address and
|
||||
// supported services with defaults for the remaining fields.
|
||||
func NewNetAddress(addr *net.TCPAddr, services ServiceFlag) *NetAddress {
|
||||
return NewNetAddressIPPort(addr.IP, uint16(addr.Port), services)
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
// 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 (
|
||||
"net"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestNetAddress tests the NetAddress API.
|
||||
func TestNetAddress(t *testing.T) {
|
||||
ip := net.ParseIP("127.0.0.1")
|
||||
port := 16111
|
||||
|
||||
// Test NewNetAddress.
|
||||
na := NewNetAddress(&net.TCPAddr{IP: ip, Port: port}, 0)
|
||||
|
||||
// Ensure we get the same ip, port, and services back out.
|
||||
if !na.IP.Equal(ip) {
|
||||
t.Errorf("NetNetAddress: wrong ip - got %v, want %v", na.IP, ip)
|
||||
}
|
||||
if na.Port != uint16(port) {
|
||||
t.Errorf("NetNetAddress: wrong port - got %v, want %v", na.Port,
|
||||
port)
|
||||
}
|
||||
if na.Services != 0 {
|
||||
t.Errorf("NetNetAddress: wrong services - got %v, want %v",
|
||||
na.Services, 0)
|
||||
}
|
||||
if na.HasService(SFNodeNetwork) {
|
||||
t.Errorf("HasService: SFNodeNetwork service is set")
|
||||
}
|
||||
|
||||
// Ensure adding the full service node flag works.
|
||||
na.AddService(SFNodeNetwork)
|
||||
if na.Services != SFNodeNetwork {
|
||||
t.Errorf("AddService: wrong services - got %v, want %v",
|
||||
na.Services, SFNodeNetwork)
|
||||
}
|
||||
if !na.HasService(SFNodeNetwork) {
|
||||
t.Errorf("HasService: SFNodeNetwork service not set")
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
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{}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
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{}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
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{}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// BanRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type BanRequestMessage struct {
|
||||
baseMessage
|
||||
|
||||
IP string
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *BanRequestMessage) Command() MessageCommand {
|
||||
return CmdBanRequestMessage
|
||||
}
|
||||
|
||||
// NewBanRequestMessage returns an instance of the message
|
||||
func NewBanRequestMessage(ip string) *BanRequestMessage {
|
||||
return &BanRequestMessage{
|
||||
IP: ip,
|
||||
}
|
||||
}
|
||||
|
||||
// BanResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type BanResponseMessage struct {
|
||||
baseMessage
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *BanResponseMessage) Command() MessageCommand {
|
||||
return CmdBanResponseMessage
|
||||
}
|
||||
|
||||
// NewBanResponseMessage returns a instance of the message
|
||||
func NewBanResponseMessage() *BanResponseMessage {
|
||||
return &BanResponseMessage{}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
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
|
||||
ChildrenHashes []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
|
||||
Version uint16
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
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
|
||||
PruningPointHash string
|
||||
|
||||
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{}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// GetBlocksRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBlocksRequestMessage struct {
|
||||
baseMessage
|
||||
LowHash string
|
||||
IncludeBlockVerboseData bool
|
||||
IncludeTransactionVerboseData 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, includeBlockVerboseData bool,
|
||||
includeTransactionVerboseData bool) *GetBlocksRequestMessage {
|
||||
return &GetBlocksRequestMessage{
|
||||
LowHash: lowHash,
|
||||
IncludeBlockVerboseData: includeBlockVerboseData,
|
||||
IncludeTransactionVerboseData: includeTransactionVerboseData,
|
||||
}
|
||||
}
|
||||
|
||||
// GetBlocksResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBlocksResponseMessage struct {
|
||||
baseMessage
|
||||
BlockHashes []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,
|
||||
BlockVerboseData: blockVerboseData,
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
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
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// GetInfoRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetInfoRequestMessage struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetInfoRequestMessage) Command() MessageCommand {
|
||||
return CmdGetInfoRequestMessage
|
||||
}
|
||||
|
||||
// NewGeInfoRequestMessage returns a instance of the message
|
||||
func NewGeInfoRequestMessage() *GetInfoRequestMessage {
|
||||
return &GetInfoRequestMessage{}
|
||||
}
|
||||
|
||||
// GetInfoResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetInfoResponseMessage struct {
|
||||
baseMessage
|
||||
P2PID string
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetInfoResponseMessage) Command() MessageCommand {
|
||||
return CmdGetInfoResponseMessage
|
||||
}
|
||||
|
||||
// NewGetInfoResponseMessage returns a instance of the message
|
||||
func NewGetInfoResponseMessage(p2pID string) *GetInfoResponseMessage {
|
||||
return &GetInfoResponseMessage{
|
||||
P2PID: p2pID,
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
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,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
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
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
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
|
||||
BlockVerboseData *BlockVerboseData
|
||||
}
|
||||
|
||||
// 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, blockVerboseData *BlockVerboseData) *BlockAddedNotificationMessage {
|
||||
return &BlockAddedNotificationMessage{
|
||||
Block: block,
|
||||
BlockVerboseData: blockVerboseData,
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user