diff --git a/internal/handshake/protocol/genesis/genesis-data.json b/internal/handshake/protocol/genesis/genesis-data.json new file mode 100644 index 0000000..17474ce --- /dev/null +++ b/internal/handshake/protocol/genesis/genesis-data.json @@ -0,0 +1,20 @@ +{ + "main": { + "version": 0, + "hash": "5b6ef2d3c1f3cdcadfd9a030ba1811efdd17740f14e166489760741d075992e0", + "prev_block": "0000000000000000000000000000000000000000000000000000000000000000", + "merkle_root": "8e4c9756fef2ad10375f360e0560fcc7587eb5223ddf8cd7c7e06e60a1140b15", + "witness_root": "1a2c60b9439206938f8d7823782abdb8b211a57431e9c9b6a6365d8d42893351", + "tree_root": "0000000000000000000000000000000000000000000000000000000000000000", + "reserved_root": "0000000000000000000000000000000000000000000000000000000000000000", + "time": 1580745078, + "bits": "0x1c00ffff", + "nonce": 0, + "mask": "0000000000000000000000000000000000000000000000000000000000000000", + "extra_nonce": "000000000000000000000000000000000000000000000000", + "height": 0, + "magic": 1533997779, + "data_b64": "AAAAAHZBOF4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGixguUOSBpOPjXgjeCq9uLIRpXQx6cm2pjZdjUKJM1GOTJdW/vKtEDdfNg4FYPzHWH61Ij3fjNfH4G5goRQLFQAAAAD//wAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AdBMV3cAAAAAABTwI3ri6Phg99eRJPxRPwEuWqqNIwAAAAAAAAQgULiTf8Xe8I+fPL2n5fCMcG7bgKuliAwAAAAAAAAAAAAgLV3lhgnUlw+1SPha0HqH20DgVONMyByVHKmVpY9nTbcgENdI7aG5xnuU0yROAhFndhiptLMp6JatkEMfn0gDS60g4sApmh5GZ3NRZlXwmmSx4WsleVMN5sSlnOVlTepFGA8=" + } + } + \ No newline at end of file diff --git a/internal/handshake/protocol/genesis/genesis.go b/internal/handshake/protocol/genesis/genesis.go new file mode 100644 index 0000000..028f080 --- /dev/null +++ b/internal/handshake/protocol/genesis/genesis.go @@ -0,0 +1,94 @@ +package genesis + +import ( + "encoding/json" + "strconv" + "strings" +) + +var raw []byte + +var ( + Main Net + Maindata string +) + +type netDisk struct { + Version uint32 `json:"version"` + Hash string `json:"hash"` + PrevBlock string `json:"prev_block"` + MerkleRoot string `json:"merkle_root"` + WitnessRoot string `json:"witness_root"` + TreeRoot string `json:"tree_root"` + ReservedRoot string `json:"reserved_root"` + Time uint32 `json:"time"` + Bits string `json:"bits"` + Nonce uint32 `json:"nonce"` + Mask string `json:"mask"` + ExtraNonce string `json:"extra_nonce"` + Height uint32 `json:"height"` + Magic uint32 `json:"magic"` + DataB64 string `json:"data_b64"` +} + +type disk struct { + Main netDisk `json:"main"` +} + +// Net holds the parsed genesis info for a network. +type Net struct { + Version uint32 + Hash string + PrevBlock string + MerkleRoot string + WitnessRoot string + TreeRoot string + ReservedRoot string + Time uint32 + Bits uint32 + Nonce uint32 + Mask string + ExtraNonce string + Height uint32 + Magic uint32 + DataB64 string +} + +func mustParseBits(s string) uint32 { + if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") { + v, err := strconv.ParseUint(s[2:], 16, 32) + if err != nil { + panic("genesis: invalid hex bits: " + s) + } + return uint32(v) + } + v, err := strconv.ParseUint(s, 10, 32) + if err != nil { + panic("genesis: invalid decimal bits: " + s) + } + return uint32(v) +} + +func init() { + var d disk + if err := json.Unmarshal(raw, &d); err != nil { + panic("genesis: invalid embedded JSON: " + err.Error()) + } + Main = Net{ + Version: d.Main.Version, + Hash: strings.ToLower(d.Main.Hash), + PrevBlock: strings.ToLower(d.Main.PrevBlock), + MerkleRoot: strings.ToLower(d.Main.MerkleRoot), + WitnessRoot: strings.ToLower(d.Main.WitnessRoot), + TreeRoot: strings.ToLower(d.Main.TreeRoot), + ReservedRoot: strings.ToLower(d.Main.ReservedRoot), + Time: d.Main.Time, + Bits: mustParseBits(d.Main.Bits), + Nonce: d.Main.Nonce, + Mask: strings.ToLower(d.Main.Mask), + ExtraNonce: strings.ToLower(d.Main.ExtraNonce), + Height: d.Main.Height, + Magic: d.Main.Magic, + } + Maindata = d.Main.DataB64 +} diff --git a/internal/handshake/protocol/network.go b/internal/handshake/protocol/network.go index bf974e1..9d03c51 100644 --- a/internal/handshake/protocol/network.go +++ b/internal/handshake/protocol/network.go @@ -8,6 +8,8 @@ import ( "strings" "sync" "time" + + gen "github.com/blinklabs-io/cdnsd/internal/handshake/protocol/genesis" ) type NetworkType string @@ -111,8 +113,8 @@ type Network struct { HalvingInterval uint32 CoinbaseMaturity uint32 - GenesisHash string - GenesisBlockHex string + Genesis gen.Net + GenesisBlock string UnknownBitsMask uint32 POW POWParams @@ -237,9 +239,12 @@ func testNet() *Network { targetTimespan := targetWindow * targetSpacing n := &Network{ - Type: "testnet", - Seeds: []string{"hs-testnet.bcoin.ninja"}, - Magic: 0, // Need to modify from genesis.testnet.magic + Type: "testnet", + Seeds: []string{"hs-testnet.bcoin.ninja"}, + Magic: 2974944722, // Need to modify from genesis.testnet.magic + + // TODO: Need to implement Genesis & GenesisBlock in genesis.go & import here. + // Genesis: "b1520dd24372f82ec94ebf8cf9d9b037d419c4aa3575d05dec70aedd1b427901", Port: 13038, BrontidePort: 45806, @@ -340,8 +345,132 @@ func testNet() *Network { } func mainNet() *Network { - // Need to implement - return &Network{} + const ( + targetSpacing = uint32(10 * 60) // 10 minutes + targetWindow = uint32(144) + ) + blocksPerDay := uint32((24 * 60 * 60) / targetSpacing) + targetTimespan := targetWindow * targetSpacing + + n := &Network{ + Type: "main", + Seeds: []string{"hs-mainnet.bcoin.ninja", "seed.htools.work"}, + Magic: gen.Main.Magic, + Genesis: gen.Main, + GenesisBlock: gen.Maindata, + Port: 12038, + BrontidePort: 44806, + + CheckpointMap: map[uint32]string{ + 1008: "0000000000001013c28fa079b545fb805f04c496687799b98e35e83cbbb8953e", + 2016: "0000000000000424ee6c2a5d6e0da5edfc47a4a10328c1792056ee48303c3e40", + 10000: "00000000000001a86811a6f520bf67cefa03207dc84fd315f58153b28694ec51", + 20000: "0000000000000162c7ac70a582256f59c189b5c90d8e9861b3f374ed714c58de", + 30000: "0000000000000004f790862846b23c3a81585aea0fa79a7d851b409e027bcaa7", + 40000: "0000000000000002966206a40b10a575cb46531253b08dae8e1b356cfa277248", + 50000: "00000000000000020c7447e7139feeb90549bfc77a7f18d4ff28f327c04f8d6e", + 56880: "0000000000000001d4ef9ea6908bb4eb970d556bd07cbd7d06a634e1cd5bbf4e", + 61043: "00000000000000015b84385e0307370f8323420eaa27ef6e407f2d3162f1fd05", + 100000: "000000000000000136d7d3efa688072f40d9fdd71bd47bb961694c0f38950246", + 130000: "0000000000000005ee5106df9e48bcd232a1917684ac344b35ddd9b9e4101096", + 160000: "00000000000000021e723ce5aedc021ab4f85d46a6914e40148f01986baa46c9", + 200000: "000000000000000181ebc18d6c34442ffef3eedca90c57ca8ecc29016a1cfe16", + 225000: "00000000000000021f0be013ebad018a9ef97c8501766632f017a778781320d5", + 258026: "0000000000000004963d20732c58e5a91cb7e1b61ec6709d031f1a5ca8c55b95", + }, + LastCheckpoint: 258026, + + HalvingInterval: 170000, + CoinbaseMaturity: 100, + + POW: POWParams{ + Limit: bi("0000000000ffff00000000000000000000000000000000000000000000000000"), + Bits: 0x1c00ffff, + Chainwork: bi("00000000000000000000000000000000000000000000000075b5a2b7bf522d45"), + TargetWindow: targetWindow, + TargetSpacing: targetSpacing, + BlocksPerDay: blocksPerDay, + TargetTimespan: targetTimespan, + MinActual: targetTimespan / 4, + MaxActual: targetTimespan * 4, + TargetReset: false, + NoRetargeting: false, + }, + + Names: NamesParams{ + AuctionStart: 14 * blocksPerDay, + RolloutInterval: 7 * blocksPerDay, + LockupPeriod: 30 * blocksPerDay, + RenewalWindow: (2 * 365) * blocksPerDay, + RenewalPeriod: 182 * blocksPerDay, + RenewalMaturity: 30 * blocksPerDay, + ClaimPeriod: (4 * 365) * blocksPerDay, + AlexaLockupPeriod: (8 * 365) * blocksPerDay, + ClaimFrequency: 2 * blocksPerDay, + BiddingPeriod: 5 * blocksPerDay, + RevealPeriod: 10 * blocksPerDay, + TreeInterval: blocksPerDay >> 2, + TransferLockup: 2 * blocksPerDay, + AuctionMaturity: (5 + 10 + 14) * blocksPerDay, + NoRollout: false, + NoReserved: false, + }, + + Block: BlockLimits{ + PruneAfterHeight: 1000, + KeepBlocks: 288, + MaxTipAge: 12 * 60 * 60, + SlowHeight: 0, + }, + + GoosigStop: (365 + 30) * blocksPerDay, + ActivationThreshold: 1916, + 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: 0x80, + XPubKey: 0x0488b21e, + XPrivKey: 0x0488ade4, + XPubKey58: "xpub", + XPrivKey58: "xprv", + CoinType: 5353, + }, + AddressPrefix: "hs", + ClaimPrefix: "hns-claim:", + RequireStandard: true, + + RPCPort: 12037, + WalletPort: 12039, + NSPort: 5349, + RSPort: 5350, + + MinRelay: 1000, + FeeRate: 100000, + MaxFeeRate: 400000, + + IdentityKeyHex: "", + SelfConnect: false, + RequestMempool: true, + + DeflationHeight: 61043, + TxStartHeight: 14 * blocksPerDay, + } + n.ensureTime() + n.init() + return n } func regTest() *Network {