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  )