mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-09-14 21:40:11 +00:00
Compare commits
No commits in common. "master" and "v0.3.1" have entirely different histories.
@ -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)
|
|
17
.gitignore
vendored
17
.gitignore
vendored
@ -13,21 +13,6 @@ kaspad.db
|
|||||||
*.o
|
*.o
|
||||||
*.a
|
*.a
|
||||||
*.so
|
*.so
|
||||||
*.dylib
|
|
||||||
|
|
||||||
# Test binary, built with `go test -c`
|
|
||||||
*.test
|
|
||||||
|
|
||||||
# Real binaries, build with `go build .`
|
|
||||||
kaspad
|
|
||||||
cmd/gencerts/gencerts
|
|
||||||
cmd/kaspactl/kaspactl
|
|
||||||
cmd/kasminer/kaspaminer
|
|
||||||
*.exe
|
|
||||||
*.exe~
|
|
||||||
|
|
||||||
# Output of the go coverage tool
|
|
||||||
*.out
|
|
||||||
|
|
||||||
# Folders
|
# Folders
|
||||||
_obj
|
_obj
|
||||||
@ -46,6 +31,7 @@ _cgo_export.*
|
|||||||
|
|
||||||
_testmain.go
|
_testmain.go
|
||||||
|
|
||||||
|
*.exe
|
||||||
|
|
||||||
# IDE
|
# IDE
|
||||||
.idea
|
.idea
|
||||||
@ -53,7 +39,6 @@ _testmain.go
|
|||||||
debug
|
debug
|
||||||
debug.test
|
debug.test
|
||||||
__debug_bin
|
__debug_bin
|
||||||
*__debug_*
|
|
||||||
|
|
||||||
# CI
|
# CI
|
||||||
version.txt
|
version.txt
|
||||||
|
@ -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.
|
|
46
README.md
46
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
|
||||||
|
====
|
||||||
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.
|
Warning: This is pre-alpha software. There's no guarantee anything works.
|
||||||
|
====
|
||||||
# Kaspad
|
|
||||||
|
|
||||||
[](https://choosealicense.com/licenses/isc/)
|
[](https://choosealicense.com/licenses/isc/)
|
||||||
[](http://godoc.org/github.com/kaspanet/kaspad)
|
[](http://godoc.org/github.com/kaspanet/kaspad)
|
||||||
|
|
||||||
Kaspad 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
|
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.
|
||||||
Kaspa is an attempt at a proof-of-work cryptocurrency with instant confirmations and sub-second block times. It is based on [the PHANTOM protocol](https://eprint.iacr.org/2018/104.pdf), a generalization of Nakamoto consensus.
|
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
Go 1.23 or later.
|
Latest version of [Go](http://golang.org) (currently 1.13).
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@ -30,44 +27,53 @@ Go 1.23 or later.
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ go version
|
$ go version
|
||||||
|
$ go env GOROOT GOPATH
|
||||||
```
|
```
|
||||||
|
|
||||||
|
NOTE: The `GOROOT` and `GOPATH` above must not be the same path. It is
|
||||||
|
recommended that `GOPATH` is set to a directory in your home directory such as
|
||||||
|
`~/dev/go` to avoid write permission issues. It is also recommended to add
|
||||||
|
`$GOPATH/bin` to your `PATH` at this point.
|
||||||
|
|
||||||
- Run the following commands to obtain and install kaspad including all dependencies:
|
- Run the following commands to obtain and install kaspad including all dependencies:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ git clone https://github.com/kaspanet/kaspad
|
$ git clone https://github.com/kaspanet/kaspad $GOPATH/src/github.com/kaspanet/kaspad
|
||||||
$ cd kaspad
|
$ cd $GOPATH/src/github.com/kaspanet/kaspad
|
||||||
|
$ ./test.sh
|
||||||
$ go install . ./cmd/...
|
$ go install . ./cmd/...
|
||||||
```
|
```
|
||||||
|
`./test.sh` tests can be skipped, but some things might not run correctly on your system if tests fail.
|
||||||
|
|
||||||
- Kaspad (and utilities) should now be installed in `$(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,
|
not already add the bin directory to your system path during Go installation,
|
||||||
you are encouraged to do so now.
|
you are encouraged to do so now.
|
||||||
|
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
Kaspad has several configuration options available to tweak how it runs, but all
|
Kaspad has several configuration options available to tweak how it runs, but all
|
||||||
of the basic operations work with zero configuration.
|
of the basic operations work with zero configuration.
|
||||||
|
|
||||||
|
#### Linux/BSD/POSIX/Source
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ kaspad
|
$ ./kaspad
|
||||||
```
|
```
|
||||||
|
|
||||||
## Discord
|
## Discord
|
||||||
|
Join our discord server using the following link: https://discord.gg/WmGhhzk
|
||||||
Join our discord server using the following link: https://discord.gg/YNYnNN5Pf2
|
|
||||||
|
|
||||||
## Issue Tracker
|
## Issue Tracker
|
||||||
|
|
||||||
The [integrated github issue tracker](https://github.com/kaspanet/kaspad/issues)
|
The [integrated github issue tracker](https://github.com/kaspanet/kaspad/issues)
|
||||||
is used for this project.
|
is used for this project.
|
||||||
|
|
||||||
Issue priorities may be seen at https://github.com/orgs/kaspanet/projects/4
|
|
||||||
|
|
||||||
## Documentation
|
## 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
|
## License
|
||||||
|
|
||||||
Kaspad is licensed under the copyfree [ISC License](https://choosealicense.com/licenses/isc/).
|
Kaspad is licensed under the copyfree [ISC License](https://choosealicense.com/licenses/isc/).
|
||||||
|
|
||||||
|
1347
addrmgr/addrmanager.go
Normal file
1347
addrmgr/addrmanager.go
Normal file
File diff suppressed because it is too large
Load Diff
674
addrmgr/addrmanager_test.go
Normal file
674
addrmgr/addrmanager_test.go
Normal file
@ -0,0 +1,674 @@
|
|||||||
|
// 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 (
|
||||||
|
"fmt"
|
||||||
|
"github.com/kaspanet/kaspad/config"
|
||||||
|
"github.com/kaspanet/kaspad/dagconfig"
|
||||||
|
"github.com/kaspanet/kaspad/util/subnetworkid"
|
||||||
|
"net"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"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", 16111, "127.0.0.1:16111")
|
||||||
|
addNaTest("127.0.0.1", 16110, "127.0.0.1:16110")
|
||||||
|
|
||||||
|
// Class A
|
||||||
|
addNaTest("1.0.0.1", 16111, "1.0.0.1:16111")
|
||||||
|
addNaTest("2.2.2.2", 16110, "2.2.2.2:16110")
|
||||||
|
addNaTest("27.253.252.251", 8335, "27.253.252.251:8335")
|
||||||
|
addNaTest("123.3.2.1", 8336, "123.3.2.1:8336")
|
||||||
|
|
||||||
|
// Private Class A
|
||||||
|
addNaTest("10.0.0.1", 16111, "10.0.0.1:16111")
|
||||||
|
addNaTest("10.1.1.1", 16110, "10.1.1.1:16110")
|
||||||
|
addNaTest("10.2.2.2", 8335, "10.2.2.2:8335")
|
||||||
|
addNaTest("10.10.10.10", 8336, "10.10.10.10:8336")
|
||||||
|
|
||||||
|
// Class B
|
||||||
|
addNaTest("128.0.0.1", 16111, "128.0.0.1:16111")
|
||||||
|
addNaTest("129.1.1.1", 16110, "129.1.1.1:16110")
|
||||||
|
addNaTest("180.2.2.2", 8335, "180.2.2.2:8335")
|
||||||
|
addNaTest("191.10.10.10", 8336, "191.10.10.10:8336")
|
||||||
|
|
||||||
|
// Private Class B
|
||||||
|
addNaTest("172.16.0.1", 16111, "172.16.0.1:16111")
|
||||||
|
addNaTest("172.16.1.1", 16110, "172.16.1.1:16110")
|
||||||
|
addNaTest("172.16.2.2", 8335, "172.16.2.2:8335")
|
||||||
|
addNaTest("172.16.172.172", 8336, "172.16.172.172:8336")
|
||||||
|
|
||||||
|
// Class C
|
||||||
|
addNaTest("193.0.0.1", 16111, "193.0.0.1:16111")
|
||||||
|
addNaTest("200.1.1.1", 16110, "200.1.1.1:16110")
|
||||||
|
addNaTest("205.2.2.2", 8335, "205.2.2.2:8335")
|
||||||
|
addNaTest("223.10.10.10", 8336, "223.10.10.10:8336")
|
||||||
|
|
||||||
|
// Private Class C
|
||||||
|
addNaTest("192.168.0.1", 16111, "192.168.0.1:16111")
|
||||||
|
addNaTest("192.168.1.1", 16110, "192.168.1.1:16110")
|
||||||
|
addNaTest("192.168.2.2", 8335, "192.168.2.2:8335")
|
||||||
|
addNaTest("192.168.192.192", 8336, "192.168.192.192:8336")
|
||||||
|
|
||||||
|
// IPv6
|
||||||
|
// Localhost
|
||||||
|
addNaTest("::1", 16111, "[::1]:16111")
|
||||||
|
addNaTest("fe80::1", 16110, "[fe80::1]:16110")
|
||||||
|
|
||||||
|
// Link-local
|
||||||
|
addNaTest("fe80::1:1", 16111, "[fe80::1:1]:16111")
|
||||||
|
addNaTest("fe91::2:2", 16110, "[fe91::2:2]:16110")
|
||||||
|
addNaTest("fea2::3:3", 8335, "[fea2::3:3]:8335")
|
||||||
|
addNaTest("feb3::4:4", 8336, "[feb3::4:4]:8336")
|
||||||
|
|
||||||
|
// Site-local
|
||||||
|
addNaTest("fec0::1:1", 16111, "[fec0::1:1]:16111")
|
||||||
|
addNaTest("fed1::2:2", 16110, "[fed1::2:2]:16110")
|
||||||
|
addNaTest("fee2::3:3", 8335, "[fee2::3:3]:8335")
|
||||||
|
addNaTest("fef3::4:4", 8336, "[fef3::4:4]:8336")
|
||||||
|
}
|
||||||
|
|
||||||
|
func addNaTest(ip string, port uint16, want 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) {
|
||||||
|
originalActiveCfg := config.ActiveConfig()
|
||||||
|
config.SetActiveConfig(&config.Config{
|
||||||
|
Flags: &config.Flags{
|
||||||
|
NetworkFlags: config.NetworkFlags{
|
||||||
|
ActiveNetParams: &dagconfig.SimnetParams},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
defer config.SetActiveConfig(originalActiveCfg)
|
||||||
|
|
||||||
|
fmtErr := errors.Errorf("")
|
||||||
|
addrErr := &net.AddrError{}
|
||||||
|
var tests = []struct {
|
||||||
|
addrIP string
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
someIP + ":16111",
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
someIP,
|
||||||
|
addrErr,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
someIP[:12] + ":8333",
|
||||||
|
fmtErr,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
someIP + ":abcd",
|
||||||
|
fmtErr,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
amgr := 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) {
|
||||||
|
originalActiveCfg := config.ActiveConfig()
|
||||||
|
config.SetActiveConfig(&config.Config{
|
||||||
|
Flags: &config.Flags{
|
||||||
|
NetworkFlags: config.NetworkFlags{
|
||||||
|
ActiveNetParams: &dagconfig.SimnetParams},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
defer config.SetActiveConfig(originalActiveCfg)
|
||||||
|
|
||||||
|
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) {
|
||||||
|
originalActiveCfg := config.ActiveConfig()
|
||||||
|
config.SetActiveConfig(&config.Config{
|
||||||
|
Flags: &config.Flags{
|
||||||
|
NetworkFlags: config.NetworkFlags{
|
||||||
|
ActiveNetParams: &dagconfig.SimnetParams},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
defer config.SetActiveConfig(originalActiveCfg)
|
||||||
|
|
||||||
|
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) {
|
||||||
|
originalActiveCfg := config.ActiveConfig()
|
||||||
|
config.SetActiveConfig(&config.Config{
|
||||||
|
Flags: &config.Flags{
|
||||||
|
NetworkFlags: config.NetworkFlags{
|
||||||
|
ActiveNetParams: &dagconfig.SimnetParams},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
defer config.SetActiveConfig(originalActiveCfg)
|
||||||
|
|
||||||
|
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) {
|
||||||
|
originalActiveCfg := config.ActiveConfig()
|
||||||
|
config.SetActiveConfig(&config.Config{
|
||||||
|
Flags: &config.Flags{
|
||||||
|
NetworkFlags: config.NetworkFlags{
|
||||||
|
ActiveNetParams: &dagconfig.SimnetParams},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
defer config.SetActiveConfig(originalActiveCfg)
|
||||||
|
|
||||||
|
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) {
|
||||||
|
originalActiveCfg := config.ActiveConfig()
|
||||||
|
config.SetActiveConfig(&config.Config{
|
||||||
|
Flags: &config.Flags{
|
||||||
|
NetworkFlags: config.NetworkFlags{
|
||||||
|
ActiveNetParams: &dagconfig.SimnetParams},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
defer config.SetActiveConfig(originalActiveCfg)
|
||||||
|
|
||||||
|
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) {
|
||||||
|
originalActiveCfg := config.ActiveConfig()
|
||||||
|
config.SetActiveConfig(&config.Config{
|
||||||
|
Flags: &config.Flags{
|
||||||
|
NetworkFlags: config.NetworkFlags{
|
||||||
|
ActiveNetParams: &dagconfig.SimnetParams},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
defer config.SetActiveConfig(originalActiveCfg)
|
||||||
|
|
||||||
|
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) {
|
||||||
|
originalActiveCfg := config.ActiveConfig()
|
||||||
|
config.SetActiveConfig(&config.Config{
|
||||||
|
Flags: &config.Flags{
|
||||||
|
NetworkFlags: config.NetworkFlags{
|
||||||
|
ActiveNetParams: &dagconfig.SimnetParams},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
defer config.SetActiveConfig(originalActiveCfg)
|
||||||
|
|
||||||
|
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) {
|
||||||
|
originalActiveCfg := config.ActiveConfig()
|
||||||
|
config.SetActiveConfig(&config.Config{
|
||||||
|
Flags: &config.Flags{
|
||||||
|
NetworkFlags: config.NetworkFlags{
|
||||||
|
ActiveNetParams: &dagconfig.SimnetParams},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
defer config.SetActiveConfig(originalActiveCfg)
|
||||||
|
|
||||||
|
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,7 @@
|
|||||||
/*
|
/*
|
||||||
Package addressmanager implements concurrency safe Kaspa address manager.
|
Package addrmgr implements concurrency safe Kaspa address manager.
|
||||||
|
|
||||||
# Address Manager Overview
|
Address Manager Overview
|
||||||
|
|
||||||
In order maintain the peer-to-peer Kaspa network, there needs to be a source
|
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
|
of addresses to connect to as nodes come and go. The Kaspa protocol provides
|
||||||
@ -31,4 +31,4 @@ 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
|
toward known good peers. The general idea is to make a best effort at only
|
||||||
providing usable addresses.
|
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.GoroutineWrapperFunc(log)
|
@ -2,12 +2,14 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package addressmanager
|
package addrmgr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/app/appmessage"
|
"github.com/kaspanet/kaspad/config"
|
||||||
|
|
||||||
|
"github.com/kaspanet/kaspad/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -78,13 +80,6 @@ var (
|
|||||||
heNet = ipNet("2001:470::", 32, 128)
|
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
|
// 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
|
// of one bits to include at the start of the mask, and the total number of bits
|
||||||
// for the mask.
|
// for the mask.
|
||||||
@ -93,19 +88,19 @@ func ipNet(ip string, ones, bits int) net.IPNet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsIPv4 returns whether or not the given address is an IPv4 address.
|
// 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
|
return na.IP.To4() != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsLocal returns whether or not the given address is a local address.
|
// 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)
|
return na.IP.IsLoopback() || zero4Net.Contains(na.IP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRFC1918 returns whether or not the passed address is part of the IPv4
|
// 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,
|
// private network address space as defined by RFC1918 (10.0.0.0/8,
|
||||||
// 172.16.0.0/12, or 192.168.0.0/16).
|
// 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 {
|
for _, rfc := range rfc1918Nets {
|
||||||
if rfc.Contains(na.IP) {
|
if rfc.Contains(na.IP) {
|
||||||
return true
|
return true
|
||||||
@ -116,56 +111,56 @@ func IsRFC1918(na *appmessage.NetAddress) bool {
|
|||||||
|
|
||||||
// IsRFC2544 returns whether or not the passed address is part of the IPv4
|
// IsRFC2544 returns whether or not the passed address is part of the IPv4
|
||||||
// address space as defined by RFC2544 (198.18.0.0/15)
|
// 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)
|
return rfc2544Net.Contains(na.IP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRFC3849 returns whether or not the passed address is part of the IPv6
|
// IsRFC3849 returns whether or not the passed address is part of the IPv6
|
||||||
// documentation range as defined by RFC3849 (2001:DB8::/32).
|
// 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)
|
return rfc3849Net.Contains(na.IP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRFC3927 returns whether or not the passed address is part of the IPv4
|
// IsRFC3927 returns whether or not the passed address is part of the IPv4
|
||||||
// autoconfiguration range as defined by RFC3927 (169.254.0.0/16).
|
// 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)
|
return rfc3927Net.Contains(na.IP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRFC3964 returns whether or not the passed address is part of the IPv6 to
|
// IsRFC3964 returns whether or not the passed address is part of the IPv6 to
|
||||||
// IPv4 encapsulation range as defined by RFC3964 (2002::/16).
|
// 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)
|
return rfc3964Net.Contains(na.IP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRFC4193 returns whether or not the passed address is part of the IPv6
|
// IsRFC4193 returns whether or not the passed address is part of the IPv6
|
||||||
// unique local range as defined by RFC4193 (FC00::/7).
|
// 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)
|
return rfc4193Net.Contains(na.IP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRFC4380 returns whether or not the passed address is part of the IPv6
|
// IsRFC4380 returns whether or not the passed address is part of the IPv6
|
||||||
// teredo tunneling over UDP range as defined by RFC4380 (2001::/32).
|
// 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)
|
return rfc4380Net.Contains(na.IP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRFC4843 returns whether or not the passed address is part of the IPv6
|
// IsRFC4843 returns whether or not the passed address is part of the IPv6
|
||||||
// ORCHID range as defined by RFC4843 (2001:10::/28).
|
// 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)
|
return rfc4843Net.Contains(na.IP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRFC4862 returns whether or not the passed address is part of the IPv6
|
// IsRFC4862 returns whether or not the passed address is part of the IPv6
|
||||||
// stateless address autoconfiguration range as defined by RFC4862 (FE80::/64).
|
// 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)
|
return rfc4862Net.Contains(na.IP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRFC5737 returns whether or not the passed address is part of the IPv4
|
// 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,
|
// documentation address space as defined by RFC5737 (192.0.2.0/24,
|
||||||
// 198.51.100.0/24, 203.0.113.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 {
|
for _, rfc := range rfc5737Net {
|
||||||
if rfc.Contains(na.IP) {
|
if rfc.Contains(na.IP) {
|
||||||
return true
|
return true
|
||||||
@ -177,19 +172,19 @@ func IsRFC5737(na *appmessage.NetAddress) bool {
|
|||||||
|
|
||||||
// IsRFC6052 returns whether or not the passed address is part of the IPv6
|
// IsRFC6052 returns whether or not the passed address is part of the IPv6
|
||||||
// well-known prefix range as defined by RFC6052 (64:FF9B::/96).
|
// 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)
|
return rfc6052Net.Contains(na.IP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRFC6145 returns whether or not the passed address is part of the IPv6 to
|
// 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).
|
// 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)
|
return rfc6145Net.Contains(na.IP)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRFC6598 returns whether or not the passed address is part of the IPv4
|
// IsRFC6598 returns whether or not the passed address is part of the IPv4
|
||||||
// shared address space specified by RFC6598 (100.64.0.0/10)
|
// 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)
|
return rfc6598Net.Contains(na.IP)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,7 +192,7 @@ func IsRFC6598(na *appmessage.NetAddress) bool {
|
|||||||
// considered invalid under the following circumstances:
|
// considered invalid under the following circumstances:
|
||||||
// IPv4: It is either a zero or all bits set address.
|
// IPv4: It is either a zero or all bits set address.
|
||||||
// IPv6: It is either a zero or RFC3849 documentation 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
|
// IsUnspecified returns if address is 0, so only all bits set, and
|
||||||
// RFC3849 need to be explicitly checked.
|
// RFC3849 need to be explicitly checked.
|
||||||
return na.IP != nil && !(na.IP.IsUnspecified() ||
|
return na.IP != nil && !(na.IP.IsUnspecified() ||
|
||||||
@ -207,8 +202,8 @@ func IsValid(na *appmessage.NetAddress) bool {
|
|||||||
// IsRoutable returns whether or not the passed address is routable over
|
// IsRoutable returns whether or not the passed address is routable over
|
||||||
// the public internet. This is true as long as the address is valid and is not
|
// the public internet. This is true as long as the address is valid and is not
|
||||||
// in any reserved ranges.
|
// in any reserved ranges.
|
||||||
func IsRoutable(na *appmessage.NetAddress, acceptUnroutable bool) bool {
|
func IsRoutable(na *wire.NetAddress) bool {
|
||||||
if acceptUnroutable {
|
if config.ActiveConfig().NetParams().AcceptUnroutable {
|
||||||
return !IsLocal(na)
|
return !IsLocal(na)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,11 +217,11 @@ func IsRoutable(na *appmessage.NetAddress, acceptUnroutable bool) bool {
|
|||||||
// of. This is the /16 for IPv4, the /32 (/36 for he.net) for IPv6, the string
|
// 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, and the string "unroutable" for an unroutable
|
||||||
// address.
|
// address.
|
||||||
func (am *AddressManager) GroupKey(na *appmessage.NetAddress) string {
|
func GroupKey(na *wire.NetAddress) string {
|
||||||
if IsLocal(na) {
|
if IsLocal(na) {
|
||||||
return "local"
|
return "local"
|
||||||
}
|
}
|
||||||
if !IsRoutable(na, am.cfg.AcceptUnroutable) {
|
if !IsRoutable(na) {
|
||||||
return "unroutable"
|
return "unroutable"
|
||||||
}
|
}
|
||||||
if IsIPv4(na) {
|
if IsIPv4(na) {
|
@ -2,22 +2,32 @@
|
|||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package addressmanager
|
package addrmgr_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/kaspanet/kaspad/config"
|
||||||
|
"github.com/kaspanet/kaspad/dagconfig"
|
||||||
"net"
|
"net"
|
||||||
"testing"
|
"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
|
// TestIPTypes ensures the various functions which determine the type of an IP
|
||||||
// address based on RFCs work as intended.
|
// address based on RFCs work as intended.
|
||||||
func TestIPTypes(t *testing.T) {
|
func TestIPTypes(t *testing.T) {
|
||||||
amgr, teardown := newAddressManagerForTest(t, "TestAddAddressByIP")
|
originalActiveCfg := config.ActiveConfig()
|
||||||
defer teardown()
|
config.SetActiveConfig(&config.Config{
|
||||||
|
Flags: &config.Flags{
|
||||||
|
NetworkFlags: config.NetworkFlags{
|
||||||
|
ActiveNetParams: &dagconfig.SimnetParams},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
defer config.SetActiveConfig(originalActiveCfg)
|
||||||
|
|
||||||
type ipTest struct {
|
type ipTest struct {
|
||||||
in appmessage.NetAddress
|
in wire.NetAddress
|
||||||
rfc1918 bool
|
rfc1918 bool
|
||||||
rfc2544 bool
|
rfc2544 bool
|
||||||
rfc3849 bool
|
rfc3849 bool
|
||||||
@ -40,7 +50,7 @@ func TestIPTypes(t *testing.T) {
|
|||||||
rfc4193, rfc4380, rfc4843, rfc4862, rfc5737, rfc6052, rfc6145, rfc6598,
|
rfc4193, rfc4380, rfc4843, rfc4862, rfc5737, rfc6052, rfc6145, rfc6598,
|
||||||
local, valid, routable bool) ipTest {
|
local, valid, routable bool) ipTest {
|
||||||
nip := net.ParseIP(ip)
|
nip := net.ParseIP(ip)
|
||||||
na := *appmessage.NewNetAddressIPPort(nip, 16111)
|
na := *wire.NewNetAddressIPPort(nip, 16111, wire.SFNodeNetwork)
|
||||||
test := ipTest{na, rfc1918, rfc2544, rfc3849, rfc3927, rfc3964, rfc4193, rfc4380,
|
test := ipTest{na, rfc1918, rfc2544, rfc3849, rfc3927, rfc3964, rfc4193, rfc4380,
|
||||||
rfc4843, rfc4862, rfc5737, rfc6052, rfc6145, rfc6598, local, valid, routable}
|
rfc4843, rfc4862, rfc5737, rfc6052, rfc6145, rfc6598, local, valid, routable}
|
||||||
return test
|
return test
|
||||||
@ -89,55 +99,55 @@ func TestIPTypes(t *testing.T) {
|
|||||||
|
|
||||||
t.Logf("Running %d tests", len(tests))
|
t.Logf("Running %d tests", len(tests))
|
||||||
for _, test := range 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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
t.Errorf("IsRoutable %s\n got: %v want: %v", test.in.IP, rv, test.routable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,8 +156,14 @@ func TestIPTypes(t *testing.T) {
|
|||||||
// TestGroupKey tests the GroupKey function to ensure it properly groups various
|
// TestGroupKey tests the GroupKey function to ensure it properly groups various
|
||||||
// IP addresses.
|
// IP addresses.
|
||||||
func TestGroupKey(t *testing.T) {
|
func TestGroupKey(t *testing.T) {
|
||||||
amgr, teardown := newAddressManagerForTest(t, "TestAddAddressByIP")
|
originalActiveCfg := config.ActiveConfig()
|
||||||
defer teardown()
|
config.SetActiveConfig(&config.Config{
|
||||||
|
Flags: &config.Flags{
|
||||||
|
NetworkFlags: config.NetworkFlags{
|
||||||
|
ActiveNetParams: &dagconfig.SimnetParams},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
defer config.SetActiveConfig(originalActiveCfg)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@ -196,8 +212,8 @@ func TestGroupKey(t *testing.T) {
|
|||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
nip := net.ParseIP(test.ip)
|
nip := net.ParseIP(test.ip)
|
||||||
na := *appmessage.NewNetAddressIPPort(nip, 8333)
|
na := *wire.NewNetAddressIPPort(nip, 8333, wire.SFNodeNetwork)
|
||||||
if key := amgr.GroupKey(&na); key != test.expected {
|
if key := addrmgr.GroupKey(&na); key != test.expected {
|
||||||
t.Errorf("TestGroupKey #%d (%s): unexpected group key "+
|
t.Errorf("TestGroupKey #%d (%s): unexpected group key "+
|
||||||
"- got '%s', want '%s'", i, test.name,
|
"- got '%s', want '%s'", i, test.name,
|
||||||
key, test.expected)
|
key, test.expected)
|
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,
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// GetMempoolEntriesRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetMempoolEntriesRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
IncludeOrphanPool bool
|
|
||||||
FilterTransactionPool bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetMempoolEntriesRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdGetMempoolEntriesRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetMempoolEntriesRequestMessage returns a instance of the message
|
|
||||||
func NewGetMempoolEntriesRequestMessage(includeOrphanPool bool, filterTransactionPool bool) *GetMempoolEntriesRequestMessage {
|
|
||||||
return &GetMempoolEntriesRequestMessage{
|
|
||||||
IncludeOrphanPool: includeOrphanPool,
|
|
||||||
FilterTransactionPool: filterTransactionPool,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMempoolEntriesResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetMempoolEntriesResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Entries []*MempoolEntry
|
|
||||||
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetMempoolEntriesResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdGetMempoolEntriesResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetMempoolEntriesResponseMessage returns a instance of the message
|
|
||||||
func NewGetMempoolEntriesResponseMessage(entries []*MempoolEntry) *GetMempoolEntriesResponseMessage {
|
|
||||||
return &GetMempoolEntriesResponseMessage{
|
|
||||||
Entries: entries,
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// MempoolEntryByAddress represents MempoolEntries associated with some address
|
|
||||||
type MempoolEntryByAddress struct {
|
|
||||||
Address string
|
|
||||||
Receiving []*MempoolEntry
|
|
||||||
Sending []*MempoolEntry
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMempoolEntriesByAddressesRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetMempoolEntriesByAddressesRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Addresses []string
|
|
||||||
IncludeOrphanPool bool
|
|
||||||
FilterTransactionPool bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetMempoolEntriesByAddressesRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdGetMempoolEntriesByAddressesRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetMempoolEntriesByAddressesRequestMessage returns a instance of the message
|
|
||||||
func NewGetMempoolEntriesByAddressesRequestMessage(addresses []string, includeOrphanPool bool, filterTransactionPool bool) *GetMempoolEntriesByAddressesRequestMessage {
|
|
||||||
return &GetMempoolEntriesByAddressesRequestMessage{
|
|
||||||
Addresses: addresses,
|
|
||||||
IncludeOrphanPool: includeOrphanPool,
|
|
||||||
FilterTransactionPool: filterTransactionPool,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMempoolEntriesByAddressesResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetMempoolEntriesByAddressesResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Entries []*MempoolEntryByAddress
|
|
||||||
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetMempoolEntriesByAddressesResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdGetMempoolEntriesByAddressesResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetMempoolEntriesByAddressesResponseMessage returns a instance of the message
|
|
||||||
func NewGetMempoolEntriesByAddressesResponseMessage(entries []*MempoolEntryByAddress) *GetMempoolEntriesByAddressesResponseMessage {
|
|
||||||
return &GetMempoolEntriesByAddressesResponseMessage{
|
|
||||||
Entries: entries,
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// GetMempoolEntryRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetMempoolEntryRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
TxID string
|
|
||||||
IncludeOrphanPool bool
|
|
||||||
FilterTransactionPool bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetMempoolEntryRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdGetMempoolEntryRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetMempoolEntryRequestMessage returns a instance of the message
|
|
||||||
func NewGetMempoolEntryRequestMessage(txID string, includeOrphanPool bool, filterTransactionPool bool) *GetMempoolEntryRequestMessage {
|
|
||||||
return &GetMempoolEntryRequestMessage{
|
|
||||||
TxID: txID,
|
|
||||||
IncludeOrphanPool: includeOrphanPool,
|
|
||||||
FilterTransactionPool: filterTransactionPool,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetMempoolEntryResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetMempoolEntryResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Entry *MempoolEntry
|
|
||||||
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// MempoolEntry represents a transaction in the mempool.
|
|
||||||
type MempoolEntry struct {
|
|
||||||
Fee uint64
|
|
||||||
Transaction *RPCTransaction
|
|
||||||
IsOrphan bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetMempoolEntryResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdGetMempoolEntryResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetMempoolEntryResponseMessage returns a instance of the message
|
|
||||||
func NewGetMempoolEntryResponseMessage(fee uint64, transaction *RPCTransaction, isOrphan bool) *GetMempoolEntryResponseMessage {
|
|
||||||
return &GetMempoolEntryResponseMessage{
|
|
||||||
Entry: &MempoolEntry{
|
|
||||||
Fee: fee,
|
|
||||||
Transaction: transaction,
|
|
||||||
IsOrphan: isOrphan,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// GetPeerAddressesRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetPeerAddressesRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetPeerAddressesRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdGetPeerAddressesRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetPeerAddressesRequestMessage returns a instance of the message
|
|
||||||
func NewGetPeerAddressesRequestMessage() *GetPeerAddressesRequestMessage {
|
|
||||||
return &GetPeerAddressesRequestMessage{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPeerAddressesResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetPeerAddressesResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
Addresses []*GetPeerAddressesKnownAddressMessage
|
|
||||||
BannedAddresses []*GetPeerAddressesKnownAddressMessage
|
|
||||||
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetPeerAddressesResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdGetPeerAddressesResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetPeerAddressesResponseMessage returns a instance of the message
|
|
||||||
func NewGetPeerAddressesResponseMessage(addresses []*GetPeerAddressesKnownAddressMessage, bannedAddresses []*GetPeerAddressesKnownAddressMessage) *GetPeerAddressesResponseMessage {
|
|
||||||
return &GetPeerAddressesResponseMessage{
|
|
||||||
Addresses: addresses,
|
|
||||||
BannedAddresses: bannedAddresses,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetPeerAddressesKnownAddressMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetPeerAddressesKnownAddressMessage struct {
|
|
||||||
Addr string
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
package appmessage
|
|
||||||
|
|
||||||
// GetSelectedTipHashRequestMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetSelectedTipHashRequestMessage struct {
|
|
||||||
baseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetSelectedTipHashRequestMessage) Command() MessageCommand {
|
|
||||||
return CmdGetSelectedTipHashRequestMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetSelectedTipHashRequestMessage returns a instance of the message
|
|
||||||
func NewGetSelectedTipHashRequestMessage() *GetSelectedTipHashRequestMessage {
|
|
||||||
return &GetSelectedTipHashRequestMessage{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetSelectedTipHashResponseMessage is an appmessage corresponding to
|
|
||||||
// its respective RPC message
|
|
||||||
type GetSelectedTipHashResponseMessage struct {
|
|
||||||
baseMessage
|
|
||||||
SelectedTipHash string
|
|
||||||
|
|
||||||
Error *RPCError
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the protocol command string for the message
|
|
||||||
func (msg *GetSelectedTipHashResponseMessage) Command() MessageCommand {
|
|
||||||
return CmdGetSelectedTipHashResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewGetSelectedTipHashResponseMessage returns a instance of the message
|
|
||||||
func NewGetSelectedTipHashResponseMessage(selectedTipHash string) *GetSelectedTipHashResponseMessage {
|
|
||||||
return &GetSelectedTipHashResponseMessage{
|
|
||||||
SelectedTipHash: selectedTipHash,
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user