mirror of
https://github.com/kaspanet/kaspad.git
synced 2026-02-22 11:39:15 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6479820fb4 | ||
|
|
4a0b7ad268 | ||
|
|
b4a38f8f60 | ||
|
|
b794254df6 | ||
|
|
b855f57371 | ||
|
|
9b832997f8 | ||
|
|
97240a108e |
@@ -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 = 16gb ,
|
||||
[System.UInt64] $MaximumSize = 16gb ,
|
||||
[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)
|
||||
69
.github/workflows/deploy.yaml
vendored
69
.github/workflows/deploy.yaml
vendored
@@ -1,69 +0,0 @@
|
||||
name: Build and upload assets
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
name: Building, ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Fix CRLF on Windows
|
||||
if: runner.os == 'Windows'
|
||||
run: git config --global core.autocrlf false
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.21
|
||||
|
||||
- name: Build on Linux
|
||||
if: runner.os == 'Linux'
|
||||
# `-extldflags=-static` - means static link everything,
|
||||
# `-tags netgo,osusergo` means use pure go replacements for "os/user" and "net"
|
||||
# `-s -w` strips the binary to produce smaller size binaries
|
||||
run: |
|
||||
go build -v -ldflags="-s -w -extldflags=-static" -tags netgo,osusergo -o ./bin/ ./cmd/...
|
||||
archive="bin/kaspad-${{ github.event.release.tag_name }}-linux.zip"
|
||||
asset_name="kaspad-${{ github.event.release.tag_name }}-linux.zip"
|
||||
zip -r "${archive}" ./bin/*
|
||||
echo "archive=${archive}" >> $GITHUB_ENV
|
||||
echo "asset_name=${asset_name}" >> $GITHUB_ENV
|
||||
|
||||
- name: Build on Windows
|
||||
if: runner.os == 'Windows'
|
||||
shell: bash
|
||||
run: |
|
||||
go build -v -ldflags="-s -w" -o bin/ ./cmd/...
|
||||
archive="bin/kaspad-${{ github.event.release.tag_name }}-win64.zip"
|
||||
asset_name="kaspad-${{ github.event.release.tag_name }}-win64.zip"
|
||||
powershell "Compress-Archive bin/* \"${archive}\""
|
||||
echo "archive=${archive}" >> $GITHUB_ENV
|
||||
echo "asset_name=${asset_name}" >> $GITHUB_ENV
|
||||
|
||||
- name: Build on MacOS
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
go build -v -ldflags="-s -w" -o ./bin/ ./cmd/...
|
||||
archive="bin/kaspad-${{ github.event.release.tag_name }}-osx.zip"
|
||||
asset_name="kaspad-${{ github.event.release.tag_name }}-osx.zip"
|
||||
zip -r "${archive}" ./bin/*
|
||||
echo "archive=${archive}" >> $GITHUB_ENV
|
||||
echo "asset_name=${asset_name}" >> $GITHUB_ENV
|
||||
|
||||
- name: Upload release asset
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ github.event.release.upload_url }}
|
||||
asset_path: "./${{ env.archive }}"
|
||||
asset_name: "${{ env.asset_name }}"
|
||||
asset_content_type: application/zip
|
||||
49
.github/workflows/race.yaml
vendored
49
.github/workflows/race.yaml
vendored
@@ -1,49 +0,0 @@
|
||||
name: Race
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
race_test:
|
||||
runs-on: ubuntu-latest
|
||||
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@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.23
|
||||
|
||||
- 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 -timeout 20m -race ./...
|
||||
92
.github/workflows/tests.yaml
vendored
92
.github/workflows/tests.yaml
vendored
@@ -1,92 +0,0 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
# edtited - because base branch can be modified
|
||||
# synchronize - update commits on PR
|
||||
types: [opened, synchronize, edited]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
name: Tests, ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Fix CRLF on Windows
|
||||
if: runner.os == 'Windows'
|
||||
run: git config --global core.autocrlf false
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Increase the pagefile size on Windows to aviod running out of memory
|
||||
- name: Increase pagefile size on Windows
|
||||
if: runner.os == 'Windows'
|
||||
run: powershell -command .github\workflows\SetPageFileSize.ps1
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.23
|
||||
|
||||
# Source: https://github.com/actions/cache/blob/main/examples.md#go---modules
|
||||
- name: Go Cache
|
||||
uses: actions/cache@v4
|
||||
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
|
||||
|
||||
stability-test-fast:
|
||||
runs-on: ubuntu-latest
|
||||
name: Fast stability tests, ${{ github.head_ref }}
|
||||
steps:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.23
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install kaspad
|
||||
run: go install ./...
|
||||
|
||||
- name: Install golint
|
||||
run: go get -u golang.org/x/lint/golint
|
||||
|
||||
- name: Run fast stability tests
|
||||
working-directory: stability-tests
|
||||
run: ./install_and_test.sh
|
||||
|
||||
coverage:
|
||||
runs-on: ubuntu-latest
|
||||
name: Produce code coverage
|
||||
steps:
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.23
|
||||
|
||||
- name: Delete the stability tests from coverage
|
||||
run: rm -r stability-tests
|
||||
|
||||
- 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)
|
||||
19
.gitignore
vendored
19
.gitignore
vendored
@@ -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,14 +31,14 @@ _cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
|
||||
*.exe
|
||||
|
||||
# IDE
|
||||
.idea
|
||||
.vscode
|
||||
debug
|
||||
debug.test
|
||||
__debug_bin
|
||||
*__debug_*
|
||||
|
||||
# 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, testnet, 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
|
||||
testnet 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,43 +0,0 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project maintainers on this [Google form][gform]. The project maintainers will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project maintainers are obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[gform]: https://forms.gle/dnKXMJL7VxdUjt3x5
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
@@ -1,18 +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 `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.
|
||||
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"
|
||||
}
|
||||
1
LICENSE
1
LICENSE
@@ -3,7 +3,6 @@ ISC License
|
||||
Copyright (c) 2018-2019 The kaspanet developers
|
||||
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
|
||||
|
||||
50
README.md
50
README.md
@@ -1,23 +1,20 @@
|
||||
# DEPRECATED
|
||||
|
||||
The full node reference implementation was [rewritten in Rust](https://github.com/kaspanet/rusty-kaspa), as a result, the Go implementation is now deprecated.
|
||||
Kaspad
|
||||
====
|
||||
Warning: This is pre-alpha software. There's no guarantee anything works.
|
||||
====
|
||||
|
||||
PLEASE NOTE: Any pull requests or issues that will be opened in this repository will be closed without treatment, except for issues or pull requests related to the kaspawallet, which remains maintained. In any other case, please use the [Rust implementation](https://github.com/kaspanet/rusty-kaspa) instead.
|
||||
|
||||
# Kaspad
|
||||
|
||||
[](https://choosealicense.com/licenses/isc/)
|
||||
[](http://copyfree.org)
|
||||
[](http://godoc.org/github.com/kaspanet/kaspad)
|
||||
|
||||
Kaspad was the reference full node Kaspa implementation written in Go (golang).
|
||||
Kaspad is the reference full node Kaspa implementation written in Go (golang).
|
||||
|
||||
## What is kaspa
|
||||
|
||||
Kaspa is an attempt at a proof-of-work cryptocurrency with instant confirmations and sub-second block times. It is based on [the PHANTOM protocol](https://eprint.iacr.org/2018/104.pdf), a generalization of Nakamoto consensus.
|
||||
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.
|
||||
|
||||
## Requirements
|
||||
|
||||
Go 1.23 or later.
|
||||
Latest version of [Go](http://golang.org) (currently 1.13).
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -30,44 +27,53 @@ Go 1.23 or later.
|
||||
|
||||
```bash
|
||||
$ go version
|
||||
$ go env GOROOT GOPATH
|
||||
```
|
||||
|
||||
NOTE: The `GOROOT` and `GOPATH` above must not be the same path. It is
|
||||
recommended that `GOPATH` is set to a directory in your home directory such as
|
||||
`~/dev/go` to avoid write permission issues. It is also recommended to add
|
||||
`$GOPATH/bin` to your `PATH` at this point.
|
||||
|
||||
- Run the following commands to obtain and install kaspad including all dependencies:
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/kaspanet/kaspad
|
||||
$ cd kaspad
|
||||
$ git clone https://github.com/kaspanet/kaspad $GOPATH/src/github.com/kaspanet/kaspad
|
||||
$ cd $GOPATH/src/github.com/kaspanet/kaspad
|
||||
$ ./test.sh
|
||||
$ go install . ./cmd/...
|
||||
```
|
||||
`./test.sh` tests can be skipped, but some things might not run correctly on your system if tests fail.
|
||||
|
||||
- Kaspad (and utilities) should now be installed in `$(go env GOPATH)/bin`. If you did
|
||||
- Kaspad (and utilities) should now be installed in `$GOPATH/bin`. If you did
|
||||
not already add the bin directory to your system path during Go installation,
|
||||
you are encouraged to do so now.
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
Kaspad has several configuration options available to tweak how it runs, but all
|
||||
of the basic operations work with zero configuration.
|
||||
|
||||
#### Linux/BSD/POSIX/Source
|
||||
|
||||
```bash
|
||||
$ kaspad
|
||||
$ ./kaspad
|
||||
```
|
||||
|
||||
## Discord
|
||||
|
||||
Join our discord server using the following link: https://discord.gg/YNYnNN5Pf2
|
||||
Join our discord server using the following link: https://discord.gg/WmGhhzk
|
||||
|
||||
## Issue Tracker
|
||||
|
||||
The [integrated github issue tracker](https://github.com/kaspanet/kaspad/issues)
|
||||
is used for this project.
|
||||
|
||||
Issue priorities may be seen at https://github.com/orgs/kaspanet/projects/4
|
||||
|
||||
## 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/kaspanet/kaspad/tree/master/docs) folder.
|
||||
|
||||
## License
|
||||
|
||||
Kaspad is licensed under the copyfree [ISC License](https://choosealicense.com/licenses/isc/).
|
||||
Kaspad is licensed under the [copyfree](http://copyfree.org) ISC License.
|
||||
|
||||
|
||||
1404
addrmgr/addrmanager.go
Normal file
1404
addrmgr/addrmanager.go
Normal file
File diff suppressed because it is too large
Load Diff
685
addrmgr/addrmanager_test.go
Normal file
685
addrmgr/addrmanager_test.go
Normal file
@@ -0,0 +1,685 @@
|
||||
// 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 (
|
||||
"bou.ke/monkey"
|
||||
"fmt"
|
||||
"github.com/kaspanet/kaspad/config"
|
||||
"github.com/kaspanet/kaspad/dagconfig"
|
||||
"github.com/pkg/errors"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/kaspanet/kaspad/util/subnetworkid"
|
||||
|
||||
"github.com/kaspanet/kaspad/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) {
|
||||
activeConfigPatch := monkey.Patch(config.ActiveConfig, func() *config.Config {
|
||||
return &config.Config{
|
||||
Flags: &config.Flags{
|
||||
NetworkFlags: config.NetworkFlags{
|
||||
ActiveNetParams: &dagconfig.SimNetParams},
|
||||
},
|
||||
}
|
||||
})
|
||||
defer activeConfigPatch.Unpatch()
|
||||
|
||||
fmtErr := errors.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("TestAddAddressByIP test %d failed expected an error and got none", i)
|
||||
continue
|
||||
}
|
||||
if test.err == nil && err != nil {
|
||||
t.Errorf("TestAddAddressByIP test %d failed expected no error and got one", i)
|
||||
continue
|
||||
}
|
||||
if reflect.TypeOf(err) != reflect.TypeOf(test.err) {
|
||||
t.Errorf("TestAddAddressByIP test %d failed got %v, want %v", i,
|
||||
reflect.TypeOf(err), reflect.TypeOf(test.err))
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddLocalAddress(t *testing.T) {
|
||||
activeConfigPatch := monkey.Patch(config.ActiveConfig, func() *config.Config {
|
||||
return &config.Config{
|
||||
Flags: &config.Flags{
|
||||
NetworkFlags: config.NetworkFlags{
|
||||
ActiveNetParams: &dagconfig.SimNetParams},
|
||||
},
|
||||
}
|
||||
})
|
||||
defer activeConfigPatch.Unpatch()
|
||||
|
||||
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) {
|
||||
activeConfigPatch := monkey.Patch(config.ActiveConfig, func() *config.Config {
|
||||
return &config.Config{
|
||||
Flags: &config.Flags{
|
||||
NetworkFlags: config.NetworkFlags{
|
||||
ActiveNetParams: &dagconfig.SimNetParams},
|
||||
},
|
||||
}
|
||||
})
|
||||
defer activeConfigPatch.Unpatch()
|
||||
|
||||
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) {
|
||||
activeConfigPatch := monkey.Patch(config.ActiveConfig, func() *config.Config {
|
||||
return &config.Config{
|
||||
Flags: &config.Flags{
|
||||
NetworkFlags: config.NetworkFlags{
|
||||
ActiveNetParams: &dagconfig.SimNetParams},
|
||||
},
|
||||
}
|
||||
})
|
||||
defer activeConfigPatch.Unpatch()
|
||||
|
||||
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) {
|
||||
activeConfigPatch := monkey.Patch(config.ActiveConfig, func() *config.Config {
|
||||
return &config.Config{
|
||||
Flags: &config.Flags{
|
||||
NetworkFlags: config.NetworkFlags{
|
||||
ActiveNetParams: &dagconfig.SimNetParams},
|
||||
},
|
||||
}
|
||||
})
|
||||
defer activeConfigPatch.Unpatch()
|
||||
|
||||
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) {
|
||||
activeConfigPatch := monkey.Patch(config.ActiveConfig, func() *config.Config {
|
||||
return &config.Config{
|
||||
Flags: &config.Flags{
|
||||
NetworkFlags: config.NetworkFlags{
|
||||
ActiveNetParams: &dagconfig.SimNetParams},
|
||||
},
|
||||
}
|
||||
})
|
||||
defer activeConfigPatch.Unpatch()
|
||||
|
||||
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) {
|
||||
activeConfigPatch := monkey.Patch(config.ActiveConfig, func() *config.Config {
|
||||
return &config.Config{
|
||||
Flags: &config.Flags{
|
||||
NetworkFlags: config.NetworkFlags{
|
||||
ActiveNetParams: &dagconfig.SimNetParams},
|
||||
},
|
||||
}
|
||||
})
|
||||
defer activeConfigPatch.Unpatch()
|
||||
|
||||
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) {
|
||||
activeConfigPatch := monkey.Patch(config.ActiveConfig, func() *config.Config {
|
||||
return &config.Config{
|
||||
Flags: &config.Flags{
|
||||
NetworkFlags: config.NetworkFlags{
|
||||
ActiveNetParams: &dagconfig.SimNetParams},
|
||||
},
|
||||
}
|
||||
})
|
||||
defer activeConfigPatch.Unpatch()
|
||||
|
||||
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")
|
||||
}
|
||||
n.Attempt(ka.NetAddress())
|
||||
|
||||
// Checks that we don't get it if we find that it has other subnetwork ID than expected.
|
||||
actualSubnetworkID := &subnetworkid.SubnetworkID{0xfe}
|
||||
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)
|
||||
}
|
||||
n.Attempt(ka.NetAddress())
|
||||
|
||||
// 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) {
|
||||
activeConfigPatch := monkey.Patch(config.ActiveConfig, func() *config.Config {
|
||||
return &config.Config{
|
||||
Flags: &config.Flags{
|
||||
NetworkFlags: config.NetworkFlags{
|
||||
ActiveNetParams: &dagconfig.SimNetParams},
|
||||
},
|
||||
}
|
||||
})
|
||||
defer activeConfigPatch.Unpatch()
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
/*
|
||||
Package addressmanager implements concurrency safe Kaspa address manager.
|
||||
// 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.
|
||||
|
||||
# Address Manager Overview
|
||||
/*
|
||||
Package addrmgr implements concurrency safe Kaspa address manager.
|
||||
|
||||
Address Manager Overview
|
||||
|
||||
In order maintain the peer-to-peer Kaspa network, there needs to be a source
|
||||
of addresses to connect to as nodes come and go. The Kaspa protocol provides
|
||||
@@ -24,11 +28,11 @@ 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 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.
|
||||
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 addressmanager
|
||||
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/kaspanet/kaspad/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/kaspanet/kaspad/util/subnetworkid"
|
||||
|
||||
"github.com/kaspanet/kaspad/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/kaspanet/kaspad/addrmgr"
|
||||
"github.com/kaspanet/kaspad/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.")
|
||||
}
|
||||
}
|
||||
13
addrmgr/log.go
Normal file
13
addrmgr/log.go
Normal file
@@ -0,0 +1,13 @@
|
||||
// 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/kaspanet/kaspad/logger"
|
||||
"github.com/kaspanet/kaspad/util/panics"
|
||||
)
|
||||
|
||||
var log, _ = logger.Get(logger.SubsystemTags.ADXR)
|
||||
var spawn = panics.GoroutineWrapperFuncWithPanicHandler(log)
|
||||
@@ -2,12 +2,15 @@
|
||||
// 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"
|
||||
"net"
|
||||
|
||||
"github.com/kaspanet/kaspad/app/appmessage"
|
||||
"github.com/kaspanet/kaspad/config"
|
||||
|
||||
"github.com/kaspanet/kaspad/wire"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -70,6 +73,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.
|
||||
// We encode 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 +94,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 +102,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 Kaspa 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 +133,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,19 +194,19 @@ 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)
|
||||
}
|
||||
|
||||
@@ -197,7 +214,7 @@ func IsRFC6598(na *appmessage.NetAddress) bool {
|
||||
// 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() ||
|
||||
@@ -207,26 +224,27 @@ 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
|
||||
// in any reserved ranges.
|
||||
func IsRoutable(na *appmessage.NetAddress, acceptUnroutable bool) bool {
|
||||
if acceptUnroutable {
|
||||
func IsRoutable(na *wire.NetAddress) bool {
|
||||
if config.ActiveConfig().NetParams().AcceptUnroutable {
|
||||
return !IsLocal(na)
|
||||
}
|
||||
|
||||
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
|
||||
// "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,6 +270,10 @@ 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
|
||||
@@ -2,22 +2,34 @@
|
||||
// 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 (
|
||||
"bou.ke/monkey"
|
||||
"github.com/kaspanet/kaspad/config"
|
||||
"github.com/kaspanet/kaspad/dagconfig"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/kaspanet/kaspad/app/appmessage"
|
||||
"github.com/kaspanet/kaspad/addrmgr"
|
||||
"github.com/kaspanet/kaspad/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()
|
||||
activeConfigPatch := monkey.Patch(config.ActiveConfig, func() *config.Config {
|
||||
return &config.Config{
|
||||
Flags: &config.Flags{
|
||||
NetworkFlags: config.NetworkFlags{
|
||||
ActiveNetParams: &dagconfig.SimNetParams},
|
||||
},
|
||||
}
|
||||
})
|
||||
defer activeConfigPatch.Unpatch()
|
||||
|
||||
type ipTest struct {
|
||||
in appmessage.NetAddress
|
||||
in wire.NetAddress
|
||||
rfc1918 bool
|
||||
rfc2544 bool
|
||||
rfc3849 bool
|
||||
@@ -40,7 +52,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)
|
||||
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 +101,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,8 +158,15 @@ 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()
|
||||
activeConfigPatch := monkey.Patch(config.ActiveConfig, func() *config.Config {
|
||||
return &config.Config{
|
||||
Flags: &config.Flags{
|
||||
NetworkFlags: config.NetworkFlags{
|
||||
ActiveNetParams: &dagconfig.SimNetParams},
|
||||
},
|
||||
}
|
||||
})
|
||||
defer activeConfigPatch.Unpatch()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -183,9 +202,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 +215,8 @@ func TestGroupKey(t *testing.T) {
|
||||
|
||||
for i, test := range tests {
|
||||
nip := net.ParseIP(test.ip)
|
||||
na := *appmessage.NewNetAddressIPPort(nip, 8333)
|
||||
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)
|
||||
|
||||
189
app/app.go
189
app/app.go
@@ -1,189 +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
|
||||
defaultDataDirname = "datadir2"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
profiling.TrackHeap(app.cfg.AppDir, log)
|
||||
|
||||
// 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.Errorf("Loading database failed: %+v", 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
|
||||
}
|
||||
|
||||
// dbPath returns the path to the block database given a database type.
|
||||
func databasePath(cfg *config.Config) string {
|
||||
return filepath.Join(cfg.AppDir, defaultDataDirname)
|
||||
}
|
||||
|
||||
func removeDatabase(cfg *config.Config) error {
|
||||
dbPath := databasePath(cfg)
|
||||
return os.RemoveAll(dbPath)
|
||||
}
|
||||
|
||||
func openDB(cfg *config.Config) (database.Database, error) {
|
||||
dbPath := databasePath(cfg)
|
||||
|
||||
err := checkDatabaseVersion(dbPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
log.Infof("Loading database from '%s'", dbPath)
|
||||
db, err := ldb.NewLevelDB(dbPath, leveldbCacheSizeMiB)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return db, nil
|
||||
}
|
||||
@@ -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,604 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/blockheader"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/hashes"
|
||||
"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(),
|
||||
Parents: domainBlockHeader.Parents(),
|
||||
HashMerkleRoot: domainBlockHeader.HashMerkleRoot(),
|
||||
AcceptedIDMerkleRoot: domainBlockHeader.AcceptedIDMerkleRoot(),
|
||||
UTXOCommitment: domainBlockHeader.UTXOCommitment(),
|
||||
Timestamp: mstime.UnixMilliseconds(domainBlockHeader.TimeInMilliseconds()),
|
||||
Bits: domainBlockHeader.Bits(),
|
||||
Nonce: domainBlockHeader.Nonce(),
|
||||
BlueScore: domainBlockHeader.BlueScore(),
|
||||
DAAScore: domainBlockHeader.DAAScore(),
|
||||
BlueWork: domainBlockHeader.BlueWork(),
|
||||
PruningPoint: domainBlockHeader.PruningPoint(),
|
||||
}
|
||||
}
|
||||
|
||||
// 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.Parents,
|
||||
blockHeader.HashMerkleRoot,
|
||||
blockHeader.AcceptedIDMerkleRoot,
|
||||
blockHeader.UTXOCommitment,
|
||||
blockHeader.Timestamp.UnixMilliseconds(),
|
||||
blockHeader.Bits,
|
||||
blockHeader.Nonce,
|
||||
blockHeader.DAAScore,
|
||||
blockHeader.BlueScore,
|
||||
blockHeader.BlueWork,
|
||||
blockHeader.PruningPoint,
|
||||
)
|
||||
}
|
||||
|
||||
// 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,
|
||||
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,
|
||||
SigOpCount: domainTransactionInput.SigOpCount,
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
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,
|
||||
SigOpCount: txIn.SigOpCount,
|
||||
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 {
|
||||
previousOutpoint, err := RPCOutpointToDomainOutpoint(input.PreviousOutpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
signatureScript, err := hex.DecodeString(input.SignatureScript)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inputs[i] = &externalapi.DomainTransactionInput{
|
||||
PreviousOutpoint: *previousOutpoint,
|
||||
SignatureScript: signatureScript,
|
||||
Sequence: input.Sequence,
|
||||
SigOpCount: input.SigOpCount,
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
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.Gas,
|
||||
MassCommitment: rpcTransaction.Mass,
|
||||
Payload: payload,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RPCOutpointToDomainOutpoint converts RPCOutpoint to DomainOutpoint
|
||||
func RPCOutpointToDomainOutpoint(outpoint *RPCOutpoint) (*externalapi.DomainOutpoint, error) {
|
||||
transactionID, err := transactionid.FromString(outpoint.TransactionID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &externalapi.DomainOutpoint{
|
||||
TransactionID: *transactionID,
|
||||
Index: outpoint.Index,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RPCUTXOEntryToUTXOEntry converts RPCUTXOEntry to UTXOEntry
|
||||
func RPCUTXOEntryToUTXOEntry(entry *RPCUTXOEntry) (externalapi.UTXOEntry, error) {
|
||||
script, err := hex.DecodeString(entry.ScriptPublicKey.Script)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return utxo.NewUTXOEntry(
|
||||
entry.Amount,
|
||||
&externalapi.ScriptPublicKey{
|
||||
Script: script,
|
||||
Version: entry.ScriptPublicKey.Version,
|
||||
},
|
||||
entry.IsCoinbase,
|
||||
entry.BlockDAAScore,
|
||||
), 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,
|
||||
SigOpCount: input.SigOpCount,
|
||||
}
|
||||
}
|
||||
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()
|
||||
payload := hex.EncodeToString(transaction.Payload)
|
||||
return &RPCTransaction{
|
||||
Version: transaction.Version,
|
||||
Inputs: inputs,
|
||||
Outputs: outputs,
|
||||
LockTime: transaction.LockTime,
|
||||
SubnetworkID: subnetworkID,
|
||||
Gas: transaction.Gas,
|
||||
Mass: transaction.MassCommitment,
|
||||
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] = outpointAndUTXOEntryPairToDomainOutpointAndUTXOEntryPair(outpointAndUTXOEntryPair)
|
||||
}
|
||||
return domainOutpointAndUTXOEntryPairs
|
||||
}
|
||||
|
||||
func outpointAndUTXOEntryPairToDomainOutpointAndUTXOEntryPair(
|
||||
outpointAndUTXOEntryPair *OutpointAndUTXOEntryPair) *externalapi.OutpointAndUTXOEntryPair {
|
||||
return &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.BlockDAAScore,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// 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(),
|
||||
BlockDAAScore: outpointAndUTXOEntryPair.UTXOEntry.BlockDAAScore(),
|
||||
},
|
||||
}
|
||||
}
|
||||
return domainOutpointAndUTXOEntryPairs
|
||||
}
|
||||
|
||||
// DomainBlockToRPCBlock converts DomainBlocks to RPCBlocks
|
||||
func DomainBlockToRPCBlock(block *externalapi.DomainBlock) *RPCBlock {
|
||||
parents := make([]*RPCBlockLevelParents, len(block.Header.Parents()))
|
||||
for i, blockLevelParents := range block.Header.Parents() {
|
||||
parents[i] = &RPCBlockLevelParents{
|
||||
ParentHashes: hashes.ToStrings(blockLevelParents),
|
||||
}
|
||||
}
|
||||
header := &RPCBlockHeader{
|
||||
Version: uint32(block.Header.Version()),
|
||||
Parents: parents,
|
||||
HashMerkleRoot: block.Header.HashMerkleRoot().String(),
|
||||
AcceptedIDMerkleRoot: block.Header.AcceptedIDMerkleRoot().String(),
|
||||
UTXOCommitment: block.Header.UTXOCommitment().String(),
|
||||
Timestamp: block.Header.TimeInMilliseconds(),
|
||||
Bits: block.Header.Bits(),
|
||||
Nonce: block.Header.Nonce(),
|
||||
DAAScore: block.Header.DAAScore(),
|
||||
BlueScore: block.Header.BlueScore(),
|
||||
BlueWork: block.Header.BlueWork().Text(16),
|
||||
PruningPoint: block.Header.PruningPoint().String(),
|
||||
}
|
||||
transactions := make([]*RPCTransaction, len(block.Transactions))
|
||||
for i, transaction := range block.Transactions {
|
||||
transactions[i] = DomainTransactionToRPCTransaction(transaction)
|
||||
}
|
||||
return &RPCBlock{
|
||||
Header: header,
|
||||
Transactions: transactions,
|
||||
}
|
||||
}
|
||||
|
||||
// RPCBlockToDomainBlock converts `block` into a DomainBlock
|
||||
func RPCBlockToDomainBlock(block *RPCBlock) (*externalapi.DomainBlock, error) {
|
||||
parents := make([]externalapi.BlockLevelParents, len(block.Header.Parents))
|
||||
for i, blockLevelParents := range block.Header.Parents {
|
||||
parents[i] = make(externalapi.BlockLevelParents, len(blockLevelParents.ParentHashes))
|
||||
for j, parentHash := range blockLevelParents.ParentHashes {
|
||||
var err error
|
||||
parents[i][j], err = externalapi.NewDomainHashFromString(parentHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
hashMerkleRoot, err := externalapi.NewDomainHashFromString(block.Header.HashMerkleRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
acceptedIDMerkleRoot, err := externalapi.NewDomainHashFromString(block.Header.AcceptedIDMerkleRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
utxoCommitment, err := externalapi.NewDomainHashFromString(block.Header.UTXOCommitment)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blueWork, success := new(big.Int).SetString(block.Header.BlueWork, 16)
|
||||
if !success {
|
||||
return nil, errors.Errorf("failed to parse blue work: %s", block.Header.BlueWork)
|
||||
}
|
||||
pruningPoint, err := externalapi.NewDomainHashFromString(block.Header.PruningPoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
header := blockheader.NewImmutableBlockHeader(
|
||||
uint16(block.Header.Version),
|
||||
parents,
|
||||
hashMerkleRoot,
|
||||
acceptedIDMerkleRoot,
|
||||
utxoCommitment,
|
||||
block.Header.Timestamp,
|
||||
block.Header.Bits,
|
||||
block.Header.Nonce,
|
||||
block.Header.DAAScore,
|
||||
block.Header.BlueScore,
|
||||
blueWork,
|
||||
pruningPoint)
|
||||
transactions := make([]*externalapi.DomainTransaction, len(block.Transactions))
|
||||
for i, transaction := range block.Transactions {
|
||||
domainTransaction, err := RPCTransactionToDomainTransaction(transaction)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
transactions[i] = domainTransaction
|
||||
}
|
||||
return &externalapi.DomainBlock{
|
||||
Header: header,
|
||||
Transactions: transactions,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// BlockWithTrustedDataToDomainBlockWithTrustedData converts *MsgBlockWithTrustedData to *externalapi.BlockWithTrustedData
|
||||
func BlockWithTrustedDataToDomainBlockWithTrustedData(block *MsgBlockWithTrustedData) *externalapi.BlockWithTrustedData {
|
||||
daaWindow := make([]*externalapi.TrustedDataDataDAAHeader, len(block.DAAWindow))
|
||||
for i, daaBlock := range block.DAAWindow {
|
||||
daaWindow[i] = &externalapi.TrustedDataDataDAAHeader{
|
||||
Header: BlockHeaderToDomainBlockHeader(&daaBlock.Block.Header),
|
||||
GHOSTDAGData: ghostdagDataToDomainGHOSTDAGData(daaBlock.GHOSTDAGData),
|
||||
}
|
||||
}
|
||||
|
||||
ghostdagData := make([]*externalapi.BlockGHOSTDAGDataHashPair, len(block.GHOSTDAGData))
|
||||
for i, datum := range block.GHOSTDAGData {
|
||||
ghostdagData[i] = &externalapi.BlockGHOSTDAGDataHashPair{
|
||||
Hash: datum.Hash,
|
||||
GHOSTDAGData: ghostdagDataToDomainGHOSTDAGData(datum.GHOSTDAGData),
|
||||
}
|
||||
}
|
||||
|
||||
return &externalapi.BlockWithTrustedData{
|
||||
Block: MsgBlockToDomainBlock(block.Block),
|
||||
DAAWindow: daaWindow,
|
||||
GHOSTDAGData: ghostdagData,
|
||||
}
|
||||
}
|
||||
|
||||
// TrustedDataDataDAABlockV4ToTrustedDataDataDAAHeader converts *TrustedDataDAAHeader to *externalapi.TrustedDataDataDAAHeader
|
||||
func TrustedDataDataDAABlockV4ToTrustedDataDataDAAHeader(daaBlock *TrustedDataDAAHeader) *externalapi.TrustedDataDataDAAHeader {
|
||||
return &externalapi.TrustedDataDataDAAHeader{
|
||||
Header: BlockHeaderToDomainBlockHeader(daaBlock.Header),
|
||||
GHOSTDAGData: ghostdagDataToDomainGHOSTDAGData(daaBlock.GHOSTDAGData),
|
||||
}
|
||||
}
|
||||
|
||||
// GHOSTDAGHashPairToDomainGHOSTDAGHashPair converts *BlockGHOSTDAGDataHashPair to *externalapi.BlockGHOSTDAGDataHashPair
|
||||
func GHOSTDAGHashPairToDomainGHOSTDAGHashPair(datum *BlockGHOSTDAGDataHashPair) *externalapi.BlockGHOSTDAGDataHashPair {
|
||||
return &externalapi.BlockGHOSTDAGDataHashPair{
|
||||
Hash: datum.Hash,
|
||||
GHOSTDAGData: ghostdagDataToDomainGHOSTDAGData(datum.GHOSTDAGData),
|
||||
}
|
||||
}
|
||||
|
||||
func ghostdagDataToDomainGHOSTDAGData(data *BlockGHOSTDAGData) *externalapi.BlockGHOSTDAGData {
|
||||
bluesAnticoneSizes := make(map[externalapi.DomainHash]externalapi.KType, len(data.BluesAnticoneSizes))
|
||||
for _, pair := range data.BluesAnticoneSizes {
|
||||
bluesAnticoneSizes[*pair.BlueHash] = pair.AnticoneSize
|
||||
}
|
||||
return externalapi.NewBlockGHOSTDAGData(
|
||||
data.BlueScore,
|
||||
data.BlueWork,
|
||||
data.SelectedParent,
|
||||
data.MergeSetBlues,
|
||||
data.MergeSetReds,
|
||||
bluesAnticoneSizes,
|
||||
)
|
||||
}
|
||||
|
||||
func domainGHOSTDAGDataGHOSTDAGData(data *externalapi.BlockGHOSTDAGData) *BlockGHOSTDAGData {
|
||||
bluesAnticoneSizes := make([]*BluesAnticoneSizes, 0, len(data.BluesAnticoneSizes()))
|
||||
for blueHash, anticoneSize := range data.BluesAnticoneSizes() {
|
||||
blueHashCopy := blueHash
|
||||
bluesAnticoneSizes = append(bluesAnticoneSizes, &BluesAnticoneSizes{
|
||||
BlueHash: &blueHashCopy,
|
||||
AnticoneSize: anticoneSize,
|
||||
})
|
||||
}
|
||||
|
||||
return &BlockGHOSTDAGData{
|
||||
BlueScore: data.BlueScore(),
|
||||
BlueWork: data.BlueWork(),
|
||||
SelectedParent: data.SelectedParent(),
|
||||
MergeSetBlues: data.MergeSetBlues(),
|
||||
MergeSetReds: data.MergeSetReds(),
|
||||
BluesAnticoneSizes: bluesAnticoneSizes,
|
||||
}
|
||||
}
|
||||
|
||||
// DomainBlockWithTrustedDataToBlockWithTrustedData converts *externalapi.BlockWithTrustedData to *MsgBlockWithTrustedData
|
||||
func DomainBlockWithTrustedDataToBlockWithTrustedData(block *externalapi.BlockWithTrustedData) *MsgBlockWithTrustedData {
|
||||
daaWindow := make([]*TrustedDataDataDAABlock, len(block.DAAWindow))
|
||||
for i, daaBlock := range block.DAAWindow {
|
||||
daaWindow[i] = &TrustedDataDataDAABlock{
|
||||
Block: &MsgBlock{
|
||||
Header: *DomainBlockHeaderToBlockHeader(daaBlock.Header),
|
||||
},
|
||||
GHOSTDAGData: domainGHOSTDAGDataGHOSTDAGData(daaBlock.GHOSTDAGData),
|
||||
}
|
||||
}
|
||||
|
||||
ghostdagData := make([]*BlockGHOSTDAGDataHashPair, len(block.GHOSTDAGData))
|
||||
for i, datum := range block.GHOSTDAGData {
|
||||
ghostdagData[i] = &BlockGHOSTDAGDataHashPair{
|
||||
Hash: datum.Hash,
|
||||
GHOSTDAGData: domainGHOSTDAGDataGHOSTDAGData(datum.GHOSTDAGData),
|
||||
}
|
||||
}
|
||||
|
||||
return &MsgBlockWithTrustedData{
|
||||
Block: DomainBlockToMsgBlock(block.Block),
|
||||
DAAScore: block.Block.Header.DAAScore(),
|
||||
DAAWindow: daaWindow,
|
||||
GHOSTDAGData: ghostdagData,
|
||||
}
|
||||
}
|
||||
|
||||
// DomainBlockWithTrustedDataToBlockWithTrustedDataV4 converts a set of *externalapi.DomainBlock, daa window indices and ghostdag data indices
|
||||
// to *MsgBlockWithTrustedDataV4
|
||||
func DomainBlockWithTrustedDataToBlockWithTrustedDataV4(block *externalapi.DomainBlock, daaWindowIndices, ghostdagDataIndices []uint64) *MsgBlockWithTrustedDataV4 {
|
||||
return &MsgBlockWithTrustedDataV4{
|
||||
Block: DomainBlockToMsgBlock(block),
|
||||
DAAWindowIndices: daaWindowIndices,
|
||||
GHOSTDAGDataIndices: ghostdagDataIndices,
|
||||
}
|
||||
}
|
||||
|
||||
// DomainTrustedDataToTrustedData converts *externalapi.BlockWithTrustedData to *MsgBlockWithTrustedData
|
||||
func DomainTrustedDataToTrustedData(domainDAAWindow []*externalapi.TrustedDataDataDAAHeader, domainGHOSTDAGData []*externalapi.BlockGHOSTDAGDataHashPair) *MsgTrustedData {
|
||||
daaWindow := make([]*TrustedDataDAAHeader, len(domainDAAWindow))
|
||||
for i, daaBlock := range domainDAAWindow {
|
||||
daaWindow[i] = &TrustedDataDAAHeader{
|
||||
Header: DomainBlockHeaderToBlockHeader(daaBlock.Header),
|
||||
GHOSTDAGData: domainGHOSTDAGDataGHOSTDAGData(daaBlock.GHOSTDAGData),
|
||||
}
|
||||
}
|
||||
|
||||
ghostdagData := make([]*BlockGHOSTDAGDataHashPair, len(domainGHOSTDAGData))
|
||||
for i, datum := range domainGHOSTDAGData {
|
||||
ghostdagData[i] = &BlockGHOSTDAGDataHashPair{
|
||||
Hash: datum.Hash,
|
||||
GHOSTDAGData: domainGHOSTDAGDataGHOSTDAGData(datum.GHOSTDAGData),
|
||||
}
|
||||
}
|
||||
|
||||
return &MsgTrustedData{
|
||||
DAAWindow: daaWindow,
|
||||
GHOSTDAGData: ghostdagData,
|
||||
}
|
||||
}
|
||||
|
||||
// MsgPruningPointProofToDomainPruningPointProof converts *MsgPruningPointProof to *externalapi.PruningPointProof
|
||||
func MsgPruningPointProofToDomainPruningPointProof(pruningPointProofMessage *MsgPruningPointProof) *externalapi.PruningPointProof {
|
||||
headers := make([][]externalapi.BlockHeader, len(pruningPointProofMessage.Headers))
|
||||
for blockLevel, blockLevelParents := range pruningPointProofMessage.Headers {
|
||||
headers[blockLevel] = make([]externalapi.BlockHeader, len(blockLevelParents))
|
||||
for i, header := range blockLevelParents {
|
||||
headers[blockLevel][i] = BlockHeaderToDomainBlockHeader(header)
|
||||
}
|
||||
}
|
||||
return &externalapi.PruningPointProof{
|
||||
Headers: headers,
|
||||
}
|
||||
}
|
||||
|
||||
// DomainPruningPointProofToMsgPruningPointProof converts *externalapi.PruningPointProof to *MsgPruningPointProof
|
||||
func DomainPruningPointProofToMsgPruningPointProof(pruningPointProof *externalapi.PruningPointProof) *MsgPruningPointProof {
|
||||
headers := make([][]*MsgBlockHeader, len(pruningPointProof.Headers))
|
||||
for blockLevel, blockLevelParents := range pruningPointProof.Headers {
|
||||
headers[blockLevel] = make([]*MsgBlockHeader, len(blockLevelParents))
|
||||
for i, header := range blockLevelParents {
|
||||
headers[blockLevel][i] = DomainBlockHeaderToBlockHeader(header)
|
||||
}
|
||||
}
|
||||
return &MsgPruningPointProof{
|
||||
Headers: headers,
|
||||
}
|
||||
}
|
||||
@@ -1,323 +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
|
||||
CmdDoneHeaders
|
||||
CmdTransactionNotFound
|
||||
CmdReject
|
||||
CmdRequestNextHeaders
|
||||
CmdRequestPruningPointUTXOSet
|
||||
CmdPruningPointUTXOSetChunk
|
||||
CmdUnexpectedPruningPoint
|
||||
CmdIBDBlockLocator
|
||||
CmdIBDBlockLocatorHighestHash
|
||||
CmdIBDBlockLocatorHighestHashNotFound
|
||||
CmdBlockHeaders
|
||||
CmdRequestNextPruningPointUTXOSetChunk
|
||||
CmdDonePruningPointUTXOSetChunks
|
||||
CmdBlockWithTrustedData
|
||||
CmdDoneBlocksWithTrustedData
|
||||
CmdRequestPruningPointAndItsAnticone
|
||||
CmdIBDBlock
|
||||
CmdRequestIBDBlocks
|
||||
CmdPruningPoints
|
||||
CmdRequestPruningPointProof
|
||||
CmdPruningPointProof
|
||||
CmdReady
|
||||
CmdTrustedData
|
||||
CmdBlockWithTrustedDataV4
|
||||
CmdRequestNextPruningPointAndItsAnticoneBlocks
|
||||
CmdRequestIBDChainBlockLocator
|
||||
CmdIBDChainBlockLocator
|
||||
CmdRequestAnticone
|
||||
|
||||
// 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
|
||||
CmdGetBalanceByAddressRequestMessage
|
||||
CmdGetBalanceByAddressResponseMessage
|
||||
CmdGetVirtualSelectedParentBlueScoreRequestMessage
|
||||
CmdGetVirtualSelectedParentBlueScoreResponseMessage
|
||||
CmdNotifyVirtualSelectedParentBlueScoreChangedRequestMessage
|
||||
CmdNotifyVirtualSelectedParentBlueScoreChangedResponseMessage
|
||||
CmdVirtualSelectedParentBlueScoreChangedNotificationMessage
|
||||
CmdBanRequestMessage
|
||||
CmdBanResponseMessage
|
||||
CmdUnbanRequestMessage
|
||||
CmdUnbanResponseMessage
|
||||
CmdGetInfoRequestMessage
|
||||
CmdGetInfoResponseMessage
|
||||
CmdNotifyPruningPointUTXOSetOverrideRequestMessage
|
||||
CmdNotifyPruningPointUTXOSetOverrideResponseMessage
|
||||
CmdPruningPointUTXOSetOverrideNotificationMessage
|
||||
CmdStopNotifyingPruningPointUTXOSetOverrideRequestMessage
|
||||
CmdStopNotifyingPruningPointUTXOSetOverrideResponseMessage
|
||||
CmdEstimateNetworkHashesPerSecondRequestMessage
|
||||
CmdEstimateNetworkHashesPerSecondResponseMessage
|
||||
CmdNotifyVirtualDaaScoreChangedRequestMessage
|
||||
CmdNotifyVirtualDaaScoreChangedResponseMessage
|
||||
CmdVirtualDaaScoreChangedNotificationMessage
|
||||
CmdGetBalancesByAddressesRequestMessage
|
||||
CmdGetBalancesByAddressesResponseMessage
|
||||
CmdNotifyNewBlockTemplateRequestMessage
|
||||
CmdNotifyNewBlockTemplateResponseMessage
|
||||
CmdNewBlockTemplateNotificationMessage
|
||||
CmdGetMempoolEntriesByAddressesRequestMessage
|
||||
CmdGetMempoolEntriesByAddressesResponseMessage
|
||||
CmdGetCoinSupplyRequestMessage
|
||||
CmdGetCoinSupplyResponseMessage
|
||||
CmdGetFeeEstimateRequestMessage
|
||||
CmdGetFeeEstimateResponseMessage
|
||||
CmdSubmitTransactionReplacementRequestMessage
|
||||
CmdSubmitTransactionReplacementResponseMessage
|
||||
)
|
||||
|
||||
// ProtocolMessageCommandToString maps all MessageCommands to their string representation
|
||||
var ProtocolMessageCommandToString = map[MessageCommand]string{
|
||||
CmdVersion: "Version",
|
||||
CmdVerAck: "VerAck",
|
||||
CmdRequestAddresses: "RequestAddresses",
|
||||
CmdAddresses: "Addresses",
|
||||
CmdRequestHeaders: "CmdRequestHeaders",
|
||||
CmdBlock: "Block",
|
||||
CmdTx: "Tx",
|
||||
CmdPing: "Ping",
|
||||
CmdPong: "Pong",
|
||||
CmdRequestBlockLocator: "RequestBlockLocator",
|
||||
CmdBlockLocator: "BlockLocator",
|
||||
CmdInvRelayBlock: "InvRelayBlock",
|
||||
CmdRequestRelayBlocks: "RequestRelayBlocks",
|
||||
CmdInvTransaction: "InvTransaction",
|
||||
CmdRequestTransactions: "RequestTransactions",
|
||||
CmdDoneHeaders: "DoneHeaders",
|
||||
CmdTransactionNotFound: "TransactionNotFound",
|
||||
CmdReject: "Reject",
|
||||
CmdRequestNextHeaders: "RequestNextHeaders",
|
||||
CmdRequestPruningPointUTXOSet: "RequestPruningPointUTXOSet",
|
||||
CmdPruningPointUTXOSetChunk: "PruningPointUTXOSetChunk",
|
||||
CmdUnexpectedPruningPoint: "UnexpectedPruningPoint",
|
||||
CmdIBDBlockLocator: "IBDBlockLocator",
|
||||
CmdIBDBlockLocatorHighestHash: "IBDBlockLocatorHighestHash",
|
||||
CmdIBDBlockLocatorHighestHashNotFound: "IBDBlockLocatorHighestHashNotFound",
|
||||
CmdBlockHeaders: "BlockHeaders",
|
||||
CmdRequestNextPruningPointUTXOSetChunk: "RequestNextPruningPointUTXOSetChunk",
|
||||
CmdDonePruningPointUTXOSetChunks: "DonePruningPointUTXOSetChunks",
|
||||
CmdBlockWithTrustedData: "BlockWithTrustedData",
|
||||
CmdDoneBlocksWithTrustedData: "DoneBlocksWithTrustedData",
|
||||
CmdRequestPruningPointAndItsAnticone: "RequestPruningPointAndItsAnticoneHeaders",
|
||||
CmdIBDBlock: "IBDBlock",
|
||||
CmdRequestIBDBlocks: "RequestIBDBlocks",
|
||||
CmdPruningPoints: "PruningPoints",
|
||||
CmdRequestPruningPointProof: "RequestPruningPointProof",
|
||||
CmdPruningPointProof: "PruningPointProof",
|
||||
CmdReady: "Ready",
|
||||
CmdTrustedData: "TrustedData",
|
||||
CmdBlockWithTrustedDataV4: "BlockWithTrustedDataV4",
|
||||
CmdRequestNextPruningPointAndItsAnticoneBlocks: "RequestNextPruningPointAndItsAnticoneBlocks",
|
||||
CmdRequestIBDChainBlockLocator: "RequestIBDChainBlockLocator",
|
||||
CmdIBDChainBlockLocator: "IBDChainBlockLocator",
|
||||
CmdRequestAnticone: "RequestAnticone",
|
||||
}
|
||||
|
||||
// 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",
|
||||
CmdGetBalanceByAddressRequestMessage: "GetBalanceByAddressRequest",
|
||||
CmdGetBalanceByAddressResponseMessage: "GetBalancesByAddressResponse",
|
||||
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",
|
||||
CmdEstimateNetworkHashesPerSecondRequestMessage: "EstimateNetworkHashesPerSecondRequest",
|
||||
CmdEstimateNetworkHashesPerSecondResponseMessage: "EstimateNetworkHashesPerSecondResponse",
|
||||
CmdNotifyVirtualDaaScoreChangedRequestMessage: "NotifyVirtualDaaScoreChangedRequest",
|
||||
CmdNotifyVirtualDaaScoreChangedResponseMessage: "NotifyVirtualDaaScoreChangedResponse",
|
||||
CmdVirtualDaaScoreChangedNotificationMessage: "VirtualDaaScoreChangedNotification",
|
||||
CmdGetBalancesByAddressesRequestMessage: "GetBalancesByAddressesRequest",
|
||||
CmdGetBalancesByAddressesResponseMessage: "GetBalancesByAddressesResponse",
|
||||
CmdNotifyNewBlockTemplateRequestMessage: "NotifyNewBlockTemplateRequest",
|
||||
CmdNotifyNewBlockTemplateResponseMessage: "NotifyNewBlockTemplateResponse",
|
||||
CmdNewBlockTemplateNotificationMessage: "NewBlockTemplateNotification",
|
||||
CmdGetMempoolEntriesByAddressesRequestMessage: "GetMempoolEntriesByAddressesRequest",
|
||||
CmdGetMempoolEntriesByAddressesResponseMessage: "GetMempoolEntriesByAddressesResponse",
|
||||
CmdGetCoinSupplyRequestMessage: "GetCoinSupplyRequest",
|
||||
CmdGetCoinSupplyResponseMessage: "GetCoinSupplyResponse",
|
||||
CmdGetFeeEstimateRequestMessage: "GetFeeEstimateRequest",
|
||||
CmdGetFeeEstimateResponseMessage: "GetFeeEstimateResponse",
|
||||
CmdSubmitTransactionReplacementRequestMessage: "SubmitTransactionReplacementRequest",
|
||||
CmdSubmitTransactionReplacementResponseMessage: "SubmitTransactionReplacementResponse",
|
||||
}
|
||||
|
||||
// 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,74 +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
|
||||
|
||||
// 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,245 +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 := uint32(4)
|
||||
|
||||
// Block 1 header.
|
||||
parents := blockOne.Header.Parents
|
||||
hashMerkleRoot := blockOne.Header.HashMerkleRoot
|
||||
acceptedIDMerkleRoot := blockOne.Header.AcceptedIDMerkleRoot
|
||||
utxoCommitment := blockOne.Header.UTXOCommitment
|
||||
bits := blockOne.Header.Bits
|
||||
nonce := blockOne.Header.Nonce
|
||||
daaScore := blockOne.Header.DAAScore
|
||||
blueScore := blockOne.Header.BlueScore
|
||||
blueWork := blockOne.Header.BlueWork
|
||||
pruningPoint := blockOne.Header.PruningPoint
|
||||
bh := NewBlockHeader(1, parents, hashMerkleRoot, acceptedIDMerkleRoot, utxoCommitment, bits, nonce,
|
||||
daaScore, blueScore, blueWork, pruningPoint)
|
||||
|
||||
// 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,
|
||||
Parents: []externalapi.BlockLevelParents{[]*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,102 +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/big"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/util/mstime"
|
||||
)
|
||||
|
||||
// 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
|
||||
|
||||
// Parents are the parent block hashes of the block in the DAG per superblock level.
|
||||
Parents []externalapi.BlockLevelParents
|
||||
|
||||
// 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
|
||||
|
||||
// DAASCore is the DAA score of the block.
|
||||
DAAScore uint64
|
||||
|
||||
BlueScore uint64
|
||||
|
||||
// BlueWork is the blue work of the block.
|
||||
BlueWork *big.Int
|
||||
|
||||
PruningPoint *externalapi.DomainHash
|
||||
}
|
||||
|
||||
// BlockHash computes the block identifier hash for the given block header.
|
||||
func (h *MsgBlockHeader) BlockHash() *externalapi.DomainHash {
|
||||
return consensushashing.HeaderHash(BlockHeaderToDomainBlockHeader(h))
|
||||
}
|
||||
|
||||
// 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, parents []externalapi.BlockLevelParents, hashMerkleRoot *externalapi.DomainHash,
|
||||
acceptedIDMerkleRoot *externalapi.DomainHash, utxoCommitment *externalapi.DomainHash, bits uint32, nonce,
|
||||
daaScore, blueScore uint64, blueWork *big.Int, pruningPoint *externalapi.DomainHash) *MsgBlockHeader {
|
||||
|
||||
// Limit the timestamp to one millisecond precision since the protocol
|
||||
// doesn't support better.
|
||||
return &MsgBlockHeader{
|
||||
Version: version,
|
||||
Parents: parents,
|
||||
HashMerkleRoot: hashMerkleRoot,
|
||||
AcceptedIDMerkleRoot: acceptedIDMerkleRoot,
|
||||
UTXOCommitment: utxoCommitment,
|
||||
Timestamp: mstime.Now(),
|
||||
Bits: bits,
|
||||
Nonce: nonce,
|
||||
DAAScore: daaScore,
|
||||
BlueScore: blueScore,
|
||||
BlueWork: blueWork,
|
||||
PruningPoint: pruningPoint,
|
||||
}
|
||||
}
|
||||
@@ -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 (
|
||||
"math/big"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
)
|
||||
|
||||
// TestBlockHeader tests the MsgBlockHeader API.
|
||||
func TestBlockHeader(t *testing.T) {
|
||||
nonce := uint64(0xba4d87a69924a93d)
|
||||
|
||||
parents := []externalapi.BlockLevelParents{[]*externalapi.DomainHash{mainnetGenesisHash, simnetGenesisHash}}
|
||||
|
||||
merkleHash := mainnetGenesisMerkleRoot
|
||||
acceptedIDMerkleRoot := exampleAcceptedIDMerkleRoot
|
||||
bits := uint32(0x1d00ffff)
|
||||
daaScore := uint64(123)
|
||||
blueScore := uint64(456)
|
||||
blueWork := big.NewInt(789)
|
||||
pruningPoint := simnetGenesisHash
|
||||
bh := NewBlockHeader(1, parents, merkleHash, acceptedIDMerkleRoot, exampleUTXOCommitment, bits, nonce,
|
||||
daaScore, blueScore, blueWork, pruningPoint)
|
||||
|
||||
// Ensure we get the same data back out.
|
||||
if !reflect.DeepEqual(bh.Parents, parents) {
|
||||
t.Errorf("NewBlockHeader: wrong parents - got %v, want %v",
|
||||
spew.Sprint(bh.Parents), spew.Sprint(parents))
|
||||
}
|
||||
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)
|
||||
}
|
||||
if bh.DAAScore != daaScore {
|
||||
t.Errorf("NewBlockHeader: wrong daaScore - got %v, want %v",
|
||||
bh.DAAScore, daaScore)
|
||||
}
|
||||
if bh.BlueScore != blueScore {
|
||||
t.Errorf("NewBlockHeader: wrong blueScore - got %v, want %v",
|
||||
bh.BlueScore, blueScore)
|
||||
}
|
||||
if bh.BlueWork != blueWork {
|
||||
t.Errorf("NewBlockHeader: wrong blueWork - got %v, want %v",
|
||||
bh.BlueWork, blueWork)
|
||||
}
|
||||
if !bh.PruningPoint.Equal(pruningPoint) {
|
||||
t.Errorf("NewBlockHeader: wrong pruningPoint - got %v, want %v",
|
||||
bh.PruningPoint, pruningPoint)
|
||||
}
|
||||
}
|
||||
@@ -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,54 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// MsgBlockWithTrustedData represents a kaspa BlockWithTrustedData message
|
||||
type MsgBlockWithTrustedData struct {
|
||||
baseMessage
|
||||
|
||||
Block *MsgBlock
|
||||
DAAScore uint64
|
||||
DAAWindow []*TrustedDataDataDAABlock
|
||||
GHOSTDAGData []*BlockGHOSTDAGDataHashPair
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *MsgBlockWithTrustedData) Command() MessageCommand {
|
||||
return CmdBlockWithTrustedData
|
||||
}
|
||||
|
||||
// NewMsgBlockWithTrustedData returns a new MsgBlockWithTrustedData.
|
||||
func NewMsgBlockWithTrustedData() *MsgBlockWithTrustedData {
|
||||
return &MsgBlockWithTrustedData{}
|
||||
}
|
||||
|
||||
// TrustedDataDataDAABlock is an appmessage representation of externalapi.TrustedDataDataDAABlock
|
||||
type TrustedDataDataDAABlock struct {
|
||||
Block *MsgBlock
|
||||
GHOSTDAGData *BlockGHOSTDAGData
|
||||
}
|
||||
|
||||
// BlockGHOSTDAGData is an appmessage representation of externalapi.BlockGHOSTDAGData
|
||||
type BlockGHOSTDAGData struct {
|
||||
BlueScore uint64
|
||||
BlueWork *big.Int
|
||||
SelectedParent *externalapi.DomainHash
|
||||
MergeSetBlues []*externalapi.DomainHash
|
||||
MergeSetReds []*externalapi.DomainHash
|
||||
BluesAnticoneSizes []*BluesAnticoneSizes
|
||||
}
|
||||
|
||||
// BluesAnticoneSizes is an appmessage representation of the BluesAnticoneSizes part of GHOSTDAG data.
|
||||
type BluesAnticoneSizes struct {
|
||||
BlueHash *externalapi.DomainHash
|
||||
AnticoneSize externalapi.KType
|
||||
}
|
||||
|
||||
// BlockGHOSTDAGDataHashPair is an appmessage representation of externalapi.BlockGHOSTDAGDataHashPair
|
||||
type BlockGHOSTDAGDataHashPair struct {
|
||||
Hash *externalapi.DomainHash
|
||||
GHOSTDAGData *BlockGHOSTDAGData
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// MsgBlockWithTrustedDataV4 represents a kaspa BlockWithTrustedDataV4 message
|
||||
type MsgBlockWithTrustedDataV4 struct {
|
||||
baseMessage
|
||||
|
||||
Block *MsgBlock
|
||||
DAAWindowIndices []uint64
|
||||
GHOSTDAGDataIndices []uint64
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *MsgBlockWithTrustedDataV4) Command() MessageCommand {
|
||||
return CmdBlockWithTrustedDataV4
|
||||
}
|
||||
|
||||
// NewMsgBlockWithTrustedDataV4 returns a new MsgBlockWithTrustedDataV4.
|
||||
func NewMsgBlockWithTrustedDataV4() *MsgBlockWithTrustedDataV4 {
|
||||
return &MsgBlockWithTrustedDataV4{}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// MsgDoneBlocksWithTrustedData implements the Message interface and represents a kaspa
|
||||
// DoneBlocksWithTrustedData message
|
||||
//
|
||||
// This message has no payload.
|
||||
type MsgDoneBlocksWithTrustedData struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgDoneBlocksWithTrustedData) Command() MessageCommand {
|
||||
return CmdDoneBlocksWithTrustedData
|
||||
}
|
||||
|
||||
// NewMsgDoneBlocksWithTrustedData returns a new kaspa DoneBlocksWithTrustedData message that conforms to the
|
||||
// Message interface.
|
||||
func NewMsgDoneBlocksWithTrustedData() *MsgDoneBlocksWithTrustedData {
|
||||
return &MsgDoneBlocksWithTrustedData{}
|
||||
}
|
||||
@@ -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,16 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// MsgRequestPruningPointAndItsAnticone represents a kaspa RequestPruningPointAndItsAnticone message
|
||||
type MsgRequestPruningPointAndItsAnticone struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *MsgRequestPruningPointAndItsAnticone) Command() MessageCommand {
|
||||
return CmdRequestPruningPointAndItsAnticone
|
||||
}
|
||||
|
||||
// NewMsgRequestPruningPointAndItsAnticone returns a new MsgRequestPruningPointAndItsAnticone.
|
||||
func NewMsgRequestPruningPointAndItsAnticone() *MsgRequestPruningPointAndItsAnticone {
|
||||
return &MsgRequestPruningPointAndItsAnticone{}
|
||||
}
|
||||
@@ -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,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"
|
||||
)
|
||||
|
||||
// MsgIBDChainBlockLocator 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 MsgIBDChainBlockLocator struct {
|
||||
baseMessage
|
||||
BlockLocatorHashes []*externalapi.DomainHash
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgIBDChainBlockLocator) Command() MessageCommand {
|
||||
return CmdIBDChainBlockLocator
|
||||
}
|
||||
|
||||
// NewMsgIBDChainBlockLocator returns a new kaspa locator message that conforms to
|
||||
// the Message interface. See MsgBlockLocator for details.
|
||||
func NewMsgIBDChainBlockLocator(locatorHashes []*externalapi.DomainHash) *MsgIBDChainBlockLocator {
|
||||
return &MsgIBDChainBlockLocator{
|
||||
BlockLocatorHashes: locatorHashes,
|
||||
}
|
||||
}
|
||||
@@ -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,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,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,20 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// MsgPruningPointProof represents a kaspa PruningPointProof message
|
||||
type MsgPruningPointProof struct {
|
||||
baseMessage
|
||||
|
||||
Headers [][]*MsgBlockHeader
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *MsgPruningPointProof) Command() MessageCommand {
|
||||
return CmdPruningPointProof
|
||||
}
|
||||
|
||||
// NewMsgPruningPointProof returns a new MsgPruningPointProof.
|
||||
func NewMsgPruningPointProof(headers [][]*MsgBlockHeader) *MsgPruningPointProof {
|
||||
return &MsgPruningPointProof{
|
||||
Headers: headers,
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// MsgPruningPoints represents a kaspa PruningPoints message
|
||||
type MsgPruningPoints struct {
|
||||
baseMessage
|
||||
|
||||
Headers []*MsgBlockHeader
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *MsgPruningPoints) Command() MessageCommand {
|
||||
return CmdPruningPoints
|
||||
}
|
||||
|
||||
// NewMsgPruningPoints returns a new MsgPruningPoints.
|
||||
func NewMsgPruningPoints(headers []*MsgBlockHeader) *MsgPruningPoints {
|
||||
return &MsgPruningPoints{
|
||||
Headers: headers,
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
BlockDAAScore 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 @@
|
||||
// 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"
|
||||
)
|
||||
|
||||
// MsgRequestAnticone implements the Message interface and represents a kaspa
|
||||
// RequestHeaders message. It is used to request the set past(ContextHash) \cap anticone(BlockHash)
|
||||
type MsgRequestAnticone struct {
|
||||
baseMessage
|
||||
BlockHash *externalapi.DomainHash
|
||||
ContextHash *externalapi.DomainHash
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgRequestAnticone) Command() MessageCommand {
|
||||
return CmdRequestAnticone
|
||||
}
|
||||
|
||||
// NewMsgRequestAnticone returns a new kaspa RequestPastDiff message that conforms to the
|
||||
// Message interface using the passed parameters and defaults for the remaining
|
||||
// fields.
|
||||
func NewMsgRequestAnticone(blockHash, contextHash *externalapi.DomainHash) *MsgRequestAnticone {
|
||||
return &MsgRequestAnticone{
|
||||
BlockHash: blockHash,
|
||||
ContextHash: contextHash,
|
||||
}
|
||||
}
|
||||
@@ -1,31 +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
|
||||
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(highHash *externalapi.DomainHash, limit uint32) *MsgRequestBlockLocator {
|
||||
return &MsgRequestBlockLocator{
|
||||
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, 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 MsgRequestIBDBlocks 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("NewMsgRequstIBDBlocks: 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("NewMsgRequstIBDBlocks: 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,31 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
)
|
||||
|
||||
// MsgRequestIBDChainBlockLocator implements the Message interface and represents a kaspa
|
||||
// IBDRequestChainBlockLocator message. It is used to request a block locator between low
|
||||
// and high hash.
|
||||
// The locator is returned via a locator message (MsgIBDChainBlockLocator).
|
||||
type MsgRequestIBDChainBlockLocator struct {
|
||||
baseMessage
|
||||
HighHash *externalapi.DomainHash
|
||||
LowHash *externalapi.DomainHash
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgRequestIBDChainBlockLocator) Command() MessageCommand {
|
||||
return CmdRequestIBDChainBlockLocator
|
||||
}
|
||||
|
||||
// NewMsgIBDRequestChainBlockLocator returns a new IBDRequestChainBlockLocator message that conforms to the
|
||||
// Message interface using the passed parameters and defaults for the remaining
|
||||
// fields.
|
||||
func NewMsgIBDRequestChainBlockLocator(highHash, lowHash *externalapi.DomainHash) *MsgRequestIBDChainBlockLocator {
|
||||
return &MsgRequestIBDChainBlockLocator{
|
||||
HighHash: highHash,
|
||||
LowHash: lowHash,
|
||||
}
|
||||
}
|
||||
@@ -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,22 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// MsgRequestNextPruningPointAndItsAnticoneBlocks implements the Message interface and represents a kaspa
|
||||
// RequestNextPruningPointAndItsAnticoneBlocks message. It is used to notify the IBD syncer peer to send
|
||||
// more blocks from the pruning anticone.
|
||||
//
|
||||
// This message has no payload.
|
||||
type MsgRequestNextPruningPointAndItsAnticoneBlocks struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgRequestNextPruningPointAndItsAnticoneBlocks) Command() MessageCommand {
|
||||
return CmdRequestNextPruningPointAndItsAnticoneBlocks
|
||||
}
|
||||
|
||||
// NewMsgRequestNextPruningPointAndItsAnticoneBlocks returns a new kaspa RequestNextPruningPointAndItsAnticoneBlocks message that conforms to the
|
||||
// Message interface.
|
||||
func NewMsgRequestNextPruningPointAndItsAnticoneBlocks() *MsgRequestNextPruningPointAndItsAnticoneBlocks {
|
||||
return &MsgRequestNextPruningPointAndItsAnticoneBlocks{}
|
||||
}
|
||||
@@ -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,16 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// MsgRequestPruningPointProof represents a kaspa RequestPruningPointProof message
|
||||
type MsgRequestPruningPointProof struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *MsgRequestPruningPointProof) Command() MessageCommand {
|
||||
return CmdRequestPruningPointProof
|
||||
}
|
||||
|
||||
// NewMsgRequestPruningPointProof returns a new MsgRequestPruningPointProof.
|
||||
func NewMsgRequestPruningPointProof() *MsgRequestPruningPointProof {
|
||||
return &MsgRequestPruningPointProof{}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
)
|
||||
|
||||
// MsgRequestPruningPointUTXOSet represents a kaspa RequestPruningPointUTXOSet message
|
||||
type MsgRequestPruningPointUTXOSet struct {
|
||||
baseMessage
|
||||
PruningPointHash *externalapi.DomainHash
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *MsgRequestPruningPointUTXOSet) Command() MessageCommand {
|
||||
return CmdRequestPruningPointUTXOSet
|
||||
}
|
||||
|
||||
// NewMsgRequestPruningPointUTXOSet returns a new MsgRequestPruningPointUTXOSet
|
||||
func NewMsgRequestPruningPointUTXOSet(pruningPointHash *externalapi.DomainHash) *MsgRequestPruningPointUTXOSet {
|
||||
return &MsgRequestPruningPointUTXOSet{
|
||||
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,25 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// MsgTrustedData represents a kaspa TrustedData message
|
||||
type MsgTrustedData struct {
|
||||
baseMessage
|
||||
|
||||
DAAWindow []*TrustedDataDAAHeader
|
||||
GHOSTDAGData []*BlockGHOSTDAGDataHashPair
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *MsgTrustedData) Command() MessageCommand {
|
||||
return CmdTrustedData
|
||||
}
|
||||
|
||||
// NewMsgTrustedData returns a new MsgTrustedData.
|
||||
func NewMsgTrustedData() *MsgTrustedData {
|
||||
return &MsgTrustedData{}
|
||||
}
|
||||
|
||||
// TrustedDataDAAHeader is an appmessage representation of externalapi.TrustedDataDataDAAHeader
|
||||
type TrustedDataDAAHeader struct {
|
||||
Header *MsgBlockHeader
|
||||
GHOSTDAGData *BlockGHOSTDAGData
|
||||
}
|
||||
@@ -1,319 +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"
|
||||
"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
|
||||
SigOpCount byte
|
||||
}
|
||||
|
||||
// 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, sigOpCount byte) *TxIn {
|
||||
return &TxIn{
|
||||
PreviousOutpoint: *prevOut,
|
||||
SignatureScript: signatureScript,
|
||||
Sequence: sequence,
|
||||
SigOpCount: sigOpCount,
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
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,
|
||||
}
|
||||
|
||||
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,
|
||||
SigOpCount: oldTxIn.SigOpCount,
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
return &MsgTx{
|
||||
Version: version,
|
||||
TxIn: txIn,
|
||||
TxOut: txOut,
|
||||
SubnetworkID: *subnetworkID,
|
||||
Gas: gas,
|
||||
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 := uint32(4)
|
||||
|
||||
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, 1)
|
||||
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 := "b06f8b650115b5cf4d59499e10764a9312742930cb43c9b4ff6495d76f332ed7"
|
||||
txID1Str := "e20225c3d065ee41743607ee627db44d01ef396dc9779b05b2caf55bac50e12d"
|
||||
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 := "fa16a8ce88d52ca1ff45187bbba0d33044e9f5fe309e8d0b22d4812dcf1782b7"
|
||||
wantHash2, err := externalapi.NewDomainHashFromString(hash2Str)
|
||||
if err != nil {
|
||||
t.Errorf("NewTxIDFromStr: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
id2Str := "89ffb49474637502d9059af38b8a95fc2f0d3baef5c801d7a9b9c8830671b711"
|
||||
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, protocolVersion uint32) *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 := uint32(4)
|
||||
|
||||
// Create version message data.
|
||||
tcpAddrMe := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 16111}
|
||||
me := NewNetAddress(tcpAddrMe)
|
||||
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, 4)
|
||||
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,64 +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 (
|
||||
"net"
|
||||
|
||||
"github.com/kaspanet/kaspad/util/mstime"
|
||||
)
|
||||
|
||||
// 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
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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) *NetAddress {
|
||||
return NewNetAddressTimestamp(mstime.Now(), 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, ip net.IP, port uint16) *NetAddress {
|
||||
// Limit the timestamp to one millisecond precision since the protocol
|
||||
// doesn't support better.
|
||||
na := NetAddress{
|
||||
Timestamp: timestamp,
|
||||
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) *NetAddress {
|
||||
return NewNetAddressIPPort(addr.IP, uint16(addr.Port))
|
||||
}
|
||||
|
||||
func (na NetAddress) String() string {
|
||||
return na.TCPAddress().String()
|
||||
}
|
||||
@@ -1,28 +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})
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// MsgReady implements the Message interface and represents a kaspa
|
||||
// Ready message. It is used to notify that the peer is ready to receive
|
||||
// messages.
|
||||
//
|
||||
// This message has no payload.
|
||||
type MsgReady struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message. This is part
|
||||
// of the Message interface implementation.
|
||||
func (msg *MsgReady) Command() MessageCommand {
|
||||
return CmdReady
|
||||
}
|
||||
|
||||
// NewMsgReady returns a new kaspa Ready message that conforms to the
|
||||
// Message interface.
|
||||
func NewMsgReady() *MsgReady {
|
||||
return &MsgReady{}
|
||||
}
|
||||
@@ -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,43 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// EstimateNetworkHashesPerSecondRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type EstimateNetworkHashesPerSecondRequestMessage struct {
|
||||
baseMessage
|
||||
StartHash string
|
||||
WindowSize uint32
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *EstimateNetworkHashesPerSecondRequestMessage) Command() MessageCommand {
|
||||
return CmdEstimateNetworkHashesPerSecondRequestMessage
|
||||
}
|
||||
|
||||
// NewEstimateNetworkHashesPerSecondRequestMessage returns a instance of the message
|
||||
func NewEstimateNetworkHashesPerSecondRequestMessage(startHash string, windowSize uint32) *EstimateNetworkHashesPerSecondRequestMessage {
|
||||
return &EstimateNetworkHashesPerSecondRequestMessage{
|
||||
StartHash: startHash,
|
||||
WindowSize: windowSize,
|
||||
}
|
||||
}
|
||||
|
||||
// EstimateNetworkHashesPerSecondResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type EstimateNetworkHashesPerSecondResponseMessage struct {
|
||||
baseMessage
|
||||
NetworkHashesPerSecond uint64
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *EstimateNetworkHashesPerSecondResponseMessage) Command() MessageCommand {
|
||||
return CmdEstimateNetworkHashesPerSecondResponseMessage
|
||||
}
|
||||
|
||||
// NewEstimateNetworkHashesPerSecondResponseMessage returns a instance of the message
|
||||
func NewEstimateNetworkHashesPerSecondResponseMessage(networkHashesPerSecond uint64) *EstimateNetworkHashesPerSecondResponseMessage {
|
||||
return &EstimateNetworkHashesPerSecondResponseMessage{
|
||||
NetworkHashesPerSecond: networkHashesPerSecond,
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// GetFeeEstimateRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetFeeEstimateRequestMessage struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetFeeEstimateRequestMessage) Command() MessageCommand {
|
||||
return CmdGetFeeEstimateRequestMessage
|
||||
}
|
||||
|
||||
// NewGetFeeEstimateRequestMessage returns a instance of the message
|
||||
func NewGetFeeEstimateRequestMessage() *GetFeeEstimateRequestMessage {
|
||||
return &GetFeeEstimateRequestMessage{}
|
||||
}
|
||||
|
||||
type RPCFeeRateBucket struct {
|
||||
Feerate float64
|
||||
EstimatedSeconds float64
|
||||
}
|
||||
|
||||
type RPCFeeEstimate struct {
|
||||
PriorityBucket RPCFeeRateBucket
|
||||
NormalBuckets []RPCFeeRateBucket
|
||||
LowBuckets []RPCFeeRateBucket
|
||||
}
|
||||
|
||||
// GetCoinSupplyResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetFeeEstimateResponseMessage struct {
|
||||
baseMessage
|
||||
Estimate RPCFeeEstimate
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetFeeEstimateResponseMessage) Command() MessageCommand {
|
||||
return CmdGetFeeEstimateResponseMessage
|
||||
}
|
||||
|
||||
// NewGetFeeEstimateResponseMessage returns a instance of the message
|
||||
func NewGetFeeEstimateResponseMessage() *GetFeeEstimateResponseMessage {
|
||||
return &GetFeeEstimateResponseMessage{}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// GetBalanceByAddressRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBalanceByAddressRequestMessage struct {
|
||||
baseMessage
|
||||
Address string
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetBalanceByAddressRequestMessage) Command() MessageCommand {
|
||||
return CmdGetBalanceByAddressRequestMessage
|
||||
}
|
||||
|
||||
// NewGetBalanceByAddressRequest returns a instance of the message
|
||||
func NewGetBalanceByAddressRequest(address string) *GetBalanceByAddressRequestMessage {
|
||||
return &GetBalanceByAddressRequestMessage{
|
||||
Address: address,
|
||||
}
|
||||
}
|
||||
|
||||
// GetBalanceByAddressResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBalanceByAddressResponseMessage struct {
|
||||
baseMessage
|
||||
Balance uint64
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetBalanceByAddressResponseMessage) Command() MessageCommand {
|
||||
return CmdGetBalanceByAddressResponseMessage
|
||||
}
|
||||
|
||||
// NewGetBalanceByAddressResponse returns an instance of the message
|
||||
func NewGetBalanceByAddressResponse(Balance uint64) *GetBalanceByAddressResponseMessage {
|
||||
return &GetBalanceByAddressResponseMessage{
|
||||
Balance: Balance,
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// GetBalancesByAddressesRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBalancesByAddressesRequestMessage struct {
|
||||
baseMessage
|
||||
Addresses []string
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetBalancesByAddressesRequestMessage) Command() MessageCommand {
|
||||
return CmdGetBalancesByAddressesRequestMessage
|
||||
}
|
||||
|
||||
// NewGetBalancesByAddressesRequest returns a instance of the message
|
||||
func NewGetBalancesByAddressesRequest(addresses []string) *GetBalancesByAddressesRequestMessage {
|
||||
return &GetBalancesByAddressesRequestMessage{
|
||||
Addresses: addresses,
|
||||
}
|
||||
}
|
||||
|
||||
// BalancesByAddressesEntry represents the balance of some address
|
||||
type BalancesByAddressesEntry struct {
|
||||
Address string
|
||||
Balance uint64
|
||||
}
|
||||
|
||||
// GetBalancesByAddressesResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBalancesByAddressesResponseMessage struct {
|
||||
baseMessage
|
||||
Entries []*BalancesByAddressesEntry
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetBalancesByAddressesResponseMessage) Command() MessageCommand {
|
||||
return CmdGetBalancesByAddressesResponseMessage
|
||||
}
|
||||
|
||||
// NewGetBalancesByAddressesResponse returns an instance of the message
|
||||
func NewGetBalancesByAddressesResponse(entries []*BalancesByAddressesEntry) *GetBalancesByAddressesResponseMessage {
|
||||
return &GetBalancesByAddressesResponseMessage{
|
||||
Entries: entries,
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// GetBlockRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBlockRequestMessage struct {
|
||||
baseMessage
|
||||
Hash string
|
||||
IncludeTransactions 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, includeTransactions bool) *GetBlockRequestMessage {
|
||||
return &GetBlockRequestMessage{
|
||||
Hash: hash,
|
||||
IncludeTransactions: includeTransactions,
|
||||
}
|
||||
}
|
||||
|
||||
// GetBlockResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBlockResponseMessage struct {
|
||||
baseMessage
|
||||
Block *RPCBlock
|
||||
|
||||
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{}
|
||||
}
|
||||
@@ -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,44 +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
|
||||
VirtualDAAScore uint64
|
||||
|
||||
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,45 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// GetBlockTemplateRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBlockTemplateRequestMessage struct {
|
||||
baseMessage
|
||||
PayAddress string
|
||||
ExtraData 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, extraData string) *GetBlockTemplateRequestMessage {
|
||||
return &GetBlockTemplateRequestMessage{
|
||||
PayAddress: payAddress,
|
||||
ExtraData: extraData,
|
||||
}
|
||||
}
|
||||
|
||||
// GetBlockTemplateResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBlockTemplateResponseMessage struct {
|
||||
baseMessage
|
||||
Block *RPCBlock
|
||||
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(block *RPCBlock, isSynced bool) *GetBlockTemplateResponseMessage {
|
||||
return &GetBlockTemplateResponseMessage{
|
||||
Block: block,
|
||||
IsSynced: isSynced,
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// GetBlocksRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBlocksRequestMessage struct {
|
||||
baseMessage
|
||||
LowHash string
|
||||
IncludeBlocks bool
|
||||
IncludeTransactions 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, includeBlocks bool,
|
||||
includeTransactions bool) *GetBlocksRequestMessage {
|
||||
return &GetBlocksRequestMessage{
|
||||
LowHash: lowHash,
|
||||
IncludeBlocks: includeBlocks,
|
||||
IncludeTransactions: includeTransactions,
|
||||
}
|
||||
}
|
||||
|
||||
// GetBlocksResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetBlocksResponseMessage struct {
|
||||
baseMessage
|
||||
BlockHashes []string
|
||||
Blocks []*RPCBlock
|
||||
|
||||
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() *GetBlocksResponseMessage {
|
||||
return &GetBlocksResponseMessage{}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package appmessage
|
||||
|
||||
// GetCoinSupplyRequestMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetCoinSupplyRequestMessage struct {
|
||||
baseMessage
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetCoinSupplyRequestMessage) Command() MessageCommand {
|
||||
return CmdGetCoinSupplyRequestMessage
|
||||
}
|
||||
|
||||
// NewGetCoinSupplyRequestMessage returns a instance of the message
|
||||
func NewGetCoinSupplyRequestMessage() *GetCoinSupplyRequestMessage {
|
||||
return &GetCoinSupplyRequestMessage{}
|
||||
}
|
||||
|
||||
// GetCoinSupplyResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetCoinSupplyResponseMessage struct {
|
||||
baseMessage
|
||||
MaxSompi uint64
|
||||
CirculatingSompi uint64
|
||||
|
||||
Error *RPCError
|
||||
}
|
||||
|
||||
// Command returns the protocol command string for the message
|
||||
func (msg *GetCoinSupplyResponseMessage) Command() MessageCommand {
|
||||
return CmdGetCoinSupplyResponseMessage
|
||||
}
|
||||
|
||||
// NewGetCoinSupplyResponseMessage returns a instance of the message
|
||||
func NewGetCoinSupplyResponseMessage(maxSompi uint64, circulatingSompi uint64) *GetCoinSupplyResponseMessage {
|
||||
return &GetCoinSupplyResponseMessage{
|
||||
MaxSompi: maxSompi,
|
||||
CirculatingSompi: circulatingSompi,
|
||||
}
|
||||
}
|
||||
@@ -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,46 +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
|
||||
}
|
||||
|
||||
// NewGetInfoRequestMessage returns a instance of the message
|
||||
func NewGetInfoRequestMessage() *GetInfoRequestMessage {
|
||||
return &GetInfoRequestMessage{}
|
||||
}
|
||||
|
||||
// GetInfoResponseMessage is an appmessage corresponding to
|
||||
// its respective RPC message
|
||||
type GetInfoResponseMessage struct {
|
||||
baseMessage
|
||||
P2PID string
|
||||
MempoolSize uint64
|
||||
ServerVersion string
|
||||
IsUtxoIndexed bool
|
||||
IsSynced bool
|
||||
|
||||
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, mempoolSize uint64, serverVersion string, isUtxoIndexed bool, isSynced bool) *GetInfoResponseMessage {
|
||||
return &GetInfoResponseMessage{
|
||||
P2PID: p2pID,
|
||||
MempoolSize: mempoolSize,
|
||||
ServerVersion: serverVersion,
|
||||
IsUtxoIndexed: isUtxoIndexed,
|
||||
IsSynced: isSynced,
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user