Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
355 changes: 355 additions & 0 deletions internal/handshake/protocol/network.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,355 @@
package protocol

// Shapes only - constants & configs from hsd's protocol/networks.js.

import (
"math/big"
"sort"
"strings"
"sync"
"time"
)

type NetworkType string

const (
Mainnet NetworkType = "main"
Testnet NetworkType = "testnet"
Regtest NetworkType = "regtest"
Simnet NetworkType = "simnet"
)

type TimeSource interface {
Now() time.Time
Ms() int64
}

type systemTime struct{}

func (t *systemTime) Now() time.Time {
return time.Now()
}

func (t *systemTime) Ms() int64 {
return time.Now().UnixMilli()
}

type Checkpoint struct {
Height uint32
Hash string
}

type Deployment struct {
Name string
Bit uint32
StartTime uint32
Timeout uint32
Threshold int32
Window int32
Required bool
Force bool
}

type KeyPrefix struct {
Privkey uint32
XPubKey uint32
XPrivKey uint32
XPubKey58 string
XPrivKey58 string
CoinType uint32
}

type POWParams struct {
Limit *big.Int
Bits uint32
Chainwork *big.Int
TargetWindow uint32
TargetSpacing uint32
BlocksPerDay uint32
TargetTimespan uint32
MinActual uint32
MaxActual uint32
TargetReset bool
NoRetargeting bool
}

type BlockLimits struct {
PruneAfterHeight uint32
KeepBlocks uint32
MaxTipAge uint32
SlowHeight uint32
}

type NamesParams struct {
AuctionStart uint32
RolloutInterval uint32
LockupPeriod uint32
RenewalWindow uint32
RenewalPeriod uint32
RenewalMaturity uint32
ClaimPeriod uint32
AlexaLockupPeriod uint32
ClaimFrequency uint32
BiddingPeriod uint32
RevealPeriod uint32
TreeInterval uint32
TransferLockup uint32
AuctionMaturity uint32
NoRollout bool
NoReserved bool
}

type Network struct {
Type string
Seeds []string
Magic uint32
Port uint16
BrontidePort uint16
CheckpointMap map[uint32]string
LastCheckpoint uint32
Checkpoints []Checkpoint

HalvingInterval uint32
CoinbaseMaturity uint32
GenesisHash string
GenesisBlockHex string
UnknownBitsMask uint32

POW POWParams
Names NamesParams
GoosigStop uint32
Block BlockLimits

ActivationThreshold uint32
MinerWindow uint32

Deployments map[string]Deployment
Deploys []Deployment

KeyPrefix KeyPrefix
AddressPrefix string
ClaimPrefix string

RequireStandard bool
MinRelay uint32
FeeRate uint32
MaxFeeRate uint32

RPCPort uint16
WalletPort uint16
NSPort uint16
RSPort uint16

IdentityKeyHex string
SelfConnect bool
RequestMempool bool

DeflationHeight uint32
TxStartHeight uint32
timeSource TimeSource
onceInit sync.Once
}

func (n *Network) init() {
n.onceInit.Do(func() {
if n.timeSource == nil {
n.timeSource = &systemTime{}
}
var mask uint32
for _, d := range n.Deploys {
if d.Bit < 32 {
mask |= (1 << d.Bit)
}
}
n.UnknownBitsMask = ^mask
n.Checkpoints = n.checkpointsFromMap()
sort.Slice(n.Checkpoints, func(i, j int) bool {
return n.Checkpoints[i].Height < n.Checkpoints[j].Height
})
})
}

func (n *Network) checkpointsFromMap() []Checkpoint {
if len(n.CheckpointMap) == 0 {
return nil
}
out := make([]Checkpoint, 0, len(n.CheckpointMap))
for h, hash := range n.CheckpointMap {
out = append(out, Checkpoint{Height: h, Hash: strings.ToLower(hash)})
}
return out
}

func (n *Network) ByBit(bit uint32) *Deployment {
for i := range n.Deploys {
if n.Deploys[i].Bit == bit {
return &n.Deploys[i]
}
}
return nil
}

func (n *Network) ensureTime() {
if n.timeSource == nil {
n.timeSource = &systemTime{}
}
}

func (n *Network) SetTimeSource(ts TimeSource) {
n.timeSource = ts
}

func (n *Network) Now() time.Time {
n.ensureTime()
return n.timeSource.Now()
}

func (n *Network) Ms() int64 {
n.ensureTime()
return n.timeSource.Ms()
}

func bi(hex string) *big.Int {
n := new(big.Int)
if _, ok := n.SetString(hex, 16); !ok {
panic("invalid hex for big.Int: " + hex)
}
return n
}

var Networks = map[NetworkType]*Network{
Mainnet: mainNet(),
Testnet: testNet(),
Regtest: regTest(),
Simnet: simNet(),
}

func SelectNetwork(t NetworkType) *Network {
return Networks[t]
}

func testNet() *Network {
const (
targetSpacing = uint32(10 * 60)
targetWindow = uint32(144)
)
blocksPerDay := uint32((24 * 60 * 60) / targetSpacing)
targetTimespan := targetWindow * targetSpacing

n := &Network{
Type: "testnet",
Seeds: []string{"hs-testnet.bcoin.ninja"},
Magic: 0, // Need to modify from genesis.testnet.magic
Port: 13038,
BrontidePort: 45806,

CheckpointMap: map[uint32]string{},
LastCheckpoint: 0,

HalvingInterval: 170000,
CoinbaseMaturity: 100,

POW: POWParams{
Limit: bi("00000000ffff0000000000000000000000000000000000000000000000000000"),
Bits: 0x1d00ffff,
Chainwork: bi("0000000000000000000000000000000000000000000000000000000000000000"),
TargetWindow: targetWindow,
TargetSpacing: targetSpacing,
BlocksPerDay: blocksPerDay,
TargetTimespan: targetTimespan,
MinActual: targetTimespan / 4,
MaxActual: targetTimespan * 4,
TargetReset: true,
NoRetargeting: false,
},

Names: NamesParams{
AuctionStart: uint32(0.25 * float32(blocksPerDay)),
RolloutInterval: uint32(0.25 * float32(blocksPerDay)),
LockupPeriod: uint32(0.25 * float32(blocksPerDay)),
RenewalWindow: 30 * blocksPerDay,
RenewalPeriod: 7 * blocksPerDay,
RenewalMaturity: 1 * blocksPerDay,
ClaimPeriod: 90 * blocksPerDay,
AlexaLockupPeriod: 180 * blocksPerDay,
ClaimFrequency: 2 * blocksPerDay,
BiddingPeriod: 1 * blocksPerDay,
RevealPeriod: 2 * blocksPerDay,
TreeInterval: blocksPerDay >> 2,
TransferLockup: 2 * blocksPerDay,
AuctionMaturity: (1 + 2 + 4) * blocksPerDay,
NoRollout: false,
NoReserved: false,
},

Block: BlockLimits{
PruneAfterHeight: 1000,
KeepBlocks: 10000,
MaxTipAge: 12 * 60 * 60,
SlowHeight: 0,
},

GoosigStop: 20 * blocksPerDay,
ActivationThreshold: 1512,
MinerWindow: 2016,

Deployments: map[string]Deployment{
"hardening": {Name: "hardening", Bit: 0, StartTime: 1581638400, Timeout: 1707868800, Threshold: -1, Window: -1, Required: false, Force: false},
"icannlockup": {Name: "icannlockup", Bit: 1, StartTime: 1691625600, Timeout: 1703980800, Threshold: -1, Window: -1, Required: false, Force: false},
"airstop": {Name: "airstop", Bit: 2, StartTime: 1751328000, Timeout: 1759881600, Threshold: -1, Window: -1, Required: false, Force: false},
"testdummy": {Name: "testdummy", Bit: 28, StartTime: 1199145601, Timeout: 1230767999, Threshold: -1, Window: -1, Required: false, Force: true},
},
Deploys: []Deployment{
{Name: "hardening", Bit: 0, StartTime: 1581638400, Timeout: 1707868800, Threshold: -1, Window: -1, Required: false, Force: false},
{Name: "icannlockup", Bit: 1, StartTime: 1691625600, Timeout: 1703980800, Threshold: -1, Window: -1, Required: false, Force: false},
{Name: "airstop", Bit: 2, StartTime: 1751328000, Timeout: 1759881600, Threshold: -1, Window: -1, Required: false, Force: false},
{Name: "testdummy", Bit: 28, StartTime: 1199145601, Timeout: 1230767999, Threshold: -1, Window: -1, Required: false, Force: true},
},

KeyPrefix: KeyPrefix{
Privkey: 0xef,
XPubKey: 0x043587cf,
XPrivKey: 0x04358394,
XPubKey58: "tpub",
XPrivKey58: "tprv",
CoinType: 5354,
},
AddressPrefix: "ts",
ClaimPrefix: "hns-testnet:",
RequireStandard: false,

RPCPort: 13037,
WalletPort: 13039,
NSPort: 15349,
RSPort: 15350,

MinRelay: 1000,
FeeRate: 20000,
MaxFeeRate: 60000,

IdentityKeyHex: "",
SelfConnect: false,
RequestMempool: true,

DeflationHeight: 0,
TxStartHeight: 0,
}
n.ensureTime()
n.init()
return n
}

func mainNet() *Network {
// Need to implement
return &Network{}
}

func regTest() *Network {
// Need to implement
return &Network{}
}

func simNet() *Network {
// Need to implement
return &Network{}
}