github.com/deso-protocol/core@v1.2.9/lib/constants.go (about) 1 package lib 2 3 import ( 4 "encoding/hex" 5 "fmt" 6 "log" 7 "math/big" 8 "os" 9 "path/filepath" 10 "regexp" 11 "time" 12 13 "github.com/btcsuite/btcd/chaincfg" 14 "github.com/btcsuite/btcd/chaincfg/chainhash" 15 "github.com/golang/glog" 16 "github.com/shibukawa/configdir" 17 ) 18 19 const ( 20 // ConfigDirVendorName is the enclosing folder for user data. 21 // It's required to created a ConfigDir. 22 ConfigDirVendorName = "deso" 23 // ConfigDirAppName is the folder where we keep user data. 24 ConfigDirAppName = "deso" 25 // UseridLengthBytes is the number of bytes of entropy to use for 26 // a userid. 27 UseridLengthBytes = 32 28 29 // These constants are used by the DNS seed code to pick a random last 30 // seen time. 31 SecondsIn3Days int32 = 24 * 60 * 60 * 3 32 SecondsIn4Days int32 = 24 * 60 * 60 * 4 33 34 // MessagesToFetchPerCall is used to limit the number of messages to fetch 35 // when getting a user's inbox. 36 MessagesToFetchPerInboxCall = 10000 37 ) 38 39 type NetworkType uint64 40 41 const ( 42 // The different network types. For now we have a mainnet and a testnet. 43 // Also create an UNSET value to catch errors. 44 NetworkType_UNSET NetworkType = 0 45 NetworkType_MAINNET NetworkType = 1 46 NetworkType_TESTNET NetworkType = 2 47 ) 48 49 const ( 50 // This is the header version that the blockchain started with. 51 HeaderVersion0 = uint32(0) 52 // This version made several changes to the previous header encoding format: 53 // - The Nonce field was expanded to 64 bits 54 // - Another ExtraNonce field was added to provide *another* 64 bits of entropy, 55 // for a total of 128 bits of entropy in the header that miners can twiddle. 56 // - The header height was expanded to 64 bits 57 // - The TstampSecs were expanded to 64 bits 58 // - All fields were moved from encoding in little-endian to big-endian 59 // 60 // The benefit of this change is that miners can hash over a wider space without 61 // needing to twiddle ExtraData ever. 62 // 63 // At the time of this writing, the intent is to deploy it in a backwards-compatible 64 // fashion, with the eventual goal of phasing out blocks with the previous version. 65 HeaderVersion1 = uint32(1) 66 CurrentHeaderVersion = HeaderVersion1 67 ) 68 69 var ( 70 // The block height at which various forks occurred including an 71 // explanation as to why they're necessary. 72 73 // SalomonFixBlockHeight defines a block height where the protocol implements 74 // two changes: 75 // (1) The protocol now prints founder reward for all buy transactions instead 76 // of just when creators reach a new all time high. 77 // This was decided in order to provide lasting incentive for creators 78 // to utilize the protocol. 79 // (2) A fix was created to deal with a bug accidentally triggered by @salomon. 80 // After a series of buys and sells @salomon was left with a single creator coin 81 // nano in circulation and a single DeSo nano locked. This caused a detach 82 // between @salomon's bonding curve and others on the protocol. As more buys and sells 83 // continued, @salomon's bonding curve continued to detach further and further from its peers. 84 // At its core, @salomon had too few creator coins in circulation. This fix introduces 85 // this missing supply back into circulation as well as prevented detached Bancor bonding 86 // curves from coming into existence. 87 // ^ It was later decided to leave Salomon's coin circulation alone. A fix was introduced 88 // to prevent similar cases from occurring again, but @salomon is left alone. 89 SalomonFixBlockHeight = uint32(15270) 90 91 // DeSoFounderRewardBlockHeight defines a block height where the protocol switches from 92 // paying the founder reward in the founder's own creator coin to paying in DeSo instead. 93 DeSoFounderRewardBlockHeight = uint32(21869) 94 95 // BuyCreatorCoinAfterDeletedBalanceEntryFixBlockHeight defines a block height after which the protocol will create 96 // a new BalanceEntry when a user purchases a Creator Coin and their current BalanceEntry is deleted. 97 // The situation in which a BalanceEntry reaches a deleted state occurs when a user transfers all their holdings 98 // of a certain creator to another public key and subsequently purchases that same creator within the same block. 99 // This resolves a bug in which users would purchase creator coins after transferring all holdings within the same 100 // block and then the creator coins would be added to a deleted balance. When the Balance Entries are flushed to 101 // the database, the user would lose the creator coins they purchased. 102 BuyCreatorCoinAfterDeletedBalanceEntryFixBlockHeight = uint32(39713) 103 104 // ParamUpdaterProfileUpdateFixBlockHeight defines a block height after which the protocol uses the update profile 105 // txMeta's ProfilePublicKey when the Param Updater is creating a profile for ProfilePublicKey. 106 ParamUpdaterProfileUpdateFixBlockHeight = uint32(39713) 107 108 // UpdateProfileFixBlockHeight defines the height at which a patch was added to prevent user from 109 // updating the profile entry for arbitrary public keys that do not have existing profile entries. 110 UpdateProfileFixBlockHeight = uint32(46165) 111 112 // BrokenNFTBidsFixBlockHeight defines the height at which the deso balance index takes effect 113 // for accepting NFT bids. This is used to fix a fork that was created by nodes running with a corrupted 114 // deso balance index, allowing bids to be submitted that were greater than the user's deso balance. 115 BrokenNFTBidsFixBlockHeight = uint32(46917) 116 117 // DeSoDiamondsBlockHeight defines the height at which diamonds will be given in DESO 118 // rather than in creator coin. 119 // Triggers: 3pm PT on 8/16/2021 120 DeSoDiamondsBlockHeight = uint32(52112) 121 122 // NFTTransfersBlockHeight defines the height at which NFT transfer txns, accept NFT 123 // transfer txns, NFT burn txns, and AuthorizeDerivedKey txns will be accepted. 124 // Triggers: 12PM PT on 9/15/2021 125 NFTTransferOrBurnAndDerivedKeysBlockHeight = uint32(60743) 126 ) 127 128 func (nt NetworkType) String() string { 129 switch nt { 130 case NetworkType_UNSET: 131 return "UNSET" 132 case NetworkType_MAINNET: 133 return "MAINNET" 134 case NetworkType_TESTNET: 135 return "TESTNET" 136 default: 137 return fmt.Sprintf("UNRECOGNIZED(%d) - make sure String() is up to date", nt) 138 } 139 } 140 141 const ( 142 MaxUsernameLengthBytes = 25 143 ) 144 145 var ( 146 UsernameRegex = regexp.MustCompile("^[a-zA-Z0-9_]+$") 147 // Profile pics are Base64 encoded plus ": ; ," used in the mime type spec. 148 ProfilePicRegex = regexp.MustCompile("^[a-zA-Z0-9+/:;,]+$") 149 150 TikTokShortURLRegex = regexp.MustCompile("^.*(vm\\.tiktok\\.com/)([A-Za-z0-9]{6,12}).*") 151 TikTokFullURLRegex = regexp.MustCompile("^.*((tiktok\\.com/)(v/)|(@[A-Za-z0-9_-]{2,24}/video/)|(embed/v2/))(\\d{0,30}).*") 152 ) 153 154 // DeSoParams defines the full list of possible parameters for the 155 // DeSo network. 156 type DeSoParams struct { 157 // The network type (mainnet, testnet, etc). 158 NetworkType NetworkType 159 // The current protocol version we're running. 160 ProtocolVersion uint64 161 // The minimum protocol version we'll allow a peer we connect to 162 // to have. 163 MinProtocolVersion uint64 164 // Used as a "vanity plate" to identify different DeSo 165 // clients. Mainly useful in analyzing the network at 166 // a meta level, not in the protocol itself. 167 UserAgent string 168 // The list of DNS seed hosts to use during bootstrapping. 169 DNSSeeds []string 170 171 // A list of DNS seed prefixes and suffixes to use during bootstrapping. 172 // These prefixes and suffixes will be scanned and all IPs found will be 173 // incorporated into the address manager. 174 DNSSeedGenerators [][]string 175 176 // The network parameter for Bitcoin messages as defined by the btcd library. 177 // Useful for certain function calls we make to this library. 178 BitcoinBtcdParams *chaincfg.Params 179 180 // Because we use the Bitcoin header chain only to process exchanges from 181 // BTC to DeSo, we don't need to worry about Bitcoin blocks before a certain 182 // point, which is specified by this node. This is basically used to make 183 // header download more efficient but it's important to note that if for 184 // some reason there becomes a different main chain that is stronger than 185 // this one, then we will still switch to that one even with this parameter 186 // set such as it is. 187 BitcoinStartBlockNode *BlockNode 188 189 // The base58Check-encoded Bitcoin address that users must send Bitcoin to in order 190 // to purchase DeSo. Note that, unfortunately, simply using an all-zeros or 191 // mostly-all-zeros address or public key doesn't work and, in fact, I found that 192 // using almost any address other than this one also doesn't work. 193 BitcoinBurnAddress string 194 195 // This is a fee in basis points charged on BitcoinExchange transactions that gets 196 // paid to the miners. Basically, if a user burned enough Satoshi to create 100 DeSo, 197 // and if the BitcoinExchangeFeeBasisPoints was 1%, then 99 DeSo would be allocated to 198 // the user's public key while 1 DeSo would be left as a transaction fee to the miner. 199 BitcoinExchangeFeeBasisPoints uint64 200 201 // The amount of time to wait for a Bitcoin txn to broadcast throughout the Bitcoin 202 // network before checking for double-spends. 203 BitcoinDoubleSpendWaitSeconds float64 204 205 // This field allows us to set the amount purchased at genesis to a non-zero 206 // value. 207 DeSoNanosPurchasedAtGenesis uint64 208 209 // Port used for network communications among full nodes. 210 DefaultSocketPort uint16 211 // Port used for the limited JSON API that supports light clients. 212 DefaultJSONPort uint16 213 214 // The amount of time we wait when connecting to a peer. 215 DialTimeout time.Duration 216 // The amount of time we wait to receive a version message from a peer. 217 VersionNegotiationTimeout time.Duration 218 219 // The genesis block to use as the base of our chain. 220 GenesisBlock *MsgDeSoBlock 221 // The expected hash of the genesis block. Should align with what one 222 // would get from actually hashing the provided genesis block. 223 GenesisBlockHashHex string 224 // How often we target a single block to be generated. 225 TimeBetweenBlocks time.Duration 226 // How many blocks between difficulty retargets. 227 TimeBetweenDifficultyRetargets time.Duration 228 // Block hashes, when interpreted as big-endian big integers, must be 229 // values less than or equal to the difficulty 230 // target. The difficulty target is expressed below as a big-endian 231 // big integer and is adjusted every TargetTimePerBlock 232 // order to keep blocks generating at consistent intervals. 233 MinDifficultyTargetHex string 234 // We will reject chains that have less than this amount of total work, 235 // expressed as a hexadecimal big-endian bigint. Useful for preventing 236 // disk-fill attacks, among other things. 237 MinChainWorkHex string 238 239 // This is used for determining whether we are still in initial block download. 240 // If our tip is older than this, we continue with IBD. 241 MaxTipAge time.Duration 242 243 // Do not allow the difficulty to change by more than a factor of this 244 // variable during each adjustment period. 245 MaxDifficultyRetargetFactor int64 246 // Amount of time one must wait before a block reward can be spent. 247 BlockRewardMaturity time.Duration 248 // When shifting from v0 blocks to v1 blocks, we changed the hash function to 249 // DeSoHash, which is technically easier. Thus we needed to apply an adjustment 250 // factor in order to phase it in. 251 V1DifficultyAdjustmentFactor int64 252 253 // The maximum number of seconds in a future a block timestamp is allowed 254 // to be before it is rejected. 255 MaxTstampOffsetSeconds uint64 256 257 // The maximum number of bytes that can be allocated to transactions in 258 // a block. 259 MaxBlockSizeBytes uint64 260 261 // It's useful to set the miner maximum block size to a little lower than the 262 // maximum block size in certain cases. For example, on initial launch, setting 263 // it significantly lower is a good way to avoid getting hit by spam blocks. 264 MinerMaxBlockSizeBytes uint64 265 266 // In order to make public keys more human-readable, we convert 267 // them to base58. When we do that, we use a prefix that makes 268 // the public keys to become more identifiable. For example, all 269 // mainnet public keys start with "X" because we do this. 270 Base58PrefixPublicKey [3]byte 271 Base58PrefixPrivateKey [3]byte 272 273 // MaxFetchBlocks is the maximum number of blocks that can be fetched from 274 // a peer at one time. 275 MaxFetchBlocks uint32 276 277 MiningIterationsPerCycle uint64 278 279 // deso 280 MaxUsernameLengthBytes uint64 281 MaxUserDescriptionLengthBytes uint64 282 MaxProfilePicLengthBytes uint64 283 MaxProfilePicDimensions uint64 284 MaxPrivateMessageLengthBytes uint64 285 286 StakeFeeBasisPoints uint64 287 MaxPostBodyLengthBytes uint64 288 MaxPostSubLengthBytes uint64 289 MaxStakeMultipleBasisPoints uint64 290 MaxCreatorBasisPoints uint64 291 MaxNFTRoyaltyBasisPoints uint64 292 ParamUpdaterPublicKeys map[PkMapKey]bool 293 294 // A list of transactions to apply when initializing the chain. Useful in 295 // cases where we want to hard fork or reboot the chain with specific 296 // transactions applied. 297 SeedTxns []string 298 299 // A list of balances to initialize the blockchain with. This is useful for 300 // testing and useful in the event that the devs need to hard fork the chain. 301 SeedBalances []*DeSoOutput 302 303 // This is a small fee charged on creator coin transactions. It helps 304 // prevent issues related to floating point calculations. 305 CreatorCoinTradeFeeBasisPoints uint64 306 // These two params define the "curve" that we use when someone buys/sells 307 // creator coins. Effectively, this curve amounts to a polynomial of the form: 308 // - currentCreatorCoinPrice ~= slope * currentCreatorCoinSupply^(1/reserveRatio-1) 309 // Buys and sells effectively take the integral of the curve in opposite directions. 310 // 311 // To better understand where this curve comes from and how it works, check out 312 // the following links. They are all well written so don't be intimidated/afraid to 313 // dig in and read them: 314 // - Primer on bonding curves: https://medium.com/@simondlr/tokens-2-0-curved-token-bonding-in-curation-markets-1764a2e0bee5 315 // - The Uniswap v2 white paper: https://whitepaper.io/document/600/uniswap-whitepaper 316 // - The Bancor white paper: https://whitepaper.io/document/52/bancor-whitepaper 317 // - Article relating Bancor curves to polynomial curves: https://medium.com/@aventus/token-bonding-curves-547f3a04914 318 // - Derivations of the Bancor supply increase/decrease formulas: https://blog.relevant.community/bonding-curves-in-depth-intuition-parametrization-d3905a681e0a 319 // - Implementations of Bancor equations in Solidity with code: https://yos.io/2018/11/10/bonding-curves/ 320 // - Bancor is flawed blog post discussing Bancor edge cases: https://hackingdistributed.com/2017/06/19/bancor-is-flawed/ 321 // - A mathematica equation sheet with tests that walks through all the 322 // equations. You will need to copy this into a Mathematica notebook to 323 // run it: https://pastebin.com/raw/M4a1femY 324 CreatorCoinSlope *big.Float 325 CreatorCoinReserveRatio *big.Float 326 327 // CreatorCoinAutoSellThresholdNanos defines two things. The first is the minimum amount 328 // of creator coins a user must purchase in order for a transaction to be valid. Secondly 329 // it defines the point at which a sell operation will auto liquidate all remaining holdings. 330 // For example if I hold 1000 nanos of creator coins and sell x nanos such that 331 // 1000 - x < CreatorCoinAutoSellThresholdNanos, we auto liquidate the remaining holdings. 332 // It does this to prevent issues with floating point rounding that can arise. 333 // This value should be chosen such that the chain is resistant to "phantom nanos." Phantom nanos 334 // are tiny amounts of CreatorCoinsInCirculation/DeSoLocked which can cause 335 // the effective reserve ratio to deviate from the expected reserve ratio of the bancor curve. 336 // A higher CreatorCoinAutoSellThresholdNanos makes it prohibitively expensive for someone to 337 // attack the bancor curve to any meaningful measure. 338 CreatorCoinAutoSellThresholdNanos uint64 339 340 // The most deflationary event in DeSo history has yet to come... 341 DeflationBombBlockHeight uint64 342 } 343 344 // EnableRegtest allows for local development and testing with incredibly fast blocks with block rewards that 345 // can be spent as soon as they are mined. It also removes the default testnet seeds 346 func (params *DeSoParams) EnableRegtest() { 347 if params.NetworkType != NetworkType_TESTNET { 348 glog.Error("Regtest mode can only be enabled in testnet mode") 349 return 350 } 351 352 // Clear the seeds 353 params.DNSSeeds = []string{} 354 355 // Mine blocks incredibly quickly 356 params.TimeBetweenBlocks = 2 * time.Second 357 params.TimeBetweenDifficultyRetargets = 6 * time.Second 358 359 // Allow block rewards to be spent instantly 360 params.BlockRewardMaturity = 0 361 362 // Add a key defined in n0_test to the ParamUpdater set when running in regtest mode. 363 // Seed: verb find card ship another until version devote guilt strong lemon six 364 params.ParamUpdaterPublicKeys[MakePkMapKey(MustBase58CheckDecode("tBCKVERmG9nZpHTk2AVPqknWc1Mw9HHAnqrTpW1RnXpXMQ4PsQgnmV"))] = true 365 } 366 367 // GenesisBlock defines the genesis block used for the DeSo maainnet and testnet 368 var ( 369 ArchitectPubKeyBase58Check = "BC1YLg3oh6Boj8e2boCo1vQCYHLk1rjsHF6jthBdvSw79bixQvKK6Qa" 370 // This is the public key corresponding to the BitcoinBurnAddress on mainnet. 371 BurnPubKeyBase58Check = "BC1YLjWBf2qnDJmi8HZzzCPeXqy4dCKq95oqqzerAyW8MUTbuXTb1QT" 372 373 GenesisBlock = MsgDeSoBlock{ 374 Header: &MsgDeSoHeader{ 375 Version: 0, 376 PrevBlockHash: &BlockHash{}, 377 TransactionMerkleRoot: mustDecodeHexBlockHash("4b71d103dd6fff1bd6110bc8ed0a2f3118bbe29a67e45c6c7d97546ad126906f"), 378 TstampSecs: uint64(1610948544), 379 Height: uint64(0), 380 Nonce: uint64(0), 381 }, 382 Txns: []*MsgDeSoTxn{ 383 { 384 TxInputs: []*DeSoInput{}, 385 // The outputs in the genesis block aren't actually used by anything, but 386 // including them helps our block explorer return the genesis transactions 387 // without needing an explicit special case. 388 TxOutputs: SeedBalances, 389 // TODO: Pick a better string 390 TxnMeta: &BlockRewardMetadataa{ 391 ExtraData: []byte( 392 "They came here, to the New World. World 2.0, version 1776."), 393 }, 394 // A signature is not required for BLOCK_REWARD transactions since they 395 // don't spend anything. 396 }, 397 }, 398 } 399 GenesisBlockHashHex = "5567c45b7b83b604f9ff5cb5e88dfc9ad7d5a1dd5818dd19e6d02466f47cbd62" 400 GenesisBlockHash = mustDecodeHexBlockHash(GenesisBlockHashHex) 401 402 ParamUpdaterPublicKeys = map[PkMapKey]bool{ 403 // 19Hg2mAJUTKFac2F2BBpSEm7BcpkgimrmD 404 MakePkMapKey(MustBase58CheckDecode(ArchitectPubKeyBase58Check)): true, 405 MakePkMapKey(MustBase58CheckDecode("BC1YLiXwGTte8oXEEVzm4zqtDpGRx44Y4rqbeFeAs5MnzsmqT5RcqkW")): true, 406 MakePkMapKey(MustBase58CheckDecode("BC1YLgGLKjuHUFZZQcNYrdWRrHsDKUofd9MSxDq4NY53x7vGt4H32oZ")): true, 407 MakePkMapKey(MustBase58CheckDecode("BC1YLj8UkNMbCsmTUTx5Z2bhtp8q86csDthRmK6zbYstjjbS5eHoGkr")): true, 408 MakePkMapKey(MustBase58CheckDecode("BC1YLgD1f7yw7Ue8qQiW7QMBSm6J7fsieK5rRtyxmWqL2Ypra2BAToc")): true, 409 MakePkMapKey(MustBase58CheckDecode("BC1YLfz4GH3Gfj6dCtBi8bNdNTbTdcibk8iCZS75toUn4UKZaTJnz9y")): true, 410 MakePkMapKey(MustBase58CheckDecode("BC1YLfoSyJWKjHGnj5ZqbSokC3LPDNBMDwHX3ehZDCA3HVkFNiPY5cQ")): true, 411 } 412 ) 413 414 // DeSoMainnetParams defines the DeSo parameters for the mainnet. 415 var DeSoMainnetParams = DeSoParams{ 416 NetworkType: NetworkType_MAINNET, 417 ProtocolVersion: 1, 418 MinProtocolVersion: 1, 419 UserAgent: "Architect", 420 DNSSeeds: []string{ 421 "deso.coinbase.com", 422 "deso.gemini.com", 423 "deso.kraken.com", 424 "deso.bitstamp.com", 425 "deso.bitfinex.com", 426 "deso.binance.com", 427 "deso.hbg.com", 428 "deso.okex.com", 429 "deso.bithumb.com", 430 "deso.upbit.com", 431 }, 432 DNSSeedGenerators: [][]string{ 433 { 434 "deso-seed-", 435 ".io", 436 }, 437 }, 438 439 GenesisBlock: &GenesisBlock, 440 GenesisBlockHashHex: GenesisBlockHashHex, 441 // This is used as the starting difficulty for the chain. 442 MinDifficultyTargetHex: "000001FFFF000000000000000000000000000000000000000000000000000000", 443 444 // Run with --v=2 and look for "cum work" output from miner.go 445 MinChainWorkHex: "000000000000000000000000000000000000000000000000006314f9a85a949b", 446 447 MaxTipAge: 24 * time.Hour, 448 449 // =================================================================================== 450 // Mainnet Bitcoin config 451 // =================================================================================== 452 BitcoinBtcdParams: &chaincfg.MainNetParams, 453 BitcoinBurnAddress: "1PuXkbwqqwzEYo9SPGyAihAge3e9Lc71b", 454 455 // We use a start node that is near the tip of the Bitcoin header chain. Doing 456 // this allows us to bootstrap Bitcoin transactions much more quickly without 457 // comrpomising on security because, if this node ends up not being on the best 458 // chain one day (which would be completely ridiculous anyhow because it would mean that 459 // days or months of bitcoin transactions got reverted), our code will still be 460 // able to robustly switch to an alternative chain that has more work. It's just 461 // much faster if the best chain is the one that has this start node in it (similar 462 // to the --assumevalid Bitcoin flag). 463 // 464 // Process for generating this config: 465 // - Find a node config from the test_nodes folder (we used fe0) 466 // - Make sure the logging for bitcoin_manager is set to 2. --vmodule="bitcoin_manager=2" 467 // - Run the node config (./fe0) 468 // - A line should print every time there's a difficulty adjustment with the parameters 469 // required below (including "DiffBits"). Just copy those into the below and 470 // everything should work. 471 // - Oh and you might have to set BitcoinMinChainWorkHex to something lower/higher. The 472 // value should equal the amount of work it takes to get from whatever start node you 473 // choose and the tip. This is done by running once, letting it fail, and then rerunning 474 // with the value it outputs. 475 BitcoinStartBlockNode: NewBlockNode( 476 nil, 477 mustDecodeHexBlockHashBitcoin("000000000000000000092d577cc673bede24b6d7199ee69c67eeb46c18fc978c"), 478 // Note the height is always one greater than the parent node. 479 653184, 480 _difficultyBitsToHash(386798414), 481 // CumWork shouldn't matter. 482 big.NewInt(0), 483 // We are bastardizing the DeSo header to store Bitcoin information here. 484 &MsgDeSoHeader{ 485 TstampSecs: 1602950620, 486 Height: 0, 487 }, 488 StatusBitcoinHeaderValidated, 489 ), 490 491 BitcoinExchangeFeeBasisPoints: 10, 492 BitcoinDoubleSpendWaitSeconds: 5.0, 493 DeSoNanosPurchasedAtGenesis: uint64(6000000000000000), 494 DefaultSocketPort: uint16(17000), 495 DefaultJSONPort: uint16(17001), 496 497 DialTimeout: 30 * time.Second, 498 VersionNegotiationTimeout: 30 * time.Second, 499 500 BlockRewardMaturity: time.Hour * 3, 501 502 V1DifficultyAdjustmentFactor: 10, 503 504 // Use a five-minute block time. Although a shorter block time seems like 505 // it would improve the user experience, the reality is that zero-confirmation 506 // transactions can usually be relied upon to give the user the illusion of 507 // instant gratification (particularly since we implement a limited form of 508 // RBF that makes it difficult to reverse transactions once they're in the 509 // mempool of nodes). Moreover, longer block times mean we require fewer 510 // headers to be downloaded by light clients in the long run, which is a 511 // big win in terms of performance. 512 TimeBetweenBlocks: 5 * time.Minute, 513 // We retarget the difficulty every day. Note this value must 514 // ideally be evenly divisible by TimeBetweenBlocks. 515 TimeBetweenDifficultyRetargets: 24 * time.Hour, 516 // Difficulty can't decrease to below 25% of its previous value or increase 517 // to above 400% of its previous value. 518 MaxDifficultyRetargetFactor: 4, 519 Base58PrefixPublicKey: [3]byte{0xcd, 0x14, 0x0}, 520 Base58PrefixPrivateKey: [3]byte{0x35, 0x0, 0x0}, 521 522 // Reject blocks that are more than two hours in the future. 523 MaxTstampOffsetSeconds: 2 * 60 * 60, 524 525 // We use a max block size of 16MB. This translates to 100-200 posts per 526 // second depending on the size of the post, which should support around 527 // ten million active users. We compute this by taking Twitter, which averages 528 // 6,000 posts per second at 300M daus => 10M/300M*6,000=200 posts per second. This 529 // generates about 1.6TB per year of data, which means that nodes will 530 // have to have a lot of space. This seems fine, however, 531 // because space is cheap and it's easy to spin up a cloud machine with 532 // tens of terabytes of space. 533 MaxBlockSizeBytes: 16000000, 534 535 // We set this to be lower initially to avoid winding up with really big 536 // spam blocks in the event someone tries to abuse the initially low min 537 // fee rates. 538 MinerMaxBlockSizeBytes: 2000000, 539 540 // This takes about ten seconds on a reasonable CPU, which makes sense given 541 // a 10 minute block time. 542 MiningIterationsPerCycle: 95000, 543 544 MaxUsernameLengthBytes: MaxUsernameLengthBytes, 545 546 MaxUserDescriptionLengthBytes: 20000, 547 548 MaxProfilePicLengthBytes: 20000, 549 MaxProfilePicDimensions: 100, 550 551 // MaxPrivateMessageLengthBytes is the maximum number of bytes of encrypted 552 // data a private message is allowed to include in an PrivateMessage transaction. 553 MaxPrivateMessageLengthBytes: 10000, 554 555 // Set the stake fee to 10% 556 StakeFeeBasisPoints: 10 * 100, 557 // TODO(performance): We're currently storing posts using HTML, which 558 // basically 2x as verbose as it needs to be for basically no reason. 559 // We should consider storing stuff as markdown instead, which we can 560 // do with the richtext editor thing that we have. 561 MaxPostBodyLengthBytes: 20000, 562 MaxPostSubLengthBytes: 140, 563 // 10x is the max for the truly highly motivated individuals. 564 MaxStakeMultipleBasisPoints: 10 * 100 * 100, 565 // 100% is the max creator percentage. Not sure why you'd buy such a coin 566 // but whatever. 567 MaxCreatorBasisPoints: 100 * 100, 568 MaxNFTRoyaltyBasisPoints: 100 * 100, 569 ParamUpdaterPublicKeys: ParamUpdaterPublicKeys, 570 571 // Use a canonical set of seed transactions. 572 SeedTxns: SeedTxns, 573 574 // Set some seed balances if desired 575 SeedBalances: SeedBalances, 576 577 // Just charge one basis point on creator coin trades for now. 578 CreatorCoinTradeFeeBasisPoints: 1, 579 // Note that Uniswap is quadratic (i.e. its price equation is 580 // - price ~= currentCreatorCoinSupply^2, 581 // and we think quadratic makes sense in this context as well. 582 CreatorCoinSlope: NewFloat().SetFloat64(0.003), 583 CreatorCoinReserveRatio: NewFloat().SetFloat64(0.3333333), 584 585 // 10 was seen as a threshold reachable in almost all transaction. 586 // It's just high enough where you avoid drifting creating coin 587 // reserve ratios. 588 CreatorCoinAutoSellThresholdNanos: uint64(10), 589 590 // Triggers approximately Saturday June 12th at 8pm PT 591 DeflationBombBlockHeight: 33783, 592 } 593 594 func mustDecodeHexBlockHashBitcoin(ss string) *BlockHash { 595 hash, err := chainhash.NewHashFromStr(ss) 596 if err != nil { 597 panic(err) 598 } 599 return (*BlockHash)(hash) 600 } 601 602 func MustDecodeHexBlockHash(ss string) *BlockHash { 603 return mustDecodeHexBlockHash(ss) 604 } 605 606 func mustDecodeHexBlockHash(ss string) *BlockHash { 607 bb, err := hex.DecodeString(ss) 608 if err != nil { 609 log.Fatalf("Problem decoding hex string to bytes: (%s): %v", ss, err) 610 } 611 if len(bb) != 32 { 612 log.Fatalf("mustDecodeHexBlockHash: Block hash has length (%d) but should be (%d)", len(bb), 32) 613 } 614 ret := BlockHash{} 615 copy(ret[:], bb) 616 return &ret 617 } 618 619 // DeSoTestnetParams defines the DeSo parameters for the testnet. 620 var DeSoTestnetParams = DeSoParams{ 621 NetworkType: NetworkType_TESTNET, 622 ProtocolVersion: 0, 623 MinProtocolVersion: 0, 624 UserAgent: "Architect", 625 DNSSeeds: []string{ 626 "dorsey.bitclout.com", 627 }, 628 DNSSeedGenerators: [][]string{}, 629 630 // =================================================================================== 631 // Testnet Bitcoin config 632 // =================================================================================== 633 BitcoinBtcdParams: &chaincfg.TestNet3Params, 634 BitcoinBurnAddress: "mhziDsPWSMwUqvZkVdKY92CjesziGP3wHL", 635 BitcoinExchangeFeeBasisPoints: 10, 636 BitcoinDoubleSpendWaitSeconds: 5.0, 637 DeSoNanosPurchasedAtGenesis: uint64(6000000000000000), 638 639 // See comment in mainnet config. 640 BitcoinStartBlockNode: NewBlockNode( 641 nil, 642 mustDecodeHexBlockHashBitcoin("000000000000003aae8fb976056413aa1d863eb5bee381ff16c9642283b1da1a"), 643 1897056, 644 _difficultyBitsToHash(424073553), 645 646 // CumWork: We set the work of the start node such that, when added to all of the 647 // blocks that follow it, it hurdles the min chain work. 648 big.NewInt(0), 649 // We are bastardizing the DeSo header to store Bitcoin information here. 650 &MsgDeSoHeader{ 651 TstampSecs: 1607659152, 652 Height: 0, 653 }, 654 StatusBitcoinHeaderValidated, 655 ), 656 657 // =================================================================================== 658 // Testnet socket config 659 // =================================================================================== 660 DefaultSocketPort: uint16(18000), 661 DefaultJSONPort: uint16(18001), 662 663 DialTimeout: 30 * time.Second, 664 VersionNegotiationTimeout: 30 * time.Second, 665 666 GenesisBlock: &GenesisBlock, 667 GenesisBlockHashHex: GenesisBlockHashHex, 668 669 // Use a faster block time in the testnet. 670 TimeBetweenBlocks: 1 * time.Minute, 671 // Use a very short difficulty retarget period in the testnet. 672 TimeBetweenDifficultyRetargets: 3 * time.Minute, 673 // This is used as the starting difficulty for the chain. 674 MinDifficultyTargetHex: "0090000000000000000000000000000000000000000000000000000000000000", 675 // Minimum amount of work a valid chain needs to have. Useful for preventing 676 // disk-fill attacks, among other things. 677 //MinChainWorkHex: "000000000000000000000000000000000000000000000000000000011883b96c", 678 MinChainWorkHex: "0000000000000000000000000000000000000000000000000000000000000000", 679 680 // TODO: Set to one day when we launch the testnet. In the meantime this value 681 // is more useful for local testing. 682 MaxTipAge: time.Hour * 24, 683 684 // Difficulty can't decrease to below 50% of its previous value or increase 685 // to above 200% of its previous value. 686 MaxDifficultyRetargetFactor: 2, 687 // Miners need to wait some time before spending their block reward. 688 BlockRewardMaturity: 5 * time.Minute, 689 690 V1DifficultyAdjustmentFactor: 10, 691 692 // Reject blocks that are more than two hours in the future. 693 MaxTstampOffsetSeconds: 2 * 60 * 60, 694 695 // We use a max block size of 1MB. This seems to work well for BTC and 696 // most of our data doesn't need to be stored on the blockchain anyway. 697 MaxBlockSizeBytes: 1000000, 698 699 // We set this to be lower initially to avoid winding up with really big 700 // spam blocks in the event someone tries to abuse the initially low min 701 // fee rates. 702 MinerMaxBlockSizeBytes: 1000000, 703 704 Base58PrefixPublicKey: [3]byte{0x11, 0xc2, 0x0}, 705 Base58PrefixPrivateKey: [3]byte{0x4f, 0x6, 0x1b}, 706 707 MiningIterationsPerCycle: 9500, 708 709 // deso 710 MaxUsernameLengthBytes: MaxUsernameLengthBytes, 711 712 MaxUserDescriptionLengthBytes: 20000, 713 714 MaxProfilePicLengthBytes: 20000, 715 MaxProfilePicDimensions: 100, 716 717 // MaxPrivateMessageLengthBytes is the maximum number of bytes of encrypted 718 // data a private message is allowed to include in an PrivateMessage transaction. 719 MaxPrivateMessageLengthBytes: 10000, 720 721 // Set the stake fee to 5% 722 StakeFeeBasisPoints: 5 * 100, 723 // TODO(performance): We're currently storing posts using HTML, which 724 // basically 2x as verbose as it needs to be for basically no reason. 725 // We should consider storing stuff as markdown instead, which we can 726 // do with the richtext editor thing that we have. 727 MaxPostBodyLengthBytes: 50000, 728 MaxPostSubLengthBytes: 140, 729 // 10x is the max for the truly highly motivated individuals. 730 MaxStakeMultipleBasisPoints: 10 * 100 * 100, 731 // 100% is the max creator percentage. Not sure why you'd buy such a coin 732 // but whatever. 733 MaxCreatorBasisPoints: 100 * 100, 734 MaxNFTRoyaltyBasisPoints: 100 * 100, 735 ParamUpdaterPublicKeys: ParamUpdaterPublicKeys, 736 737 // Use a canonical set of seed transactions. 738 SeedTxns: TestSeedTxns, 739 740 // Set some seed balances if desired 741 // Note: For now these must be the same as mainnet because GenesisBlock is the same 742 SeedBalances: SeedBalances, 743 744 // Just charge one basis point on creator coin trades for now. 745 CreatorCoinTradeFeeBasisPoints: 1, 746 // Note that Uniswap is quadratic (i.e. its price equation is 747 // - price ~= currentCreatorCoinSupply^2, 748 // and we think quadratic makes sense in this context as well. 749 CreatorCoinSlope: NewFloat().SetFloat64(0.003), 750 CreatorCoinReserveRatio: NewFloat().SetFloat64(0.3333333), 751 752 // 10 was seen as a threshold reachable in almost all transaction. 753 // It's just high enough where you avoid drifting creating coin 754 // reserve ratios. 755 CreatorCoinAutoSellThresholdNanos: uint64(10), 756 } 757 758 // GetDataDir gets the user data directory where we store files 759 // in a cross-platform way. 760 func GetDataDir(params *DeSoParams) string { 761 configDirs := configdir.New( 762 ConfigDirVendorName, ConfigDirAppName) 763 dirString := configDirs.QueryFolders(configdir.Global)[0].Path 764 dataDir := filepath.Join(dirString, params.NetworkType.String()) 765 if err := os.MkdirAll(dataDir, os.ModePerm); err != nil { 766 log.Fatalf("GetDataDir: Could not create data directories (%s): %v", dataDir, err) 767 } 768 return dataDir 769 } 770 771 // Defines keys that may exist in a transaction's ExtraData map 772 const ( 773 // Key in transaction's extra data map that points to a post that the current transaction is reposting 774 RepostedPostHash = "RecloutedPostHash" 775 // Key in transaction's extra map -- The presence of this key indicates that this post is a repost with a quote. 776 IsQuotedRepostKey = "IsQuotedReclout" 777 778 // Keys for a GlobalParamUpdate transaction's extra data map. 779 USDCentsPerBitcoinKey = "USDCentsPerBitcoin" 780 MinNetworkFeeNanosPerKBKey = "MinNetworkFeeNanosPerKB" 781 CreateProfileFeeNanosKey = "CreateProfileFeeNanos" 782 CreateNFTFeeNanosKey = "CreateNFTFeeNanos" 783 MaxCopiesPerNFTKey = "MaxCopiesPerNFT" 784 ForbiddenBlockSignaturePubKeyKey = "ForbiddenBlockSignaturePubKey" 785 786 DiamondLevelKey = "DiamondLevel" 787 DiamondPostHashKey = "DiamondPostHash" 788 789 // Key in transaction's extra data map containing the derived key used in signing the txn. 790 DerivedPublicKey = "DerivedPublicKey" 791 ) 792 793 // Defines values that may exist in a transaction's ExtraData map 794 var ( 795 PostExtraDataConsensusKeys = [2]string{RepostedPostHash, IsQuotedRepostKey} 796 ) 797 798 var ( 799 QuotedRepostVal = []byte{1} 800 NotQuotedRepostVal = []byte{0} 801 ) 802 803 // InitialGlobalParamsEntry to be used before ParamUpdater creates the first update. 804 var ( 805 InitialGlobalParamsEntry = GlobalParamsEntry{ 806 // We initialize the USDCentsPerBitcoin to 0 so we can use the value set by the UPDATE_BITCOIN_USD_EXCHANGE_RATE. 807 USDCentsPerBitcoin: 0, 808 // We initialize the MinimumNetworkFeeNanosPerKB to 0 so we do not assess a minimum fee until specified by ParamUpdater. 809 MinimumNetworkFeeNanosPerKB: 0, 810 // We initialize the CreateProfileFeeNanos to 0 so we do not assess a fee to create a profile until specified by ParamUpdater. 811 CreateProfileFeeNanos: 0, 812 // We initialize the CreateNFTFeeNanos to 0 so we do not assess a fee to create an NFT until specified by ParamUpdater. 813 CreateNFTFeeNanos: 0, 814 MaxCopiesPerNFT: 0, 815 } 816 ) 817 818 // Define min / max possible values for GlobalParams. 819 const ( 820 // MinNetworkFeeNanosPerKBValue - Minimum value to which the minimum network fee per KB can be set. 821 MinNetworkFeeNanosPerKBValue = 0 822 // MaxNetworkFeeNanosPerKBValue - Maximum value to which the maximum network fee per KB can be set. 823 MaxNetworkFeeNanosPerKBValue = 100 * NanosPerUnit 824 // MinCreateProfileFeeNanos - Minimum value to which the create profile fee can be set. 825 MinCreateProfileFeeNanos = 0 826 // MaxCreateProfileFeeNanos - Maximum value to which the create profile fee can be set. 827 MaxCreateProfileFeeNanos = 100 * NanosPerUnit 828 // Min/MaxCreateNFTFeeNanos - Min/max value to which the create NFT fee can be set. 829 MinCreateNFTFeeNanos = 0 830 MaxCreateNFTFeeNanos = 100 * NanosPerUnit 831 // Min/MaxMaxCopiesPerNFTNanos - Min/max value to which the create NFT fee can be set. 832 MinMaxCopiesPerNFT = 1 833 MaxMaxCopiesPerNFT = 10000 834 )