|
| 1 | +package protocol |
| 2 | + |
| 3 | +// Shapes only - constants & configs from hsd's protocol/networks.js. |
| 4 | + |
| 5 | +import ( |
| 6 | + "math/big" |
| 7 | + "sort" |
| 8 | + "strings" |
| 9 | + "sync" |
| 10 | + "time" |
| 11 | +) |
| 12 | + |
| 13 | +type NetworkType string |
| 14 | + |
| 15 | +const ( |
| 16 | + Mainnet NetworkType = "main" |
| 17 | + Testnet NetworkType = "testnet" |
| 18 | + Regtest NetworkType = "regtest" |
| 19 | + Simnet NetworkType = "simnet" |
| 20 | +) |
| 21 | + |
| 22 | +type TimeSource interface { |
| 23 | + Now() time.Time |
| 24 | + Ms() int64 |
| 25 | +} |
| 26 | + |
| 27 | +type systemTime struct{} |
| 28 | + |
| 29 | +func (t *systemTime) Now() time.Time { |
| 30 | + return time.Now() |
| 31 | +} |
| 32 | + |
| 33 | +func (t *systemTime) Ms() int64 { |
| 34 | + return time.Now().UnixMilli() |
| 35 | +} |
| 36 | + |
| 37 | +type Checkpoint struct { |
| 38 | + Height uint32 |
| 39 | + Hash string |
| 40 | +} |
| 41 | + |
| 42 | +type Deployment struct { |
| 43 | + Name string |
| 44 | + Bit uint32 |
| 45 | + StartTime uint32 |
| 46 | + Timeout uint32 |
| 47 | + Threshold int32 |
| 48 | + Window int32 |
| 49 | + Required bool |
| 50 | + Force bool |
| 51 | +} |
| 52 | + |
| 53 | +type KeyPrefix struct { |
| 54 | + Privkey uint32 |
| 55 | + XPubKey uint32 |
| 56 | + XPrivKey uint32 |
| 57 | + XPubKey58 string |
| 58 | + XPrivKey58 string |
| 59 | + CoinType uint32 |
| 60 | +} |
| 61 | + |
| 62 | +type POWParams struct { |
| 63 | + Limit *big.Int |
| 64 | + Bits uint32 |
| 65 | + Chainwork *big.Int |
| 66 | + TargetWindow uint32 |
| 67 | + TargetSpacing uint32 |
| 68 | + BlocksPerDay uint32 |
| 69 | + TargetTimespan uint32 |
| 70 | + MinActual uint32 |
| 71 | + MaxActual uint32 |
| 72 | + TargetReset bool |
| 73 | + NoRetargeting bool |
| 74 | +} |
| 75 | + |
| 76 | +type BlockLimits struct { |
| 77 | + PruneAfterHeight uint32 |
| 78 | + KeepBlocks uint32 |
| 79 | + MaxTipAge uint32 |
| 80 | + SlowHeight uint32 |
| 81 | +} |
| 82 | + |
| 83 | +type NamesParams struct { |
| 84 | + AuctionStart uint32 |
| 85 | + RolloutInterval uint32 |
| 86 | + LockupPeriod uint32 |
| 87 | + RenewalWindow uint32 |
| 88 | + RenewalPeriod uint32 |
| 89 | + RenewalMaturity uint32 |
| 90 | + ClaimPeriod uint32 |
| 91 | + AlexaLockupPeriod uint32 |
| 92 | + ClaimFrequency uint32 |
| 93 | + BiddingPeriod uint32 |
| 94 | + RevealPeriod uint32 |
| 95 | + TreeInterval uint32 |
| 96 | + TransferLockup uint32 |
| 97 | + AuctionMaturity uint32 |
| 98 | + NoRollout bool |
| 99 | + NoReserved bool |
| 100 | +} |
| 101 | + |
| 102 | +type Network struct { |
| 103 | + Type string |
| 104 | + Seeds []string |
| 105 | + Magic uint32 |
| 106 | + Port uint16 |
| 107 | + BrontidePort uint16 |
| 108 | + CheckpointMap map[uint32]string |
| 109 | + LastCheckpoint uint32 |
| 110 | + Checkpoints []Checkpoint |
| 111 | + |
| 112 | + HalvingInterval uint32 |
| 113 | + CoinbaseMaturity uint32 |
| 114 | + GenesisHash string |
| 115 | + GenesisBlockHex string |
| 116 | + UnknownBitsMask uint32 |
| 117 | + |
| 118 | + POW POWParams |
| 119 | + Names NamesParams |
| 120 | + GoosigStop uint32 |
| 121 | + Block BlockLimits |
| 122 | + |
| 123 | + ActivationThreshold uint32 |
| 124 | + MinerWindow uint32 |
| 125 | + |
| 126 | + Deployments map[string]Deployment |
| 127 | + Deploys []Deployment |
| 128 | + |
| 129 | + KeyPrefix KeyPrefix |
| 130 | + AddressPrefix string |
| 131 | + ClaimPrefix string |
| 132 | + |
| 133 | + RequireStandard bool |
| 134 | + MinRelay uint32 |
| 135 | + FeeRate uint32 |
| 136 | + MaxFeeRate uint32 |
| 137 | + |
| 138 | + RPCPort uint16 |
| 139 | + WalletPort uint16 |
| 140 | + NSPort uint16 |
| 141 | + RSPort uint16 |
| 142 | + |
| 143 | + IdentityKeyHex string |
| 144 | + SelfConnect bool |
| 145 | + RequestMempool bool |
| 146 | + |
| 147 | + DeflationHeight uint32 |
| 148 | + TxStartHeight uint32 |
| 149 | + timeSource TimeSource |
| 150 | + onceInit sync.Once |
| 151 | +} |
| 152 | + |
| 153 | +func (n *Network) init() { |
| 154 | + n.onceInit.Do(func() { |
| 155 | + if n.timeSource == nil { |
| 156 | + n.timeSource = &systemTime{} |
| 157 | + } |
| 158 | + var mask uint32 |
| 159 | + for _, d := range n.Deploys { |
| 160 | + if d.Bit < 32 { |
| 161 | + mask |= (1 << d.Bit) |
| 162 | + } |
| 163 | + } |
| 164 | + n.UnknownBitsMask = ^mask |
| 165 | + n.Checkpoints = n.checkpointsFromMap() |
| 166 | + sort.Slice(n.Checkpoints, func(i, j int) bool { |
| 167 | + return n.Checkpoints[i].Height < n.Checkpoints[j].Height |
| 168 | + }) |
| 169 | + }) |
| 170 | +} |
| 171 | + |
| 172 | +func (n *Network) checkpointsFromMap() []Checkpoint { |
| 173 | + if len(n.CheckpointMap) == 0 { |
| 174 | + return nil |
| 175 | + } |
| 176 | + out := make([]Checkpoint, 0, len(n.CheckpointMap)) |
| 177 | + for h, hash := range n.CheckpointMap { |
| 178 | + out = append(out, Checkpoint{Height: h, Hash: strings.ToLower(hash)}) |
| 179 | + } |
| 180 | + return out |
| 181 | +} |
| 182 | + |
| 183 | +func (n *Network) ByBit(bit uint32) *Deployment { |
| 184 | + for i := range n.Deploys { |
| 185 | + if n.Deploys[i].Bit == bit { |
| 186 | + return &n.Deploys[i] |
| 187 | + } |
| 188 | + } |
| 189 | + return nil |
| 190 | +} |
| 191 | + |
| 192 | +func (n *Network) ensureTime() { |
| 193 | + if n.timeSource == nil { |
| 194 | + n.timeSource = &systemTime{} |
| 195 | + } |
| 196 | +} |
| 197 | + |
| 198 | +func (n *Network) SetTimeSource(ts TimeSource) { |
| 199 | + n.timeSource = ts |
| 200 | +} |
| 201 | + |
| 202 | +func (n *Network) Now() time.Time { |
| 203 | + n.ensureTime() |
| 204 | + return n.timeSource.Now() |
| 205 | +} |
| 206 | + |
| 207 | +func (n *Network) Ms() int64 { |
| 208 | + n.ensureTime() |
| 209 | + return n.timeSource.Ms() |
| 210 | +} |
| 211 | + |
| 212 | +func bi(hex string) *big.Int { |
| 213 | + n := new(big.Int) |
| 214 | + if _, ok := n.SetString(hex, 16); !ok { |
| 215 | + panic("invalid hex for big.Int: " + hex) |
| 216 | + } |
| 217 | + return n |
| 218 | +} |
| 219 | + |
| 220 | +var Networks = map[NetworkType]*Network{ |
| 221 | + Mainnet: mainNet(), |
| 222 | + Testnet: testNet(), |
| 223 | + Regtest: regTest(), |
| 224 | + Simnet: simNet(), |
| 225 | +} |
| 226 | + |
| 227 | +func SelectNetwork(t NetworkType) *Network { |
| 228 | + return Networks[t] |
| 229 | +} |
| 230 | + |
| 231 | +func testNet() *Network { |
| 232 | + const ( |
| 233 | + targetSpacing = uint32(10 * 60) |
| 234 | + targetWindow = uint32(144) |
| 235 | + ) |
| 236 | + blocksPerDay := uint32((24 * 60 * 60) / targetSpacing) |
| 237 | + targetTimespan := targetWindow * targetSpacing |
| 238 | + |
| 239 | + n := &Network{ |
| 240 | + Type: "testnet", |
| 241 | + Seeds: []string{"hs-testnet.bcoin.ninja"}, |
| 242 | + Magic: 0, // Need to modify from genesis.testnet.magic |
| 243 | + Port: 13038, |
| 244 | + BrontidePort: 45806, |
| 245 | + |
| 246 | + CheckpointMap: map[uint32]string{}, |
| 247 | + LastCheckpoint: 0, |
| 248 | + |
| 249 | + HalvingInterval: 170000, |
| 250 | + CoinbaseMaturity: 100, |
| 251 | + |
| 252 | + POW: POWParams{ |
| 253 | + Limit: bi("00000000ffff0000000000000000000000000000000000000000000000000000"), |
| 254 | + Bits: 0x1d00ffff, |
| 255 | + Chainwork: bi("0000000000000000000000000000000000000000000000000000000000000000"), |
| 256 | + TargetWindow: targetWindow, |
| 257 | + TargetSpacing: targetSpacing, |
| 258 | + BlocksPerDay: blocksPerDay, |
| 259 | + TargetTimespan: targetTimespan, |
| 260 | + MinActual: targetTimespan / 4, |
| 261 | + MaxActual: targetTimespan * 4, |
| 262 | + TargetReset: true, |
| 263 | + NoRetargeting: false, |
| 264 | + }, |
| 265 | + |
| 266 | + Names: NamesParams{ |
| 267 | + AuctionStart: uint32(0.25 * float32(blocksPerDay)), |
| 268 | + RolloutInterval: uint32(0.25 * float32(blocksPerDay)), |
| 269 | + LockupPeriod: uint32(0.25 * float32(blocksPerDay)), |
| 270 | + RenewalWindow: 30 * blocksPerDay, |
| 271 | + RenewalPeriod: 7 * blocksPerDay, |
| 272 | + RenewalMaturity: 1 * blocksPerDay, |
| 273 | + ClaimPeriod: 90 * blocksPerDay, |
| 274 | + AlexaLockupPeriod: 180 * blocksPerDay, |
| 275 | + ClaimFrequency: 2 * blocksPerDay, |
| 276 | + BiddingPeriod: 1 * blocksPerDay, |
| 277 | + RevealPeriod: 2 * blocksPerDay, |
| 278 | + TreeInterval: blocksPerDay >> 2, |
| 279 | + TransferLockup: 2 * blocksPerDay, |
| 280 | + AuctionMaturity: (1 + 2 + 4) * blocksPerDay, |
| 281 | + NoRollout: false, |
| 282 | + NoReserved: false, |
| 283 | + }, |
| 284 | + |
| 285 | + Block: BlockLimits{ |
| 286 | + PruneAfterHeight: 1000, |
| 287 | + KeepBlocks: 10000, |
| 288 | + MaxTipAge: 12 * 60 * 60, |
| 289 | + SlowHeight: 0, |
| 290 | + }, |
| 291 | + |
| 292 | + GoosigStop: 20 * blocksPerDay, |
| 293 | + ActivationThreshold: 1512, |
| 294 | + MinerWindow: 2016, |
| 295 | + |
| 296 | + Deployments: map[string]Deployment{ |
| 297 | + "hardening": {Name: "hardening", Bit: 0, StartTime: 1581638400, Timeout: 1707868800, Threshold: -1, Window: -1, Required: false, Force: false}, |
| 298 | + "icannlockup": {Name: "icannlockup", Bit: 1, StartTime: 1691625600, Timeout: 1703980800, Threshold: -1, Window: -1, Required: false, Force: false}, |
| 299 | + "airstop": {Name: "airstop", Bit: 2, StartTime: 1751328000, Timeout: 1759881600, Threshold: -1, Window: -1, Required: false, Force: false}, |
| 300 | + "testdummy": {Name: "testdummy", Bit: 28, StartTime: 1199145601, Timeout: 1230767999, Threshold: -1, Window: -1, Required: false, Force: true}, |
| 301 | + }, |
| 302 | + Deploys: []Deployment{ |
| 303 | + {Name: "hardening", Bit: 0, StartTime: 1581638400, Timeout: 1707868800, Threshold: -1, Window: -1, Required: false, Force: false}, |
| 304 | + {Name: "icannlockup", Bit: 1, StartTime: 1691625600, Timeout: 1703980800, Threshold: -1, Window: -1, Required: false, Force: false}, |
| 305 | + {Name: "airstop", Bit: 2, StartTime: 1751328000, Timeout: 1759881600, Threshold: -1, Window: -1, Required: false, Force: false}, |
| 306 | + {Name: "testdummy", Bit: 28, StartTime: 1199145601, Timeout: 1230767999, Threshold: -1, Window: -1, Required: false, Force: true}, |
| 307 | + }, |
| 308 | + |
| 309 | + KeyPrefix: KeyPrefix{ |
| 310 | + Privkey: 0xef, |
| 311 | + XPubKey: 0x043587cf, |
| 312 | + XPrivKey: 0x04358394, |
| 313 | + XPubKey58: "tpub", |
| 314 | + XPrivKey58: "tprv", |
| 315 | + CoinType: 5354, |
| 316 | + }, |
| 317 | + AddressPrefix: "ts", |
| 318 | + ClaimPrefix: "hns-testnet:", |
| 319 | + RequireStandard: false, |
| 320 | + |
| 321 | + RPCPort: 13037, |
| 322 | + WalletPort: 13039, |
| 323 | + NSPort: 15349, |
| 324 | + RSPort: 15350, |
| 325 | + |
| 326 | + MinRelay: 1000, |
| 327 | + FeeRate: 20000, |
| 328 | + MaxFeeRate: 60000, |
| 329 | + |
| 330 | + IdentityKeyHex: "", |
| 331 | + SelfConnect: false, |
| 332 | + RequestMempool: true, |
| 333 | + |
| 334 | + DeflationHeight: 0, |
| 335 | + TxStartHeight: 0, |
| 336 | + } |
| 337 | + n.ensureTime() |
| 338 | + n.init() |
| 339 | + return n |
| 340 | +} |
| 341 | + |
| 342 | +func mainNet() *Network { |
| 343 | + // Need to implement |
| 344 | + return &Network{} |
| 345 | +} |
| 346 | + |
| 347 | +func regTest() *Network { |
| 348 | + // Need to implement |
| 349 | + return &Network{} |
| 350 | +} |
| 351 | + |
| 352 | +func simNet() *Network { |
| 353 | + // Need to implement |
| 354 | + return &Network{} |
| 355 | +} |
0 commit comments