github.com/deso-protocol/core@v1.2.9/lib/blockchain.go (about) 1 package lib 2 3 import ( 4 "bytes" 5 "container/list" 6 "encoding/hex" 7 "fmt" 8 "math" 9 "math/big" 10 "reflect" 11 "runtime/debug" 12 "sort" 13 "strings" 14 "time" 15 16 btcdchain "github.com/btcsuite/btcd/blockchain" 17 chainlib "github.com/btcsuite/btcd/blockchain" 18 "github.com/btcsuite/btcd/btcec" 19 "github.com/btcsuite/btcd/wire" 20 "github.com/davecgh/go-spew/spew" 21 "github.com/deso-protocol/go-deadlock" 22 merkletree "github.com/deso-protocol/go-merkle-tree" 23 "github.com/dgraph-io/badger/v3" 24 "github.com/golang/glog" 25 "github.com/pkg/errors" 26 ) 27 28 // blockchain.go is the work-horse for validating DeSo blocks and updating the 29 // database after each block is processed. The ProcessBlock function is probably 30 // a good place to start to understand this file. 31 32 const ( 33 // MaxOrphansInMemory is the maximum number of orphan blocks that we're willing to keep in memory. We set 34 // a maximum here in order to prevent memory exhaustion from someone sending us too 35 // many unconnectedTxns. 36 MaxOrphansInMemory = 100 37 38 // MaxBlockIndexNodes needs to allow the block index to grow large enough to accommodate multiple 39 // forks of material length while allowing us to avoid an out-of-memory issue due to 40 // a "disk-fill" attack. Notice that because we will only ever download blocks 41 // after we have a header chain that has beaten all other header chains we're aware 42 // of, the common case for an attack will be someone sending us long useless header 43 // chains that we never actually download blocks for. This results in the block index 44 // bloating up (indefinitely if we don't prune it) due to storing useless headers 45 // but not resulting in the downloading of any blocks, which is a good thing. 46 // 47 // At ten minute block times, 5,000,000 comes out to roughly 95 years worth of blocks, 48 // which seems like a reasonable limit for now (if we had 25 years of blocks, we'd still 49 // have room for multiple forks each an entire history's length with this value). If 50 // each node takes up 100 bytes of space this amounts to around 500MB, which also seems 51 // like a reasonable size. 52 MaxBlockIndexNodes = 5000000 53 ) 54 55 type BlockStatus uint32 56 57 const ( 58 StatusNone BlockStatus = 0 59 60 // Headers must always be Validated or ValidateFailed. We 61 // don't store orphan headers and therefore any header that we do 62 // have in our node index will be known definitively to be valid or 63 // invalid one way or the other. 64 StatusHeaderValidated = 1 << iota 65 StatusHeaderValidateFailed 66 67 StatusBlockProcessed 68 StatusBlockStored 69 StatusBlockValidated 70 StatusBlockValidateFailed 71 72 // These statuses are only used for Bitcoin header blocks in the BitcoinManager, 73 // not DeSo blocks. As such, you should only see these referenced in the BitcoinManager. 74 // We include them here because overloading the DeSo data structures to make it 75 // so that the BitcoinManager can use them is easier than defining whole new data 76 // structures that are incompatible with existing methods like LatestLocator(). If 77 // Go supported generics, this would probably not be necessary but it doesn't and 78 // so this is the path of least resistance. 79 StatusBitcoinHeaderValidated 80 StatusBitcoinHeaderValidateFailed 81 ) 82 83 func (blockStatus BlockStatus) String() string { 84 if blockStatus == 0 { 85 return "NONE" 86 } 87 88 statuses := []string{} 89 if blockStatus&StatusHeaderValidated != 0 { 90 statuses = append(statuses, "HEADER_VALIDATED") 91 blockStatus ^= StatusHeaderValidated 92 } 93 if blockStatus&StatusHeaderValidateFailed != 0 { 94 statuses = append(statuses, "HEADER_VALIDATE_FAILED") 95 blockStatus ^= StatusHeaderValidateFailed 96 } 97 if blockStatus&StatusBlockProcessed != 0 { 98 statuses = append(statuses, "BLOCK_PROCESSED") 99 blockStatus ^= StatusBlockProcessed 100 } 101 if blockStatus&StatusBlockStored != 0 { 102 statuses = append(statuses, "BLOCK_STORED") 103 blockStatus ^= StatusBlockStored 104 } 105 if blockStatus&StatusBlockValidated != 0 { 106 statuses = append(statuses, "BLOCK_VALIDATED") 107 blockStatus ^= StatusBlockValidated 108 } 109 if blockStatus&StatusBlockValidateFailed != 0 { 110 statuses = append(statuses, "BLOCK_VALIDATE_FAILED") 111 blockStatus ^= StatusBlockValidateFailed 112 } 113 114 // If at this point the blockStatus isn't zeroed out then 115 // we have an unknown status remaining. 116 if blockStatus != 0 { 117 statuses = append(statuses, "ERROR_UNKNOWN_STATUS!") 118 } 119 120 return strings.Join(statuses, " | ") 121 } 122 123 // Add some fields in addition to the header to aid in the selection 124 // of the best chain. 125 type BlockNode struct { 126 // Pointer to a node representing the block's parent. 127 Parent *BlockNode 128 129 // The hash computed on this block. 130 Hash *BlockHash 131 132 // Height is the position in the block chain. 133 Height uint32 134 135 // The difficulty target for this block. Used to compute the next 136 // block's difficulty target so it can be validated. 137 DifficultyTarget *BlockHash 138 139 // A computation of the total amount of work that has been performed 140 // on this chain, including the current node. 141 CumWork *big.Int 142 143 // The block header. 144 Header *MsgDeSoHeader 145 146 // Status holds the validation state for the block and whether or not 147 // it's stored in the database. 148 Status BlockStatus 149 } 150 151 func _difficultyBitsToHash(diffBits uint32) (_diffHash *BlockHash) { 152 diffBigint := btcdchain.CompactToBig(diffBits) 153 return BigintToHash(diffBigint) 154 } 155 156 func ExtractBitcoinBurnTransactionsFromBitcoinBlock( 157 bitcoinBlock *wire.MsgBlock, bitcoinBurnAddress string, params *DeSoParams) []*wire.MsgTx { 158 159 burnTxns := []*wire.MsgTx{} 160 for _, txn := range bitcoinBlock.Transactions { 161 burnOutput, err := _computeBitcoinBurnOutput( 162 txn, bitcoinBurnAddress, params.BitcoinBtcdParams) 163 if err != nil { 164 glog.Errorf("ExtractBitcoinBurnTransactionsFromBitcoinBlock: Problem "+ 165 "extracting Bitcoin transaction: %v", err) 166 continue 167 } 168 169 if burnOutput > 0 { 170 burnTxns = append(burnTxns, txn) 171 } 172 } 173 174 return burnTxns 175 } 176 177 func ExtractBitcoinBurnTransactionsFromBitcoinBlockWithMerkleProofs( 178 bitcoinBlock *wire.MsgBlock, burnAddress string, params *DeSoParams) ( 179 _txns []*wire.MsgTx, _merkleProofs [][]*merkletree.ProofPart, _err error) { 180 181 // Extract the Bitcoin burn transactions. 182 burnTxns := ExtractBitcoinBurnTransactionsFromBitcoinBlock( 183 bitcoinBlock, burnAddress, params) 184 185 // If there weren't any burn transactions then there's nothing to do. 186 if len(burnTxns) == 0 { 187 return nil, nil, nil 188 } 189 190 // Compute all of the transaction hashes for the block. 191 txHashes := [][]byte{} 192 for _, txn := range bitcoinBlock.Transactions { 193 txnBytes := bytes.Buffer{} 194 err := txn.SerializeNoWitness(&txnBytes) 195 if err != nil { 196 return nil, nil, fmt.Errorf( 197 "ExtractBitcoinBurnTransactionsFromBitcoinBlockWithMerkleProofs: "+ 198 "Error computing all the txn hashes for block: %v", 199 err) 200 } 201 txHashes = append(txHashes, txnBytes.Bytes()) 202 } 203 204 // Compute a merkle tree for the block. 205 merkleTree := merkletree.NewTree(merkletree.Sha256DoubleHash, txHashes) 206 207 if !reflect.DeepEqual(merkleTree.Root.GetHash(), bitcoinBlock.Header.MerkleRoot[:]) { 208 return nil, nil, fmt.Errorf( 209 "ExtractBitcoinBurnTransactionsFromBitcoinBlockWithMerkleProofs: "+ 210 "Merkle proof computed from txns %#v != to Merkle proof in Bitcoin block %#v", 211 merkleTree.Root.GetHash(), bitcoinBlock.Header.MerkleRoot[:]) 212 } 213 214 // Use the Merkle tree to compute a Merkle proof for each transaction. 215 burnTxnsWithProofs := []*wire.MsgTx{} 216 merkleProofs := [][]*merkletree.ProofPart{} 217 for _, txn := range burnTxns { 218 txHash := txn.TxHash() 219 proof, err := merkleTree.CreateProof(txHash[:]) 220 if err != nil { 221 return nil, nil, fmt.Errorf( 222 "ExtractBitcoinBurnTransactionsFromBitcoinBlockWithMerkleProofs: Problem "+ 223 "computing Merkle proof for txn %v for block %v: %v", 224 txn, bitcoinBlock, err) 225 } 226 227 burnTxnsWithProofs = append(burnTxnsWithProofs, txn) 228 merkleProofs = append(merkleProofs, proof.PathToRoot) 229 } 230 231 return burnTxnsWithProofs, merkleProofs, nil 232 } 233 234 func ExtractBitcoinExchangeTransactionsFromBitcoinBlock( 235 bitcoinBlock *wire.MsgBlock, burnAddress string, params *DeSoParams) ( 236 _txns []*MsgDeSoTxn, _err error) { 237 238 bitcoinBurnTxns, merkleProofs, err := 239 ExtractBitcoinBurnTransactionsFromBitcoinBlockWithMerkleProofs( 240 bitcoinBlock, burnAddress, params) 241 if err != nil { 242 return nil, errors.Wrapf(err, "ExtractBitcoinExchangeTransactionsFromBitcoinBlock: "+ 243 "Problem extracting raw Bitcoin burn transactions from Bitcoin Block") 244 } 245 246 bitcoinExchangeTxns := []*MsgDeSoTxn{} 247 blockHash := (BlockHash)(bitcoinBlock.BlockHash()) 248 merkleRoot := (BlockHash)(bitcoinBlock.Header.MerkleRoot) 249 for ii := range bitcoinBurnTxns { 250 bitcoinExchangeMetadata := &BitcoinExchangeMetadata{ 251 BitcoinTransaction: bitcoinBurnTxns[ii], 252 BitcoinBlockHash: &blockHash, 253 BitcoinMerkleRoot: &merkleRoot, 254 BitcoinMerkleProof: merkleProofs[ii], 255 } 256 257 // The only thing a BitcoinExchange transaction has set is its TxnMeta. 258 // Everything else is left blank because it is not needed. Note that the 259 // recipient of the DeSo that will be created is the first valid input in 260 // the BitcoinTransaction specified. Note also that the 261 // fee is deducted as a percentage of the eventual DeSo that will get 262 // created as a result of this transaction. 263 currentTxn := &MsgDeSoTxn{ 264 TxnMeta: bitcoinExchangeMetadata, 265 } 266 bitcoinExchangeTxns = append(bitcoinExchangeTxns, currentTxn) 267 } 268 269 return bitcoinExchangeTxns, nil 270 } 271 272 func (nn *BlockNode) String() string { 273 var parentHash *BlockHash 274 if nn.Parent != nil { 275 parentHash = nn.Parent.Hash 276 } 277 tstamp := uint32(0) 278 if nn.Header != nil { 279 tstamp = uint32(nn.Header.TstampSecs) 280 } 281 return fmt.Sprintf("< TstampSecs: %d, Height: %d, Hash: %s, ParentHash %s, Status: %s, CumWork: %v>", 282 tstamp, nn.Header.Height, nn.Hash, parentHash, nn.Status, nn.CumWork) 283 } 284 285 // TODO: Height not needed in this since it's in the header. 286 func NewBlockNode( 287 parent *BlockNode, 288 hash *BlockHash, 289 height uint32, 290 difficultyTarget *BlockHash, 291 cumWork *big.Int, 292 header *MsgDeSoHeader, 293 status BlockStatus) *BlockNode { 294 295 return &BlockNode{ 296 Parent: parent, 297 Hash: hash, 298 Height: height, 299 DifficultyTarget: difficultyTarget, 300 CumWork: cumWork, 301 Header: header, 302 Status: status, 303 } 304 } 305 306 func (nn *BlockNode) Ancestor(height uint32) *BlockNode { 307 if height > nn.Height { 308 return nil 309 } 310 311 node := nn 312 for ; node != nil && node.Height != height; node = node.Parent { 313 // Keep iterating node until the condition no longer holds. 314 } 315 316 return node 317 } 318 319 // RelativeAncestor returns the ancestor block node a relative 'distance' blocks 320 // before this node. This is equivalent to calling Ancestor with the node's 321 // height minus provided distance. 322 // 323 // This function is safe for concurrent access. 324 func (nn *BlockNode) RelativeAncestor(distance uint32) *BlockNode { 325 return nn.Ancestor(nn.Height - distance) 326 } 327 328 // CalcNextDifficultyTarget computes the difficulty target expected of the 329 // next block. 330 func CalcNextDifficultyTarget( 331 lastNode *BlockNode, version uint32, params *DeSoParams) (*BlockHash, error) { 332 333 // Compute the blocks in each difficulty cycle. 334 blocksPerRetarget := uint32(params.TimeBetweenDifficultyRetargets / params.TimeBetweenBlocks) 335 336 // We effectively skip the first difficulty retarget by returning the default 337 // difficulty value for the first cycle. Not doing this (or something like it) 338 // would cause the genesis block's timestamp, which could be off by several days 339 // to significantly skew the first cycle in a way that is mostly annoying for 340 // testing but also suboptimal for the mainnet. 341 minDiffBytes, err := hex.DecodeString(params.MinDifficultyTargetHex) 342 if err != nil { 343 return nil, errors.Wrapf(err, "CalcNextDifficultyTarget: Problem computing min difficulty") 344 } 345 var minDiffHash BlockHash 346 copy(minDiffHash[:], minDiffBytes) 347 if lastNode == nil || lastNode.Height <= blocksPerRetarget { 348 return &minDiffHash, nil 349 } 350 351 // If we get here we know we are dealing with a block whose height exceeds 352 // the height of the first difficulty adjustment (that is 353 // lastNode.Height > blocksPerRetarget 354 355 // If we're not at a difficulty retarget point, return the previous 356 // block's difficulty. 357 if lastNode.Height%blocksPerRetarget != 0 { 358 return lastNode.DifficultyTarget, nil 359 } 360 361 // If we get here it means we reached a difficulty retarget point. 362 targetSecs := int64(params.TimeBetweenDifficultyRetargets / time.Second) 363 minRetargetTimeSecs := targetSecs / params.MaxDifficultyRetargetFactor 364 maxRetargetTimeSecs := targetSecs * params.MaxDifficultyRetargetFactor 365 366 firstNodeHeight := lastNode.Height - blocksPerRetarget 367 firstNode := lastNode.Ancestor(firstNodeHeight) 368 if firstNode == nil { 369 return nil, fmt.Errorf("CalcNextDifficultyTarget: Problem getting block at "+ 370 "beginning of retarget interval at height %d during retarget from height %d", 371 firstNodeHeight, lastNode.Height) 372 } 373 374 actualTimeDiffSecs := int64(lastNode.Header.TstampSecs - firstNode.Header.TstampSecs) 375 clippedTimeDiffSecs := actualTimeDiffSecs 376 if actualTimeDiffSecs < minRetargetTimeSecs { 377 clippedTimeDiffSecs = minRetargetTimeSecs 378 } else if actualTimeDiffSecs > maxRetargetTimeSecs { 379 clippedTimeDiffSecs = maxRetargetTimeSecs 380 } 381 382 numerator := new(big.Int).Mul( 383 HashToBigint(lastNode.DifficultyTarget), 384 big.NewInt(clippedTimeDiffSecs)) 385 nextDiffBigint := numerator.Div(numerator, big.NewInt(targetSecs)) 386 387 // If the next difficulty is nil or if it passes the min difficulty, set it equal 388 // to the min difficulty. This should never happen except for weird instances where 389 // we're testing edge cases. 390 if nextDiffBigint == nil || nextDiffBigint.Cmp(HashToBigint(&minDiffHash)) > 0 { 391 nextDiffBigint = HashToBigint(&minDiffHash) 392 } 393 394 return BigintToHash(nextDiffBigint), nil 395 } 396 397 type OrphanBlock struct { 398 Block *MsgDeSoBlock 399 Hash *BlockHash 400 } 401 402 type Blockchain struct { 403 db *badger.DB 404 postgres *Postgres 405 timeSource chainlib.MedianTimeSource 406 trustedBlockProducerPublicKeys map[PkMapKey]bool 407 trustedBlockProducerStartHeight uint64 408 params *DeSoParams 409 eventManager *EventManager 410 // Returns true once all of the housekeeping in creating the 411 // blockchain is complete. This includes setting up the genesis block. 412 isInitialized bool 413 414 // Protects most of the fields below this point. 415 ChainLock deadlock.RWMutex 416 417 // These should only be accessed after acquiring the ChainLock. 418 // 419 // An in-memory index of the "tree" of blocks we are currently aware of. 420 // This index includes forks and side-chains but does not include unconnectedTxns. 421 blockIndex map[BlockHash]*BlockNode 422 // An in-memory slice of the blocks on the main chain only. The end of 423 // this slice is the best known tip that we have at any given time. 424 bestChain []*BlockNode 425 bestChainMap map[BlockHash]*BlockNode 426 427 bestHeaderChain []*BlockNode 428 bestHeaderChainMap map[BlockHash]*BlockNode 429 430 // We keep track of orphan blocks with the following data structures. Orphans 431 // are not written to disk and are only cached in memory. Moreover we only keep 432 // up to MaxOrphansInMemory of them in order to prevent memory exhaustion. 433 orphanList *list.List 434 } 435 436 func (bc *Blockchain) CopyBlockIndex() map[BlockHash]*BlockNode { 437 newBlockIndex := make(map[BlockHash]*BlockNode) 438 for kk, vv := range bc.blockIndex { 439 newBlockIndex[kk] = vv 440 } 441 return newBlockIndex 442 } 443 444 func (bc *Blockchain) CopyBestChain() ([]*BlockNode, map[BlockHash]*BlockNode) { 445 newBestChain := []*BlockNode{} 446 newBestChainMap := make(map[BlockHash]*BlockNode) 447 newBestChain = append(newBestChain, bc.bestChain...) 448 for kk, vv := range bc.bestChainMap { 449 newBestChainMap[kk] = vv 450 } 451 452 return newBestChain, newBestChainMap 453 } 454 455 func (bc *Blockchain) CopyBestHeaderChain() ([]*BlockNode, map[BlockHash]*BlockNode) { 456 newBestChain := []*BlockNode{} 457 newBestChainMap := make(map[BlockHash]*BlockNode) 458 newBestChain = append(newBestChain, bc.bestHeaderChain...) 459 for kk, vv := range bc.bestHeaderChainMap { 460 newBestChainMap[kk] = vv 461 } 462 463 return newBestChain, newBestChainMap 464 } 465 466 // _initChain initializes the in-memory data structures for the Blockchain object 467 // by reading from the database. If the database has never been initialized before 468 // then _initChain will initialize it to contain only the genesis block before 469 // proceeding to read from it. 470 func (bc *Blockchain) _initChain() error { 471 // See if we have a best chain hash stored in the db. 472 var bestBlockHash *BlockHash 473 if bc.postgres != nil { 474 chain := bc.postgres.GetChain(MAIN_CHAIN) 475 if chain != nil { 476 bestBlockHash = chain.TipHash 477 } 478 } else { 479 bestBlockHash = DbGetBestHash(bc.db, ChainTypeDeSoBlock) 480 } 481 // When we load up initially, the best header hash is just the tip of the best 482 // block chain, since we don't store headers for which we don't have corresponding 483 // blocks. 484 bestHeaderHash := bestBlockHash 485 486 // If there is no best chain hash in the db then it means we've never 487 // initialized anything so take the time to do it now. 488 if bestBlockHash == nil || bestHeaderHash == nil { 489 var err error 490 491 if bc.postgres != nil { 492 err = bc.postgres.InitGenesisBlock(bc.params, bc.db) 493 } else { 494 err = InitDbWithDeSoGenesisBlock(bc.params, bc.db, bc.eventManager) 495 } 496 if err != nil { 497 return errors.Wrapf(err, "_initChain: Problem initializing db with genesis block") 498 } 499 500 // After initializing the db to contain only the genesis block, 501 // set the best hash we're aware of equal to it. 502 bestBlockHash = MustDecodeHexBlockHash(bc.params.GenesisBlockHashHex) 503 bestHeaderHash = bestBlockHash 504 } 505 506 // At this point we should have bestHashes set and the db should have been 507 // initialized to contain a block index and a best chain that we can read 508 // in. 509 510 // Read in the nodes using the (<height, hash> -> node) index. The nodes will 511 // be iterated over starting with height 0 and ending with the height of the 512 // longest chain we're aware of. As we go, check that all the blocks connect 513 // to previous blocks we've read in and error if they don't. This works because 514 // reading blocks in height order as we do here ensures that we'll always 515 // add a block's parents, if they exist, before adding the block itself. 516 var err error 517 if bc.postgres != nil { 518 bc.blockIndex, err = bc.postgres.GetBlockIndex() 519 } else { 520 bc.blockIndex, err = GetBlockIndex(bc.db, false /*bitcoinNodes*/) 521 } 522 if err != nil { 523 return errors.Wrapf(err, "_initChain: Problem reading block index from db") 524 } 525 526 // At this point the blockIndex should contain a full node tree with all 527 // nodes pointing to valid parent nodes. 528 { 529 // Find the tip node with the best node hash. 530 tipNode := bc.blockIndex[*bestBlockHash] 531 if tipNode == nil { 532 return fmt.Errorf("_initChain(block): Best hash (%#v) not found in block index", bestBlockHash) 533 } 534 535 // Walk back from the best node to the genesis block and store them all 536 // in bestChain. 537 bc.bestChain, err = GetBestChain(tipNode, bc.blockIndex) 538 if err != nil { 539 return errors.Wrapf(err, "_initChain(block): Problem reading best chain from db") 540 } 541 for _, bestChainNode := range bc.bestChain { 542 bc.bestChainMap[*bestChainNode.Hash] = bestChainNode 543 } 544 } 545 546 // TODO: This code is a bit repetitive but this seemed clearer than factoring it out. 547 { 548 // Find the tip node with the best node hash. 549 tipNode := bc.blockIndex[*bestHeaderHash] 550 if tipNode == nil { 551 return fmt.Errorf("_initChain(header): Best hash (%#v) not found in block index", bestHeaderHash) 552 } 553 554 // Walk back from the best node to the genesis block and store them all 555 // in bestChain. 556 bc.bestHeaderChain, err = GetBestChain(tipNode, bc.blockIndex) 557 if err != nil { 558 return errors.Wrapf(err, "_initChain(header): Problem reading best chain from db") 559 } 560 for _, bestHeaderChainNode := range bc.bestHeaderChain { 561 bc.bestHeaderChainMap[*bestHeaderChainNode.Hash] = bestHeaderChainNode 562 } 563 } 564 565 bc.isInitialized = true 566 567 return nil 568 } 569 570 // NewBlockchain returns a new blockchain object. It initializes some in-memory 571 // data structures by reading from the db. It also initializes the db if it hasn't 572 // been initialized in the past. This function should only be called once per 573 // db, and one should never run two blockhain objects over the same db at the same 574 // time as they will likely step on each other and become inconsistent. 575 func NewBlockchain( 576 trustedBlockProducerPublicKeyStrs []string, 577 trustedBlockProducerStartHeight uint64, 578 params *DeSoParams, 579 timeSource chainlib.MedianTimeSource, 580 db *badger.DB, 581 postgres *Postgres, 582 eventManager *EventManager, 583 ) (*Blockchain, error) { 584 585 trustedBlockProducerPublicKeys := make(map[PkMapKey]bool) 586 for _, keyStr := range trustedBlockProducerPublicKeyStrs { 587 pkBytes, _, err := Base58CheckDecode(keyStr) 588 if err != nil { 589 return nil, fmt.Errorf("Error decoding trusted block producer public key: %v", err) 590 } 591 trustedBlockProducerPublicKeys[MakePkMapKey(pkBytes)] = true 592 } 593 594 bc := &Blockchain{ 595 db: db, 596 postgres: postgres, 597 timeSource: timeSource, 598 trustedBlockProducerPublicKeys: trustedBlockProducerPublicKeys, 599 trustedBlockProducerStartHeight: trustedBlockProducerStartHeight, 600 params: params, 601 eventManager: eventManager, 602 603 blockIndex: make(map[BlockHash]*BlockNode), 604 bestChainMap: make(map[BlockHash]*BlockNode), 605 606 bestHeaderChainMap: make(map[BlockHash]*BlockNode), 607 608 orphanList: list.New(), 609 } 610 611 // Hold the chain lock whenever we modify this object from now on. 612 bc.ChainLock.Lock() 613 defer bc.ChainLock.Unlock() 614 615 // Initialize all the in-memory data structures by loading our state 616 // from the db. This function creates an initial database state containing 617 // only the genesis block if we've never initialized the database before. 618 if err := bc._initChain(); err != nil { 619 return nil, errors.Wrapf(err, "NewBlockchain: ") 620 } 621 622 return bc, nil 623 } 624 625 // log2FloorMasks defines the masks to use when quickly calculating 626 // floor(log2(x)) in a constant log2(32) = 5 steps, where x is a uint32, using 627 // shifts. They are derived from (2^(2^x) - 1) * (2^(2^x)), for x in 4..0. 628 var log2FloorMasks = []uint32{0xffff0000, 0xff00, 0xf0, 0xc, 0x2} 629 630 // fastLog2Floor calculates and returns floor(log2(x)) in a constant 5 steps. 631 func fastLog2Floor(n uint32) uint8 { 632 rv := uint8(0) 633 exponent := uint8(16) 634 for i := 0; i < 5; i++ { 635 if n&log2FloorMasks[i] != 0 { 636 rv += exponent 637 n >>= exponent 638 } 639 exponent >>= 1 640 } 641 return rv 642 } 643 644 // locateInventory returns the node of the block after the first known block in 645 // the locator along with the number of subsequent nodes needed to either reach 646 // the provided stop hash or the provided max number of entries. 647 // 648 // In addition, there are two special cases: 649 // 650 // - When no locators are provided, the stop hash is treated as a request for 651 // that block, so it will either return the node associated with the stop hash 652 // if it is known, or nil if it is unknown 653 // - When locators are provided, but none of them are known, nodes starting 654 // after the genesis block will be returned 655 // 656 // This is primarily a helper function for the locateBlocks and locateHeaders 657 // functions. 658 // 659 // This function MUST be called with the chain state lock held (for reads). 660 func locateInventory(locator []*BlockHash, stopHash *BlockHash, maxEntries uint32, 661 blockIndex map[BlockHash]*BlockNode, bestChainList []*BlockNode, 662 bestChainMap map[BlockHash]*BlockNode) (*BlockNode, uint32) { 663 664 // There are no block locators so a specific block is being requested 665 // as identified by the stop hash. 666 stopNode, stopNodeExists := blockIndex[*stopHash] 667 if len(locator) == 0 { 668 if !stopNodeExists { 669 // No blocks with the stop hash were found so there is 670 // nothing to do. 671 return nil, 0 672 } 673 return stopNode, 1 674 } 675 676 // Find the most recent locator block hash in the main chain. In the 677 // case none of the hashes in the locator are in the main chain, fall 678 // back to the genesis block. 679 startNode := bestChainList[0] 680 for _, hash := range locator { 681 node, bestChainContainsNode := bestChainMap[*hash] 682 if bestChainContainsNode { 683 startNode = node 684 break 685 } 686 } 687 688 // Start at the block after the most recently known block. When there 689 // is no next block it means the most recently known block is the tip of 690 // the best chain, so there is nothing more to do. 691 nextNodeHeight := uint32(startNode.Header.Height) + 1 692 if uint32(len(bestChainList)) <= nextNodeHeight { 693 return nil, 0 694 } 695 startNode = bestChainList[nextNodeHeight] 696 697 // Calculate how many entries are needed. 698 tip := bestChainList[len(bestChainList)-1] 699 total := uint32((tip.Header.Height - startNode.Header.Height) + 1) 700 if stopNodeExists && stopNode.Header.Height >= startNode.Header.Height { 701 702 _, bestChainContainsStopNode := bestChainMap[*stopNode.Hash] 703 if bestChainContainsStopNode { 704 total = uint32((stopNode.Header.Height - startNode.Header.Height) + 1) 705 } 706 } 707 if total > maxEntries { 708 total = maxEntries 709 } 710 711 return startNode, total 712 } 713 714 // locateHeaders returns the headers of the blocks after the first known block 715 // in the locator until the provided stop hash is reached, or up to the provided 716 // max number of block headers. 717 // 718 // See the comment on the exported function for more details on special cases. 719 // 720 // This function MUST be called with the ChainLock held (for reads). 721 func locateHeaders(locator []*BlockHash, stopHash *BlockHash, maxHeaders uint32, 722 blockIndex map[BlockHash]*BlockNode, bestChainList []*BlockNode, 723 bestChainMap map[BlockHash]*BlockNode) []*MsgDeSoHeader { 724 725 // Find the node after the first known block in the locator and the 726 // total number of nodes after it needed while respecting the stop hash 727 // and max entries. 728 node, total := locateInventory(locator, stopHash, maxHeaders, 729 blockIndex, bestChainList, bestChainMap) 730 if total == 0 { 731 return nil 732 } 733 734 // Populate and return the found headers. 735 headers := make([]*MsgDeSoHeader, 0, total) 736 for ii := uint32(0); ii < total; ii++ { 737 headers = append(headers, node.Header) 738 if uint32(len(headers)) == total { 739 break 740 } 741 node = bestChainList[node.Header.Height+1] 742 } 743 return headers 744 } 745 746 // LocateBestBlockChainHeaders returns the headers of the blocks after the first known block 747 // in the locator until the provided stop hash is reached, or up to a max of 748 // wire.MaxBlockHeadersPerMsg headers. Note that it returns the best headers 749 // considering only headers for which we have blocks (that is, it considers the 750 // best *block* chain we have rather than the best *header* chain). This is 751 // the correct thing to do because in general this function is called in order 752 // to serve a response to a peer's GetHeaders request. 753 // 754 // In addition, there are two special cases: 755 // 756 // - When no locators are provided, the stop hash is treated as a request for 757 // that header, so it will either return the header for the stop hash itself 758 // if it is known, or nil if it is unknown 759 // - When locators are provided, but none of them are known, headers starting 760 // after the genesis block will be returned 761 // 762 // This function is safe for concurrent access. 763 func (bc *Blockchain) LocateBestBlockChainHeaders(locator []*BlockHash, stopHash *BlockHash) []*MsgDeSoHeader { 764 headers := locateHeaders(locator, stopHash, MaxHeadersPerMsg, 765 bc.blockIndex, bc.bestChain, bc.bestChainMap) 766 767 return headers 768 } 769 770 // LatestLocator returns a block locator for the passed block node. The passed 771 // node can be nil in which case the block locator for the current tip 772 // associated with the view will be returned. 773 // 774 // BlockLocator is used to help locate a specific block. The algorithm for 775 // building the block locator is to add the hashes in reverse order until 776 // the genesis block is reached. In order to keep the list of locator hashes 777 // to a reasonable number of entries, first the most recent previous 12 block 778 // hashes are added, then the step is doubled each loop iteration to 779 // exponentially decrease the number of hashes as a function of the distance 780 // from the block being located. 781 // 782 // For example, assume a block chain with a side chain as depicted below: 783 // genesis -> 1 -> 2 -> ... -> 15 -> 16 -> 17 -> 18 784 // \-> 16a -> 17a 785 // 786 // The block locator for block 17a would be the hashes of blocks: 787 // [17a 16a 15 14 13 12 11 10 9 8 7 6 4 genesis] 788 // 789 // Caller is responsible for acquiring the ChainLock before calling this function. 790 func (bc *Blockchain) LatestLocator(tip *BlockNode) []*BlockHash { 791 792 // Calculate the max number of entries that will ultimately be in the 793 // block locator. See the description of the algorithm for how these 794 // numbers are derived. 795 var maxEntries uint8 796 if tip.Header.Height <= 12 { 797 maxEntries = uint8(tip.Header.Height) + 1 798 } else { 799 // Requested hash itself + previous 10 entries + genesis block. 800 // Then floor(log2(height-10)) entries for the skip portion. 801 adjustedHeight := uint32(tip.Header.Height) - 10 802 maxEntries = 12 + fastLog2Floor(adjustedHeight) 803 } 804 locator := make([]*BlockHash, 0, maxEntries) 805 806 step := int32(1) 807 for tip != nil { 808 locator = append(locator, tip.Hash) 809 810 // Nothing more to add once the genesis block has been added. 811 if tip.Header.Height == 0 { 812 break 813 } 814 815 // Calculate height of previous node to include ensuring the 816 // final node is the genesis block. 817 height := int32(tip.Header.Height) - step 818 if height < 0 { 819 height = 0 820 } 821 822 // When the node is in the current chain view, all of its 823 // ancestors must be too, so use a much faster O(1) lookup in 824 // that case. Otherwise, fall back to walking backwards through 825 // the nodes of the other chain to the correct ancestor. 826 if _, exists := bc.bestHeaderChainMap[*tip.Hash]; exists { 827 tip = bc.bestHeaderChain[height] 828 } else { 829 tip = tip.Ancestor(uint32(height)) 830 } 831 832 // Once 11 entries have been included, start doubling the 833 // distance between included hashes. 834 if len(locator) > 10 { 835 step *= 2 836 } 837 } 838 839 return locator 840 } 841 842 func (bc *Blockchain) HeaderLocatorWithNodeHash(blockHash *BlockHash) ([]*BlockHash, error) { 843 node, exists := bc.blockIndex[*blockHash] 844 if !exists { 845 return nil, fmt.Errorf("Blockchain.HeaderLocatorWithNodeHash: Node for hash %v is not in our blockIndex", blockHash) 846 } 847 848 return bc.LatestLocator(node), nil 849 } 850 851 // LatestHeaderLocator calls LatestLocator in order to fetch a locator 852 // for the best header chain. 853 func (bc *Blockchain) LatestHeaderLocator() []*BlockHash { 854 headerTip := bc.headerTip() 855 856 return bc.LatestLocator(headerTip) 857 } 858 859 func (bc *Blockchain) GetBlockNodesToFetch( 860 numBlocks int, _maxHeight int, blocksToIgnore map[BlockHash]bool) []*BlockNode { 861 862 // Get the tip of the main block chain. 863 bestBlockTip := bc.blockTip() 864 865 // If the maxHeight is set to < 0, then we don't want to use it as a constraint. 866 maxHeight := uint32(math.MaxUint32) 867 if _maxHeight >= 0 { 868 maxHeight = uint32(_maxHeight) 869 } 870 871 // If the tip of the best block chain is in the main header chain, make that 872 // the start point for our fetch. 873 headerNodeStart, blockTipExistsInBestHeaderChain := bc.bestHeaderChainMap[*bestBlockTip.Hash] 874 if !blockTipExistsInBestHeaderChain { 875 // If the hash of the tip of the best blockchain is not in the best header chain, then 876 // this is a case where the header chain has forked off from the best block 877 // chain. In this situation, the best header chain is taken as the source of truth 878 // and so we iterate backward over the best header chain starting at the tip 879 // until we find the first block that has StatusBlockProcessed. Then we fetch 880 // blocks starting from there. Note that, at minimum, the genesis block has 881 // StatusBlockProcessed so this loop is guaranteed to terminate successfully. 882 headerNodeStart = bc.headerTip() 883 for headerNodeStart != nil && (headerNodeStart.Status&StatusBlockProcessed) == 0 { 884 headerNodeStart = headerNodeStart.Parent 885 } 886 887 if headerNodeStart == nil { 888 // If for some reason we ended up with the headerNode being nil, log 889 // an error and set it to the genesis block. 890 glog.Errorf("GetBlockToFetch: headerNode was nil after iterating " + 891 "backward through best header chain; using genesis block") 892 headerNodeStart = bc.bestHeaderChain[0] 893 } 894 } 895 896 // At this point, headerNodeStart should point to a node in the best header 897 // chain that has StatusBlockProcessed set. As such, the blocks we need to 898 // fetch are those right after this one. Fetch the desired number. 899 currentHeight := headerNodeStart.Height + 1 900 blockNodesToFetch := []*BlockNode{} 901 heightLimit := maxHeight 902 if heightLimit >= uint32(len(bc.bestHeaderChain)) { 903 heightLimit = uint32(len(bc.bestHeaderChain) - 1) 904 } 905 for currentHeight <= heightLimit && 906 len(blockNodesToFetch) < numBlocks { 907 908 // Get the current hash and increment the height. 909 currentNode := bc.bestHeaderChain[currentHeight] 910 currentHeight++ 911 912 if _, exists := blocksToIgnore[*currentNode.Hash]; exists { 913 continue 914 } 915 916 blockNodesToFetch = append(blockNodesToFetch, currentNode) 917 } 918 919 // Return the nodes for the blocks we should fetch. 920 return blockNodesToFetch 921 } 922 923 func (bc *Blockchain) HasHeader(headerHash *BlockHash) bool { 924 _, exists := bc.blockIndex[*headerHash] 925 return exists 926 } 927 928 func (bc *Blockchain) HeaderAtHeight(blockHeight uint32) *BlockNode { 929 if blockHeight >= uint32(len(bc.bestHeaderChain)) { 930 return nil 931 } 932 933 return bc.bestHeaderChain[blockHeight] 934 } 935 936 func (bc *Blockchain) HasBlock(blockHash *BlockHash) bool { 937 node, nodeExists := bc.blockIndex[*blockHash] 938 if !nodeExists { 939 glog.V(2).Infof("Blockchain.HasBlock: Node with hash %v does not exist in node index", blockHash) 940 return false 941 } 942 943 if (node.Status & StatusBlockProcessed) == 0 { 944 glog.V(2).Infof("Blockchain.HasBlock: Node %v does not have StatusBlockProcessed so we don't have the block", node) 945 return false 946 } 947 948 // Node exists with StatusBlockProcess set means we have it. 949 return true 950 } 951 952 // Don't need a lock because blocks don't get removed from the db after they're added 953 func (bc *Blockchain) GetBlock(blockHash *BlockHash) *MsgDeSoBlock { 954 blk, err := GetBlock(blockHash, bc.db) 955 if err != nil { 956 glog.V(2).Infof("Blockchain.GetBlock: Failed to fetch node with hash %v from the db: %v", blockHash, err) 957 return nil 958 } 959 960 return blk 961 } 962 963 func (bc *Blockchain) GetBlockAtHeight(height uint32) *MsgDeSoBlock { 964 numBlocks := uint32(len(bc.bestChain)) 965 966 if height >= numBlocks { 967 return nil 968 } 969 970 return bc.GetBlock(bc.bestChain[height].Hash) 971 } 972 973 func (bc *Blockchain) isTipCurrent(tip *BlockNode) bool { 974 minChainWorkBytes, _ := hex.DecodeString(bc.params.MinChainWorkHex) 975 976 // Not current if the cumulative work is below the threshold. 977 if tip.CumWork.Cmp(BytesToBigint(minChainWorkBytes)) < 0 { 978 //glog.V(2).Infof("Blockchain.isTipCurrent: Tip not current because "+ 979 //"CumWork (%v) is less than minChainWorkBytes (%v)", 980 //tip.CumWork, BytesToBigint(minChainWorkBytes)) 981 return false 982 } 983 984 // Not current if the tip has a timestamp older than the maximum 985 // tip age. 986 tipTime := time.Unix(int64(tip.Header.TstampSecs), 0) 987 oldestAllowedTipTime := bc.timeSource.AdjustedTime().Add(-1 * bc.params.MaxTipAge) 988 989 return !tipTime.Before(oldestAllowedTipTime) 990 } 991 992 type SyncState uint8 993 994 const ( 995 // SyncStateSyncingHeaders indicates that our header chain is not current. 996 // This is the state a node will start in when it hasn't downloaded 997 // anything from its peers. Because we always download headers and 998 // validate them before we download blocks, SyncingHeaders implies that 999 // the block tip is also not current yet. 1000 SyncStateSyncingHeaders SyncState = iota 1001 // SyncStateSyncingBlocks indicates that our header chain is current but 1002 // that the block chain we have is not current yet. In particular, it 1003 // means, among other things, that the tip of the block chain is still 1004 // older than max tip age. 1005 SyncStateSyncingBlocks 1006 // SyncStateNeedBlocksss indicates that our header chain is current and our 1007 // block chain is current but that there are headers in our main chain for 1008 // which we have not yet processed blocks. 1009 SyncStateNeedBlocksss 1010 // SyncStateFullyCurrent indicates that our header chain is current and that 1011 // we've fetched all the blocks corresponding to this chain. 1012 SyncStateFullyCurrent 1013 ) 1014 1015 func (ss SyncState) String() string { 1016 switch ss { 1017 case SyncStateSyncingHeaders: 1018 return "SYNCING_HEADERS" 1019 case SyncStateSyncingBlocks: 1020 return "SYNCING_BLOCKS" 1021 case SyncStateNeedBlocksss: 1022 return "NEED_BLOCKS" 1023 case SyncStateFullyCurrent: 1024 return "FULLY_CURRENT" 1025 default: 1026 return fmt.Sprintf("UNRECOGNIZED(%d) - make sure String() is up to date", ss) 1027 } 1028 } 1029 1030 // - Latest block height is after the latest checkpoint (if enabled) 1031 // - Latest block has a timestamp newer than 24 hours ago 1032 // 1033 // This function MUST be called with the ChainLock held (for reads). 1034 func (bc *Blockchain) chainState() SyncState { 1035 // If the header is not current, then we're in the SyncStateSyncingHeaders. 1036 headerTip := bc.headerTip() 1037 if !bc.isTipCurrent(headerTip) { 1038 return SyncStateSyncingHeaders 1039 } 1040 1041 // If the header tip is current but the block tip isn't then we're in 1042 // the SyncStateSyncingBlocks state. 1043 blockTip := bc.blockTip() 1044 if !bc.isTipCurrent(blockTip) { 1045 return SyncStateSyncingBlocks 1046 } 1047 1048 // If the header tip is current and the block tip is current but the block 1049 // tip is not equal to the header tip then we're in SyncStateNeedBlocks. 1050 if *blockTip.Hash != *headerTip.Hash { 1051 return SyncStateNeedBlocksss 1052 } 1053 1054 // If none of the checks above returned it means we're current. 1055 return SyncStateFullyCurrent 1056 } 1057 1058 func (bc *Blockchain) ChainState() SyncState { 1059 return bc.chainState() 1060 } 1061 1062 func (bc *Blockchain) isSyncing() bool { 1063 syncState := bc.chainState() 1064 return syncState == SyncStateSyncingHeaders || syncState == SyncStateSyncingBlocks 1065 } 1066 1067 // headerTip returns the tip of the header chain. Because we fetch headers 1068 // before we fetch blocks, we track a chain for headers as separate from the 1069 // main chain for blocks, which is why separate functions are required for 1070 // each of them. 1071 func (bc *Blockchain) headerTip() *BlockNode { 1072 if len(bc.bestHeaderChain) == 0 { 1073 return nil 1074 } 1075 1076 // Note this should always work because we should have the genesis block 1077 // in here. 1078 return bc.bestHeaderChain[len(bc.bestHeaderChain)-1] 1079 } 1080 1081 func (bc *Blockchain) HeaderTip() *BlockNode { 1082 return bc.headerTip() 1083 } 1084 1085 func (bc *Blockchain) DB() *badger.DB { 1086 return bc.db 1087 } 1088 1089 // blockTip returns the tip of the main block chain. We fetch headers first 1090 // and then, once the header chain looks good, we fetch blocks. As such, we 1091 // store two separate "best" chains: One containing the best headers, and 1092 // the other containing the best blocks. The header chain is essentially a 1093 // trail-blazer, validating headers as fast as it can before later fetching 1094 // blocks for the headers that seem legitimate and adding them to the "real" 1095 // best chain. If, while adding blocks to the best block chain, we realize 1096 // some of the blocks are invalid, the best header chain is then adjusted to 1097 // invalidate and chop off the headers corresponding to those blocks and 1098 // their ancestors so the two generally stay in sync. 1099 func (bc *Blockchain) blockTip() *BlockNode { 1100 var tip *BlockNode 1101 1102 if len(bc.bestChain) == 0 { 1103 return nil 1104 } 1105 1106 tip = bc.bestChain[len(bc.bestChain)-1] 1107 1108 return tip 1109 } 1110 1111 func (bc *Blockchain) BlockTip() *BlockNode { 1112 return bc.blockTip() 1113 } 1114 1115 func (bc *Blockchain) BestChain() []*BlockNode { 1116 return bc.bestChain 1117 } 1118 1119 func (bc *Blockchain) SetBestChain(bestChain []*BlockNode) { 1120 bc.bestChain = bestChain 1121 } 1122 1123 func (bc *Blockchain) SetBestChainMap(bestChain []*BlockNode, bestChainMap map[BlockHash]*BlockNode, blockIndex map[BlockHash]*BlockNode) { 1124 bc.bestChain = bestChain 1125 bc.bestChainMap = bestChainMap 1126 bc.blockIndex = blockIndex 1127 } 1128 1129 func (bc *Blockchain) _validateOrphanBlock(desoBlock *MsgDeSoBlock) error { 1130 // Error if the block is missing a parent hash or header. 1131 if desoBlock.Header == nil { 1132 return fmt.Errorf("_validateOrphanBlock: Block is missing header") 1133 } 1134 parentHash := desoBlock.Header.PrevBlockHash 1135 if parentHash == nil { 1136 return fmt.Errorf("_validateOrphanBlock: Block is missing parent hash") 1137 } 1138 1139 // Check that the block size isn't bigger than the max allowed. This prevents 1140 // an attack vector where someone might try and send us very large orphan blocks in 1141 // an attempt to exhaust our memory. 1142 serializedBlock, err := desoBlock.ToBytes(false) 1143 if err != nil { 1144 return fmt.Errorf("_validateOrphanBlock: Could not serialize block") 1145 } 1146 if uint64(len(serializedBlock)) > bc.params.MaxBlockSizeBytes { 1147 return RuleErrorBlockTooBig 1148 } 1149 1150 // No more validation is needed since the orphan will be properly validated 1151 // if and when we ever end up adding it to our block index either on the main 1152 // chain or on a side chain. 1153 // 1154 // TODO: It would be nice to do some kind of PoW check on unconnectedTxns, but it 1155 // seems useless because anyone who has access to MaxOrphansInMemory orphan 1156 // blocks has the ability to fill our orphan lists with garbage. Put another 1157 // way, a simple PoW check on orphan blocks doesn't seem to increase the cost 1158 // of an attack materially and could have negative effects if e.g. legitimate unconnectedTxns 1159 // earlier in the chain get filtered out because their difficulty is too low. 1160 // Moreover, while being attacked would be a minor inconvenience it doesn't 1161 // stop the node from reaching consensus eventually. So we'll punt on defending 1162 // against it unless/until it actually becomes a problem. 1163 1164 return nil 1165 } 1166 1167 // ProcessOrphanBlock runs some very basic validation on the orphan block and adds 1168 // it to our orphan data structure if it passes. If there are too many orphan blocks 1169 // in our data structure, it also evicts the oldest block to make room for this one. 1170 // 1171 // TODO: Currently we only remove orphan blocks if we have too many. This means in 1172 // a steady state we are potentially keeping MaxOrphansInMemory at all times, which 1173 // is wasteful of resources. Better would be to clean up orphan blocks once they're 1174 // too old or something like that. 1175 func (bc *Blockchain) ProcessOrphanBlock(desoBlock *MsgDeSoBlock, blockHash *BlockHash) error { 1176 err := bc._validateOrphanBlock(desoBlock) 1177 if err != nil { 1178 return errors.Wrapf(err, "ProcessOrphanBlock: Problem validating orphan block") 1179 } 1180 1181 // If this block is already in the orphan list then don't add it. 1182 // 1183 // TODO: We do a basic linear search here because there are so few unconnectedTxns 1184 // in our list. If we want to track more unconnectedTxns in the future we would probably 1185 // want to manage this with a map. 1186 for orphanElem := bc.orphanList.Front(); orphanElem != nil; orphanElem = orphanElem.Next() { 1187 orphanBlock := orphanElem.Value.(*OrphanBlock) 1188 if *orphanBlock.Hash == *blockHash { 1189 return RuleErrorDuplicateOrphan 1190 } 1191 } 1192 1193 // At this point we know we are adding a new orphan to the list. 1194 1195 // If we are at capacity remove an orphan block by simply deleting the front 1196 // element of the orphan list, which is also the oldest orphan. 1197 if bc.orphanList.Len() >= MaxOrphansInMemory { 1198 elemToRemove := bc.orphanList.Front() 1199 bc.orphanList.Remove(elemToRemove) 1200 } 1201 1202 // Add the orphan block to our data structure. We can also assume the orphan 1203 // is not a duplicate and therefore simply add a new entry to the end of the list. 1204 bc.orphanList.PushBack(&OrphanBlock{ 1205 Block: desoBlock, 1206 Hash: blockHash, 1207 }) 1208 1209 return nil 1210 } 1211 1212 func (bc *Blockchain) MarkBlockInvalid(node *BlockNode, errOccurred RuleError) { 1213 // Print a stack trace when this happens 1214 glog.Errorf("MarkBlockInvalid: Block height: %v, Block hash: %v, Error: %v", node.Height, node.Hash, errOccurred) 1215 glog.Error("MarkBlockInvalid: Printing stack trace so error is easy to find: ") 1216 glog.Error(string(debug.Stack())) 1217 1218 // TODO: Not marking blocks invalid makes debugging easier when we hit an issuse, 1219 // and makes it so that we don't need to start the node from scratch when it has a 1220 // problem. But it can also make connecting to a bad peer more risky. In the future, once 1221 // syncing issues are all resolved, bad blocks should be marked as such and probably 1222 // not reprocessed. 1223 glog.Error("MarkBlockInvalid: Not marking blocks invalid for now because it makes debugging easier") 1224 1225 //panic(errOccurred) 1226 1227 // Mark the node's block as invalid. 1228 //node.Status |= StatusBlockValidateFailed 1229 // 1230 //// If this node happens to be in the main header chain, mark 1231 //// every node after this one in the header chain as invalid and 1232 //// remove these nodes from the header chain to keep it in sync. 1233 //if _, nodeInHeaderChain := bc.bestHeaderChainMap[*node.Hash]; nodeInHeaderChain { 1234 // for ii := node.Height; ii < uint32(len(bc.bestHeaderChain)); ii++ { 1235 // // Update the status of the node. Mark it as processed since that's used 1236 // // to determine whether we shoudl fetch the block. 1237 // headerNode := bc.bestHeaderChain[ii] 1238 // headerNode.Status |= (StatusBlockProcessed & StatusBlockValidateFailed) 1239 // if err := PutHeightHashToNodeInfo(headerNode, bc.db, false /*bitcoinNodes*/); err != nil { 1240 // // Log if an error occurs but no need to return it. 1241 // glog.Error(errors.Wrapf(err, 1242 // "MarkBlockInvalid: Problem calling PutHeightHashToNodeInfo on header node")) 1243 // } 1244 // 1245 // delete(bc.bestHeaderChainMap, *headerNode.Hash) 1246 // } 1247 // // Chop off the nodes now that we've updated the status of all of them. 1248 // bc.bestHeaderChain = bc.bestHeaderChain[:node.Height] 1249 // 1250 // // Note there is no need to update the db for the header chain because we don't 1251 // // store nodes for headers on the db. 1252 // 1253 // // At this point the header main chain should be fully updated in memory 1254 // // and in the db to reflect that all nodes from this one onward are invalid 1255 // // and should no longer be considered as part of the main chain. 1256 //} 1257 // 1258 //// Update the node on the db to reflect the status change. 1259 //// 1260 //// Put the node in our node index in the db under the 1261 //// <height uin32, blockhash BlockHash> -> <node info> 1262 //// index. 1263 //if err := PutHeightHashToNodeInfo(node, bc.db, false /*bitcoinNodes*/); err != nil { 1264 // // Log if an error occurs but no need to return it. 1265 // glog.Error(errors.Wrapf(err, 1266 // "MarkBlockInvalid: Problem calling PutHeightHashToNodeInfo")) 1267 //} 1268 } 1269 1270 func _FindCommonAncestor(node1 *BlockNode, node2 *BlockNode) *BlockNode { 1271 if node1 == nil || node2 == nil { 1272 // If either node is nil then there can't be a common ancestor. 1273 return nil 1274 } 1275 1276 // Get the two nodes to be at the same height. 1277 if node1.Height > node2.Height { 1278 node1 = node1.Ancestor(node2.Height) 1279 } else if node1.Height < node2.Height { 1280 node2 = node2.Ancestor(node1.Height) 1281 } 1282 1283 // Iterate the nodes backward until they're either the same or we 1284 // reach the end of the lists. We only need to check node1 for nil 1285 // since they're the same height and we are iterating both back 1286 // in tandem. 1287 for node1 != nil && node1 != node2 { 1288 node1 = node1.Parent 1289 node2 = node2.Parent 1290 } 1291 1292 // By now either node1 == node2 and we found the common ancestor or 1293 // both nodes are nil, which means we reached the bottom without finding 1294 // a common ancestor. 1295 return node1 1296 } 1297 1298 func CheckTransactionSanity(txn *MsgDeSoTxn) error { 1299 // We don't check the sanity of block reward transactions. 1300 if txn.TxnMeta.GetTxnType() == TxnTypeBlockReward { 1301 return nil 1302 } 1303 1304 // All transactions are required to have a valid public key set unless they are one 1305 // of the following: 1306 // - BitcoinExchange transactions don't need a PublicKey because the public key can 1307 // easily be derived from the BitcoinTransaction embedded in the TxnMeta. 1308 requiresPublicKey := txn.TxnMeta.GetTxnType() != TxnTypeBitcoinExchange 1309 if requiresPublicKey { 1310 if len(txn.PublicKey) != btcec.PubKeyBytesLenCompressed { 1311 return errors.Wrapf(RuleErrorTransactionMissingPublicKey, "CheckTransactionSanity: ") 1312 } 1313 } 1314 1315 // Every txn must have at least one input unless it is one of the following 1316 // transaction types. 1317 // - BitcoinExchange transactions will be rejected if they're duplicates in 1318 // spite of the fact that they don't have inputs or outputs. 1319 // 1320 // Note this function isn't run on BlockReward transactions, but that they're 1321 // allowed to have zero inputs as well. In the case of BlockRewards, they could 1322 // have duplicates if someone uses the same public key without changing the 1323 // ExtraNonce field, but this is not the default behavior, and in general the 1324 // only thing a duplicate will do is make a previous transaction invalid, so 1325 // there's not much incentive to do it. 1326 // 1327 // TODO: The above is easily fixed by requiring something like block height to 1328 // be present in the ExtraNonce field. 1329 canHaveZeroInputs := (txn.TxnMeta.GetTxnType() == TxnTypeBitcoinExchange || 1330 txn.TxnMeta.GetTxnType() == TxnTypePrivateMessage) 1331 if len(txn.TxInputs) == 0 && !canHaveZeroInputs { 1332 glog.V(2).Infof("CheckTransactionSanity: Txn needs at least one input: %v", spew.Sdump(txn)) 1333 return RuleErrorTxnMustHaveAtLeastOneInput 1334 } 1335 // Every txn must have at least one output unless it is one of the following transaction 1336 // types. 1337 // - BitcoinExchange transactions are deduped using the hash of the Bitcoin transaction 1338 // embedded in them and having an output adds no value because the output is implied 1339 // by the Bitcoin transaction embedded in it. In particular, the output is automatically 1340 // assumed to be the public key of the the first input in the Bitcoin transaction and 1341 // the fee is automatically assumed to be some percentage of the DeSo being created 1342 // (10bps at the time of this writing). 1343 // 1344 // - TxnTypeCreatorCoin are also ok to have no outputs (e.g. if you spend your whole deso 1345 // balance on a creator coin) 1346 canHaveZeroOutputs := (txn.TxnMeta.GetTxnType() == TxnTypeBitcoinExchange || 1347 txn.TxnMeta.GetTxnType() == TxnTypePrivateMessage || 1348 txn.TxnMeta.GetTxnType() == TxnTypeCreatorCoin) // TODO: add a test for this case 1349 1350 if len(txn.TxOutputs) == 0 && !canHaveZeroOutputs { 1351 glog.V(2).Infof("CheckTransactionSanity: Txn needs at least one output: %v", spew.Sdump(txn)) 1352 return RuleErrorTxnMustHaveAtLeastOneOutput 1353 } 1354 1355 // Loop through the outputs and do a few sanity checks. 1356 var totalOutNanos uint64 1357 for _, txout := range txn.TxOutputs { 1358 // Check that each output's amount is not bigger than the max as a 1359 // sanity check. 1360 if txout.AmountNanos > MaxNanos { 1361 return RuleErrorOutputExceedsMax 1362 } 1363 // Check that this output doesn't overflow the total as a sanity 1364 // check. This is frankly impossible since our maximum limit is 1365 // not close to the max size of a uint64 but check it nevertheless. 1366 if totalOutNanos >= math.MaxUint64-txout.AmountNanos { 1367 return RuleErrorOutputOverflowsTotal 1368 } 1369 // Check that the total isn't bigger than the max supply. 1370 if totalOutNanos > MaxNanos { 1371 return RuleErrorTotalOutputExceedsMax 1372 } 1373 } 1374 1375 // Loop through the inputs and do a few sanity checks. 1376 existingInputs := make(map[DeSoInput]bool) 1377 for _, txin := range txn.TxInputs { 1378 if _, exists := existingInputs[*txin]; exists { 1379 return RuleErrorDuplicateInputs 1380 } 1381 existingInputs[*txin] = true 1382 } 1383 1384 return nil 1385 } 1386 1387 func GetReorgBlocks(tip *BlockNode, newNode *BlockNode) (_commonAncestor *BlockNode, _detachNodes []*BlockNode, _attachNodes []*BlockNode) { 1388 // Find the common ancestor of this block and the main header chain. 1389 commonAncestor := _FindCommonAncestor(tip, newNode) 1390 // Log a warning if the reorg is going to be a big one. 1391 numBlocks := tip.Height - commonAncestor.Height 1392 if numBlocks > 10 { 1393 glog.Warningf("GetReorgBlocks: Proceeding with reorg of (%d) blocks from "+ 1394 "block (%v) at height (%d) to block (%v) at height of (%d)", 1395 numBlocks, tip, tip.Height, newNode, newNode.Height) 1396 } 1397 1398 // Get the blocks to detach. Start at the tip and work backwards to the 1399 // common ancestor (but don't include the common ancestor since we don't 1400 // need to roll that back). 1401 // 1402 // detachBlocks will have the current tip as its first element and parents 1403 // of the tip thereafter. 1404 detachBlocks := []*BlockNode{} 1405 for currentBlock := tip; *currentBlock.Hash != *commonAncestor.Hash; currentBlock = currentBlock.Parent { 1406 detachBlocks = append(detachBlocks, currentBlock) 1407 } 1408 1409 // Get the blocks to attach. Start at the new node and work backwards to 1410 // the common ancestor (but don't include the common ancestor since we'll 1411 // be using it as the new tip after we detach all the blocks from the current 1412 // tip). 1413 // 1414 // attachNodes will have the new node as its first element and work back to 1415 // the node right after the common ancestor as its last element. 1416 attachBlocks := []*BlockNode{} 1417 for currentBlock := newNode; *currentBlock.Hash != *commonAncestor.Hash; currentBlock = currentBlock.Parent { 1418 attachBlocks = append(attachBlocks, currentBlock) 1419 } 1420 // Reverse attachBlocks so that the node right after the common ancestor 1421 // will be the first element and the node at the end of the list will be 1422 // the new node. 1423 for i, j := 0, len(attachBlocks)-1; i < j; i, j = i+1, j-1 { 1424 attachBlocks[i], attachBlocks[j] = attachBlocks[j], attachBlocks[i] 1425 } 1426 1427 return commonAncestor, detachBlocks, attachBlocks 1428 } 1429 1430 func updateBestChainInMemory(mainChainList []*BlockNode, mainChainMap map[BlockHash]*BlockNode, detachBlocks []*BlockNode, attachBlocks []*BlockNode) ( 1431 chainList []*BlockNode, chainMap map[BlockHash]*BlockNode) { 1432 1433 // Remove the nodes we detached from the end of the best chain node list. 1434 tipIndex := len(mainChainList) - 1 1435 for blockOffset := 0; blockOffset < len(detachBlocks); blockOffset++ { 1436 blockIndex := tipIndex - blockOffset 1437 delete(mainChainMap, *mainChainList[blockIndex].Hash) 1438 } 1439 mainChainList = mainChainList[:len(mainChainList)-len(detachBlocks)] 1440 1441 // Add the nodes we attached to the end of the list. Note that this loop iterates 1442 // forward because because attachBlocks has the node right after the common ancestor 1443 // first, with the new tip at the end. 1444 for _, attachNode := range attachBlocks { 1445 mainChainList = append(mainChainList, attachNode) 1446 mainChainMap[*attachNode.Hash] = attachNode 1447 } 1448 1449 return mainChainList, mainChainMap 1450 } 1451 1452 // Caller must acquire the ChainLock for writing prior to calling this. 1453 func (bc *Blockchain) processHeader(blockHeader *MsgDeSoHeader, headerHash *BlockHash) (_isMainChain bool, _isOrphan bool, _err error) { 1454 // Start by checking if the header already exists in our node 1455 // index. If it does, then return an error. We should generally 1456 // expect that processHeader will only be called on headers we 1457 // haven't seen before. 1458 _, nodeExists := bc.blockIndex[*headerHash] 1459 if nodeExists { 1460 return false, false, HeaderErrorDuplicateHeader 1461 } 1462 1463 // If we're here then it means we're processing a header we haven't 1464 // seen before. 1465 1466 // Reject the header if it is more than N seconds in the future. 1467 tstampDiff := int64(blockHeader.TstampSecs) - bc.timeSource.AdjustedTime().Unix() 1468 if tstampDiff > int64(bc.params.MaxTstampOffsetSeconds) { 1469 glog.V(1).Infof("HeaderErrorBlockTooFarInTheFuture: tstampDiff %d > "+ 1470 "MaxTstampOffsetSeconds %d. blockHeader.TstampSecs=%d; adjustedTime=%d", 1471 tstampDiff, bc.params.MaxTstampOffsetSeconds, blockHeader.TstampSecs, 1472 bc.timeSource.AdjustedTime().Unix()) 1473 return false, false, HeaderErrorBlockTooFarInTheFuture 1474 } 1475 1476 // Try to find this header's parent in our block index. 1477 // If we can't find the parent then this header is an orphan and we 1478 // can return early because we don't process unconnectedTxns. 1479 // TODO: Should we just return an error if the header is an orphan? 1480 if blockHeader.PrevBlockHash == nil { 1481 return false, false, HeaderErrorNilPrevHash 1482 } 1483 parentNode, parentNodeExists := bc.blockIndex[*blockHeader.PrevBlockHash] 1484 if !parentNodeExists { 1485 // This block is an orphan if its parent doesn't exist and we don't 1486 // process unconnectedTxns. 1487 return false, true, nil 1488 } 1489 1490 // If the parent node is invalid then this header is invalid as well. Note that 1491 // if the parent node exists then its header must either be Validated or 1492 // ValidateFailed. 1493 parentHeader := parentNode.Header 1494 if parentHeader == nil || (parentNode.Status&(StatusHeaderValidateFailed|StatusBlockValidateFailed)) != 0 { 1495 return false, false, errors.Wrapf( 1496 HeaderErrorInvalidParent, "Parent header: %v, Status check: %v, Parent node status: %v, Parent node header: %v", 1497 parentHeader, (parentNode.Status&(StatusHeaderValidateFailed|StatusBlockValidateFailed)) != 0, 1498 parentNode.Status, 1499 parentNode.Header) 1500 } 1501 1502 // Verify that the height is one greater than the parent. 1503 prevHeight := parentHeader.Height 1504 if blockHeader.Height != prevHeight+1 { 1505 glog.Errorf("processHeader: Height of block (=%d) is not equal to one greater "+ 1506 "than the parent height (=%d)", blockHeader.Height, prevHeight) 1507 return false, false, HeaderErrorHeightInvalid 1508 } 1509 1510 // Make sure the block timestamp is greater than the previous block's timestamp. 1511 // Note Bitcoin checks that the timestamp is greater than the median 1512 // of the last 11 blocks. While this seems to work for Bitcoin for now it seems 1513 // vulnerable to a "time warp" attack (requires 51%) and 1514 // we can do a little better by forcing a harder constraint of making 1515 // sure a timestamp is larger than the of the previous block. It seems 1516 // the only real downside of this is some complexity on the miner side 1517 // of having to account for what happens if a block appears that is from 1518 // some nearby time in the future rather than the current time. But this 1519 // burden seems worth it in order to 1520 // preclude a known and fairly damaging attack from being possible. Moreover, 1521 // while there are more complicated schemes to fight other attacks based on 1522 // timestamp manipulation, their benefits seem marginal and not worth the 1523 // added complexity they entail for now. 1524 // 1525 // Discussion of time warp attack and potential fixes for BTC: 1526 // https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-August/016342.html 1527 // Discussion of more complex attacks and potential fixes: 1528 // https://github.com/zawy12/difficulty-algorithms/issues/30 1529 // 1530 // TODO: Consider a per-block difficulty adjustment scheme like Ethereum has. 1531 // This commentary is useful to consider with regard to that: 1532 // https://github.com/zawy12/difficulty-algorithms/issues/45 1533 if blockHeader.TstampSecs <= parentHeader.TstampSecs { 1534 glog.Warningf("processHeader: Rejecting header because timestamp %v is "+ 1535 "before timestamp of previous block %v", 1536 time.Unix(int64(blockHeader.TstampSecs), 0), 1537 time.Unix(int64(parentHeader.TstampSecs), 0)) 1538 return false, false, HeaderErrorTimestampTooEarly 1539 } 1540 1541 // Check that the proof of work beats the difficulty as calculated from 1542 // the parent block. Note that if the parent block is in the block index 1543 // then it has necessarily had its difficulty validated, and so using it to 1544 // do this check makes sense. 1545 diffTarget, err := CalcNextDifficultyTarget( 1546 parentNode, blockHeader.Version, bc.params) 1547 if err != nil { 1548 return false, false, errors.Wrapf(err, 1549 "ProcessBlock: Problem computing difficulty "+ 1550 "target from parent block %s", hex.EncodeToString(parentNode.Hash[:])) 1551 } 1552 diffTargetBigint := HashToBigint(diffTarget) 1553 blockHashBigint := HashToBigint(headerHash) 1554 if diffTargetBigint.Cmp(blockHashBigint) < 0 { 1555 return false, false, 1556 errors.Wrapf(HeaderErrorBlockDifficultyAboveTarget, "Target: %v, Actual: %v", diffTarget, headerHash) 1557 } 1558 1559 // At this point the header seems sane so we store it in the db and add 1560 // it to our in-memory block index. Note we're not doing this atomically. 1561 // Worst-case, we have a block in our db with no pointer to it in our index, 1562 // which isn't a big deal. 1563 // 1564 // Note in the calculation of CumWork below we are adding the work specified 1565 // in the difficulty *target* rather than the work actually done to mine the 1566 // block. There is a very good reason for this, which is that it materially 1567 // increases a miner's incentive to reveal their block immediately after it's 1568 // been mined as opposed to try and play games where they withhold their block 1569 // and try to mine on top of it before revealing it to everyone. 1570 newWork := BytesToBigint(ExpectedWorkForBlockHash(diffTarget)[:]) 1571 cumWork := newWork.Add(newWork, parentNode.CumWork) 1572 newNode := NewBlockNode( 1573 parentNode, 1574 headerHash, 1575 uint32(blockHeader.Height), 1576 diffTarget, 1577 cumWork, 1578 blockHeader, 1579 StatusHeaderValidated) 1580 1581 // Note that we don't store a node for this header on the db until we have downloaded 1582 // a corresponding block. This has the effect of preventing us against disk-fill 1583 // attacks. If we instead stored headers on the db then we'd have to deal with an 1584 // attack that looks as follows: 1585 // - Attacker makes us download a lot of low-difficulty headers until we eventually 1586 // get current and disconnect because the chainwork is too low (having stored all 1587 // of those header nodes on the db). 1588 // - Attacker repeats this over and over again until our db on disk is really full. 1589 // 1590 // The above is mitigated because we don't download blocks until we have a header chain 1591 // with enough work, which means we won't store anything that doesn't have a lot of work 1592 // built on it. 1593 1594 // If all went well with storing the header, set it in our in-memory 1595 // index. If we're still syncing then it's safe to just set it. Otherwise, we 1596 // need to make a copy first since there could be some concurrency issues. 1597 if bc.isSyncing() { 1598 bc.blockIndex[*newNode.Hash] = newNode 1599 } else { 1600 newBlockIndex := bc.CopyBlockIndex() 1601 newBlockIndex[*newNode.Hash] = newNode 1602 bc.blockIndex = newBlockIndex 1603 } 1604 1605 // Update the header chain if this header has more cumulative work than 1606 // the header chain's tip. Note that we can assume all ancestors of this 1607 // header are valid at this point. 1608 isMainChain := false 1609 headerTip := bc.headerTip() 1610 if headerTip.CumWork.Cmp(newNode.CumWork) < 0 { 1611 isMainChain = true 1612 1613 _, detachBlocks, attachBlocks := GetReorgBlocks(headerTip, newNode) 1614 bc.bestHeaderChain, bc.bestHeaderChainMap = updateBestChainInMemory( 1615 bc.bestHeaderChain, bc.bestHeaderChainMap, detachBlocks, attachBlocks) 1616 1617 // Note that we don't store the best header hash here and so this is an 1618 // in-memory-only adjustment. See the comment above on preventing attacks. 1619 } 1620 1621 return isMainChain, false, nil 1622 } 1623 1624 // ProcessHeader is a wrapper around processHeader, which does the leg-work, that 1625 // acquires the ChainLock first. 1626 func (bc *Blockchain) ProcessHeader(blockHeader *MsgDeSoHeader, headerHash *BlockHash) (_isMainChain bool, _isOrphan bool, _err error) { 1627 bc.ChainLock.Lock() 1628 defer bc.ChainLock.Unlock() 1629 1630 return bc.processHeader(blockHeader, headerHash) 1631 } 1632 1633 // Note: It is the caller's responsibility to ensure that the BitcoinManager is 1634 // time-current prior to calling ProcessBlock on any transactions that require the 1635 // BitcoinManager for validation (e.g. BitcoinExchange transactions). Failure to 1636 // do so will cause ProcessBlock to error on blocks that could otherwise be valid 1637 // if a time-current BitcoinManager were available. If it is known for sure that 1638 // no BitcoinExchange transactions need to be validated then it is OK for the 1639 // BitcoinManager to not be time-current and even for it to be nil entirely. This 1640 // is useful e.g. for tests where we want to exercise ProcessBlock without setting 1641 // up a time-current BitcoinManager. 1642 func (bc *Blockchain) ProcessBlock(desoBlock *MsgDeSoBlock, verifySignatures bool) (_isMainChain bool, _isOrphan bool, _err error) { 1643 // TODO: Move this to be more isolated. 1644 bc.ChainLock.Lock() 1645 defer bc.ChainLock.Unlock() 1646 1647 if desoBlock == nil { 1648 return false, false, fmt.Errorf("ProcessBlock: Block is nil") 1649 } 1650 1651 // Start by getting and validating the block's header. 1652 blockHeader := desoBlock.Header 1653 if blockHeader == nil { 1654 return false, false, fmt.Errorf("ProcessBlock: Block header was nil") 1655 } 1656 blockHash, err := blockHeader.Hash() 1657 if err != nil { 1658 return false, false, errors.Wrapf(err, "ProcessBlock: Problem computing block hash") 1659 } 1660 // If a trusted block producer public key is set, then we only accept blocks 1661 // if they have been signed by one of these public keys. 1662 if len(bc.trustedBlockProducerPublicKeys) > 0 { 1663 if blockHeader.Height >= bc.trustedBlockProducerStartHeight { 1664 if desoBlock.BlockProducerInfo == nil || 1665 desoBlock.BlockProducerInfo.Signature == nil { 1666 1667 return false, false, errors.Wrapf(RuleErrorMissingBlockProducerSignature, 1668 "ProcessBlock: Block signature is required since "+ 1669 "--trusted_block_producer_public_keys is set *and* block height "+ 1670 "%v is >= --trusted_block_producer_block_height %v.", blockHeader.Height, 1671 bc.trustedBlockProducerStartHeight) 1672 } 1673 // At this point, we are confident that a signature is embedded in 1674 // the block. 1675 1676 // Verify that the public key has the valid length 1677 publicKey := desoBlock.BlockProducerInfo.PublicKey 1678 if len(publicKey) != btcec.PubKeyBytesLenCompressed { 1679 return false, false, errors.Wrapf(RuleErrorInvalidBlockProducerPublicKey, 1680 "ProcessBlock: Block producer public key is invalid even though "+ 1681 "--trusted_block_producer_public_keys is set *and* block height "+ 1682 "%v is >= --trusted_block_producer_block_height %v.", blockHeader.Height, 1683 bc.trustedBlockProducerStartHeight) 1684 } 1685 1686 // Verify that the public key is in the allowed set. 1687 if _, exists := bc.trustedBlockProducerPublicKeys[MakePkMapKey(publicKey)]; !exists { 1688 return false, false, errors.Wrapf(RuleErrorBlockProducerPublicKeyNotInWhitelist, 1689 "ProcessBlock: Block producer public key %v is not in the allowed list of "+ 1690 "--trusted_block_producer_public_keys: %v.", PkToStringBoth(publicKey), 1691 bc.trustedBlockProducerPublicKeys) 1692 } 1693 1694 // Verify that the public key has not been forbidden. 1695 dbEntry := DbGetForbiddenBlockSignaturePubKey(bc.db, publicKey) 1696 if dbEntry != nil { 1697 return false, false, errors.Wrapf(RuleErrorForbiddenBlockProducerPublicKey, 1698 "ProcessBlock: Block producer public key %v is forbidden", PkToStringBoth(publicKey)) 1699 } 1700 1701 // At this point we are confident that we have a valid public key that is 1702 // trusted. 1703 1704 signature := desoBlock.BlockProducerInfo.Signature 1705 pkObj, err := btcec.ParsePubKey(publicKey, btcec.S256()) 1706 if err != nil { 1707 return false, false, errors.Wrapf(err, 1708 "ProcessBlock: Error parsing block producer public key: %v.", 1709 PkToStringBoth(publicKey)) 1710 } 1711 if !signature.Verify(blockHash[:], pkObj) { 1712 return false, false, errors.Wrapf(RuleErrorInvalidBlockProducerSIgnature, 1713 "ProcessBlock: Error validating signature %v for public key %v: %v.", 1714 hex.EncodeToString(signature.Serialize()), 1715 PkToStringBoth(publicKey), 1716 err) 1717 } 1718 } 1719 } 1720 1721 // See if a node for the block exists in our node index. 1722 nodeToValidate, nodeExists := bc.blockIndex[*blockHash] 1723 // If no node exists for this block at all, then process the header 1724 // first before we do anything. This should create a node and set 1725 // the header validation status for it. 1726 if !nodeExists { 1727 _, isOrphan, err := bc.processHeader(blockHeader, blockHash) 1728 if err != nil { 1729 // If an error occurred processing the header, then the header 1730 // should be marked as invalid, which should be sufficient. 1731 return false, false, err 1732 } 1733 // If the header is an orphan, return early. We don't process orphan 1734 // blocks. If the block and its header are truly legitimate then we 1735 // should re-request it and its parents from a peer and reprocess it 1736 // once it is no longer an orphan. 1737 if isOrphan { 1738 return false, true, nil 1739 } 1740 1741 // Reset the pointers after having presumably added the header to the 1742 // block index. 1743 nodeToValidate, nodeExists = bc.blockIndex[*blockHash] 1744 } 1745 // At this point if the node still doesn't exist or if the header's validation 1746 // failed then we should return an error for the block. Note that at this point 1747 // the header must either be Validated or ValidateFailed. 1748 if !nodeExists || (nodeToValidate.Status&StatusHeaderValidated) == 0 { 1749 return false, false, RuleErrorInvalidBlockHeader 1750 } 1751 1752 // At this point, we are sure that the block's header is not an orphan and 1753 // that its header has been properly validated. The block itself could still 1754 // be an orphan, however, for example if we've processed the header of the parent but 1755 // not the parent block itself. 1756 // 1757 // Find the parent node in our block index. If the node doesn't exist or if the 1758 // node exists without StatusBlockProcessed, then the current block is an orphan. 1759 // In this case go ahead and return early. If its parents are truly legitimate then we 1760 // should re-request it and its parents from a node and reprocess it 1761 // once it is no longer an orphan. 1762 parentNode, parentNodeExists := bc.blockIndex[*blockHeader.PrevBlockHash] 1763 if !parentNodeExists || (parentNode.Status&StatusBlockProcessed) == 0 { 1764 return false, true, nil 1765 } 1766 1767 // At this point, because we know the block isn't an orphan, go ahead and mark 1768 // it as processed. This flag is basically used to avoid situations in which we 1769 // continuously try to fetch and reprocess a block because we forgot to mark 1770 // it as invalid (which would be a bug but this behavior allows us to handle 1771 // it more gracefully). 1772 nodeToValidate.Status |= StatusBlockProcessed 1773 1774 if bc.postgres != nil { 1775 if err := bc.postgres.UpsertBlock(nodeToValidate); err != nil { 1776 return false, false, errors.Wrapf(err, 1777 "ProcessBlock: Problem saving block with StatusBlockProcessed") 1778 } 1779 } else { 1780 if err := PutHeightHashToNodeInfo(nodeToValidate, bc.db, false /*bitcoinNodes*/); err != nil { 1781 return false, false, errors.Wrapf( 1782 err, "ProcessBlock: Problem calling PutHeightHashToNodeInfo with StatusBlockProcessed") 1783 } 1784 } 1785 1786 // Reject the block if any of the following apply to the parent: 1787 // - Its header is nil. 1788 // - Its header or its block validation failed. 1789 if parentNode.Header == nil || 1790 (parentNode.Status&(StatusHeaderValidateFailed|StatusBlockValidateFailed)) != 0 { 1791 1792 bc.MarkBlockInvalid(nodeToValidate, RuleErrorPreviousBlockInvalid) 1793 return false, false, RuleErrorPreviousBlockInvalid 1794 } 1795 1796 // At this point, we know that we are processing a block we haven't seen 1797 // before and we know that the parent block is stored and not invalid. 1798 1799 // Make sure the block size is not too big. 1800 serializedBlock, err := desoBlock.ToBytes(false) 1801 if err != nil { 1802 // Don't mark the block invalid here since the serialization is 1803 // potentially a network issue not an issue with the actual block. 1804 return false, false, fmt.Errorf("ProcessBlock: Problem serializing block") 1805 } 1806 if uint64(len(serializedBlock)) > bc.params.MaxBlockSizeBytes { 1807 bc.MarkBlockInvalid(nodeToValidate, RuleErrorBlockTooBig) 1808 return false, false, RuleErrorBlockTooBig 1809 } 1810 1811 // Block must have at least one transaction. 1812 if len(desoBlock.Txns) == 0 { 1813 bc.MarkBlockInvalid(nodeToValidate, RuleErrorNoTxns) 1814 return false, false, RuleErrorNoTxns 1815 } 1816 1817 // The first transaction in a block must be a block reward. 1818 firstTxn := desoBlock.Txns[0] 1819 if firstTxn.TxnMeta.GetTxnType() != TxnTypeBlockReward { 1820 return false, false, RuleErrorFirstTxnMustBeBlockReward 1821 } 1822 1823 // Do some txn sanity checks. 1824 for _, txn := range desoBlock.Txns[1:] { 1825 // There shouldn't be more than one block reward in the transaction list. 1826 if txn.TxnMeta.GetTxnType() == TxnTypeBlockReward { 1827 bc.MarkBlockInvalid(nodeToValidate, RuleErrorMoreThanOneBlockReward) 1828 return false, false, RuleErrorMoreThanOneBlockReward 1829 } 1830 1831 if err := CheckTransactionSanity(txn); err != nil { 1832 bc.MarkBlockInvalid( 1833 nodeToValidate, RuleError(errors.Wrapf(RuleErrorTxnSanity, "Error: %v", err).Error())) 1834 return false, false, err 1835 } 1836 } 1837 1838 // Compute and check the merkle root of all the txns. 1839 merkleRoot, txHashes, err := ComputeMerkleRoot(desoBlock.Txns) 1840 if err != nil { 1841 // Don't mark the block invalid here since the serialization is 1842 // potentially a network issue not an issue with the actual block. 1843 return false, false, errors.Wrapf(err, "ProcessBlock: Problem computing merkle root") 1844 } 1845 if *merkleRoot != *blockHeader.TransactionMerkleRoot { 1846 bc.MarkBlockInvalid(nodeToValidate, RuleErrorInvalidTxnMerkleRoot) 1847 glog.Errorf("ProcessBlock: Merkle root in block %v does not match computed "+ 1848 "merkle root %v", blockHeader.TransactionMerkleRoot, merkleRoot) 1849 return false, false, RuleErrorInvalidTxnMerkleRoot 1850 } 1851 1852 // Check for duplicate txns now that they're hashed. 1853 existingTxns := make(map[BlockHash]bool) 1854 for ii := range desoBlock.Txns { 1855 currentHash := *txHashes[ii] 1856 if _, exists := existingTxns[currentHash]; exists { 1857 bc.MarkBlockInvalid(nodeToValidate, RuleErrorDuplicateTxn) 1858 return false, false, RuleErrorDuplicateTxn 1859 } 1860 existingTxns[currentHash] = true 1861 } 1862 1863 // Try and store the block and its corresponding node info since it has passed 1864 // basic validation. 1865 nodeToValidate.Status |= StatusBlockStored 1866 1867 if bc.postgres != nil { 1868 if err = bc.postgres.UpsertBlock(nodeToValidate); err != nil { 1869 err = errors.Wrapf(err, "ProcessBlock: Problem saving block with StatusBlockStored") 1870 } 1871 } else { 1872 err = bc.db.Update(func(txn *badger.Txn) error { 1873 // Store the new block in the db under the 1874 // <blockHash> -> <serialized block> 1875 // index. 1876 if err := PutBlockWithTxn(txn, desoBlock); err != nil { 1877 return errors.Wrapf(err, "ProcessBlock: Problem calling PutBlock") 1878 } 1879 1880 // Store the new block's node in our node index in the db under the 1881 // <height uin32, blockhash BlockHash> -> <node info> 1882 // index. 1883 if err := PutHeightHashToNodeInfoWithTxn(txn, nodeToValidate, false /*bitcoinNodes*/); err != nil { 1884 return errors.Wrapf(err, "ProcessBlock: Problem calling PutHeightHashToNodeInfo before validation") 1885 } 1886 1887 return nil 1888 }) 1889 } 1890 1891 if err != nil { 1892 return false, false, errors.Wrapf(err, "ProcessBlock: Problem storing block after basic validation") 1893 } 1894 1895 // Now we try and add the block to the main block chain (note that it should 1896 // already be on the main header chain if we've made it this far). 1897 1898 // Get the current tip. 1899 currentTip := bc.blockTip() 1900 1901 // See if the current tip is equal to the block's parent. 1902 isMainChain := false 1903 1904 if *parentNode.Hash == *currentTip.Hash { 1905 // Create a new UtxoView representing the current tip. 1906 // 1907 // TODO: An optimization can be made here where we pre-load all the inputs this txn 1908 // requires into the view before-hand. This basically requires two passes over 1909 // the txns to account for txns that spend previous txns in the block, but it would 1910 // almost certainly be more efficient than doing a separate db call for each input 1911 // and output. 1912 utxoView, err := NewUtxoView(bc.db, bc.params, bc.postgres) 1913 if err != nil { 1914 return false, false, errors.Wrapf(err, "ProcessBlock: Problem initializing UtxoView in simple connect to tip") 1915 } 1916 1917 // Preload the view with almost all of the data it will need to connect the block 1918 err = utxoView.Preload(desoBlock) 1919 if err != nil { 1920 glog.Errorf("ProcessBlock: Problem preloading the view: %v", err) 1921 } 1922 1923 // Verify that the utxo view is pointing to the current tip. 1924 if *utxoView.TipHash != *currentTip.Hash { 1925 //return false, false, fmt.Errorf("ProcessBlock: Tip hash for utxo view (%v) is "+ 1926 // "not the current tip hash (%v)", utxoView.TipHash, currentTip.Hash) 1927 glog.Errorf("ProcessBlock: Tip hash for utxo view (%v) is "+ 1928 "not the current tip hash (%v)", utxoView.TipHash, currentTip.Hash) 1929 } 1930 1931 utxoOpsForBlock, err := utxoView.ConnectBlock(desoBlock, txHashes, verifySignatures, nil) 1932 if err != nil { 1933 if IsRuleError(err) { 1934 // If we have a RuleError, mark the block as invalid before 1935 // returning. 1936 bc.MarkBlockInvalid(nodeToValidate, RuleError(err.Error())) 1937 return false, false, err 1938 } 1939 1940 // If the error wasn't a RuleError, return without marking the 1941 // block as invalid, since this means the block may benefit from 1942 // being reprocessed in the future, which will happen if a reorg 1943 // puts this block on the main chain. 1944 return false, false, err 1945 } 1946 // If all of the above passed it means the block is valid. So set the 1947 // status flag on the block to indicate that and write the status to disk. 1948 nodeToValidate.Status |= StatusBlockValidated 1949 1950 // Now that we have a valid block that we know is connecting to the tip, 1951 // update our data structures to actually make this connection. Do this 1952 // in a transaction so that it is atomic. 1953 if bc.postgres != nil { 1954 if err = bc.postgres.UpsertBlockAndTransactions(nodeToValidate, desoBlock); err != nil { 1955 return false, false, errors.Wrapf(err, "ProcessBlock: Problem upserting block and transactions") 1956 } 1957 1958 // Write the modified utxo set to the view. 1959 // FIXME: This codepath breaks the balance computation in handleBlock for Rosetta 1960 // because it clears the UtxoView before balances can be snapshotted. 1961 if err := utxoView.FlushToDb(); err != nil { 1962 return false, false, errors.Wrapf(err, "ProcessBlock: Problem flushing view to db") 1963 } 1964 } else { 1965 err = bc.db.Update(func(txn *badger.Txn) error { 1966 // This will update the node's status. 1967 if err := PutHeightHashToNodeInfoWithTxn(txn, nodeToValidate, false /*bitcoinNodes*/); err != nil { 1968 return errors.Wrapf( 1969 err, "ProcessBlock: Problem calling PutHeightHashToNodeInfo after validation") 1970 } 1971 1972 // Set the best node hash to this one. Note the header chain should already 1973 // be fully aware of this block so we shouldn't update it here. 1974 if err := PutBestHashWithTxn(txn, blockHash, ChainTypeDeSoBlock); err != nil { 1975 return err 1976 } 1977 1978 // Write the modified utxo set to the view. 1979 if err := utxoView.FlushToDbWithTxn(txn); err != nil { 1980 return errors.Wrapf(err, "ProcessBlock: Problem writing utxo view to db on simple add to tip") 1981 } 1982 1983 // Write the utxo operations for this block to the db so we can have the 1984 // ability to roll it back in the future. 1985 if err := PutUtxoOperationsForBlockWithTxn(txn, blockHash, utxoOpsForBlock); err != nil { 1986 return errors.Wrapf(err, "ProcessBlock: Problem writing utxo operations to db on simple add to tip") 1987 } 1988 1989 return nil 1990 }) 1991 } 1992 1993 if err != nil { 1994 return false, false, errors.Wrapf(err, "ProcessBlock: Problem writing block info to db on simple add to tip") 1995 } 1996 1997 // Now that we've set the best chain in the db, update our in-memory data 1998 // structure to reflect this. Do a quick check first to make sure it's consistent. 1999 lastIndex := len(bc.bestChain) - 1 2000 bestChainHash := bc.bestChain[lastIndex].Hash 2001 2002 if *bestChainHash != *nodeToValidate.Header.PrevBlockHash { 2003 return false, false, fmt.Errorf("ProcessBlock: Last block in bestChain "+ 2004 "data structure (%v) is not equal to parent hash of block being "+ 2005 "added to tip (%v)", bestChainHash, nodeToValidate.Header.PrevBlockHash) 2006 } 2007 2008 // If we're syncing there's no risk of concurrency issues. Otherwise, we 2009 // need to make a copy in order to be save. 2010 if bc.isSyncing() { 2011 bc.bestChain = append(bc.bestChain, nodeToValidate) 2012 bc.bestChainMap[*nodeToValidate.Hash] = nodeToValidate 2013 } else { 2014 newBestChain, newBestChainMap := bc.CopyBestChain() 2015 newBestChain = append(newBestChain, nodeToValidate) 2016 newBestChainMap[*nodeToValidate.Hash] = nodeToValidate 2017 bc.bestChain, bc.bestChainMap = newBestChain, newBestChainMap 2018 } 2019 2020 // This node is on the main chain so set this variable. 2021 isMainChain = true 2022 2023 // At this point we should have the following: 2024 // * The block has been written to disk. 2025 // * The block is in our in-memory node tree data structure. 2026 // * The node tree has been updated on disk. 2027 // * The block is on our in-memory main chain data structure. 2028 // * The on-disk data structure should be updated too: 2029 // - The best hash should now be set to this block. 2030 // - The <height -> hash> index representing the main chain should be updated 2031 // to have this block. 2032 // - The utxo db should be updated to reflect the effects of adding this block. 2033 // - The utxo operations performed for this block should also be stored so we 2034 // can roll the block back in the future if needed. 2035 2036 // Notify any listeners. 2037 if bc.eventManager != nil { 2038 bc.eventManager.blockConnected(&BlockEvent{ 2039 Block: desoBlock, 2040 UtxoView: utxoView, 2041 UtxoOps: utxoOpsForBlock, 2042 }) 2043 } 2044 2045 } else if nodeToValidate.CumWork.Cmp(currentTip.CumWork) <= 0 { 2046 // A block has less cumulative work than our tip. In this case, we just ignore 2047 // the block for now. It is stored in our <hash -> block_data> map on disk as well 2048 // as in our in-memory node tree data structure (which is also stored on disk). 2049 // Eventually, if enough work gets added to the block, then we'll 2050 // add it via a reorg. 2051 } else { 2052 // In this case the block is not attached to our tip and the cumulative work 2053 // of the block is greater than our tip. This means we have a fork that has 2054 // the potential to become our new main chain so we need to do a reorg to 2055 // process it. A reorg consists of the following: 2056 // 1) Find the common ancecstor of this block and the main chain. 2057 // 2) Roll back all of the main chain blocks back to this common ancestor. 2058 // 3) Verify and add the new blocks up to this one. 2059 // 2060 // Note that if verification fails while trying to add the new blocks then 2061 // we will not wind up accepting the changes. For this reason all of the 2062 // above steps are processed using an in-memory view before writing anything 2063 // to the database. 2064 2065 // Find the common ancestor of this block and the main chain. 2066 commonAncestor, detachBlocks, attachBlocks := GetReorgBlocks(currentTip, nodeToValidate) 2067 // Log a warning if the reorg is going to be a big one. 2068 numBlocks := currentTip.Height - commonAncestor.Height 2069 if numBlocks > 10 { 2070 glog.Warningf("ProcessBlock: Proceeding with reorg of (%d) blocks from "+ 2071 "block (%v) at height (%d) to block (%v) at height of (%d)", 2072 numBlocks, currentTip, currentTip.Height, nodeToValidate, nodeToValidate.Height) 2073 } 2074 2075 // Create an empty view referencing the current tip. 2076 // 2077 // TODO: An optimization can be made here where we pre-load all the inputs this txn 2078 // requires into the view before-hand. This basically requires two passes over 2079 // the txns to account for txns that spend previous txns in the block, but it would 2080 // almost certainly be more efficient than doing a separate db call for each input 2081 // and output 2082 utxoView, err := NewUtxoView(bc.db, bc.params, bc.postgres) 2083 if err != nil { 2084 return false, false, errors.Wrapf(err, "processblock: Problem initializing UtxoView in reorg") 2085 } 2086 // Verify that the utxo view is pointing to the current tip. 2087 if *utxoView.TipHash != *currentTip.Hash { 2088 return false, false, fmt.Errorf("ProcessBlock: Tip hash for utxo view (%v) is "+ 2089 "not the current tip hash (%v)", *utxoView.TipHash, *currentTip) 2090 } 2091 2092 // Go through and detach all of the blocks down to the common ancestor. We 2093 // shouldn't encounter any errors but if we do, return without marking the 2094 // block as invalid. 2095 for _, nodeToDetach := range detachBlocks { 2096 // Fetch the utxo operations for the block we're detaching. We need these 2097 // in order to be able to detach the block. 2098 utxoOps, err := GetUtxoOperationsForBlock(bc.db, nodeToDetach.Hash) 2099 if err != nil { 2100 return false, false, errors.Wrapf(err, "ProcessBlock: Problem fetching "+ 2101 "utxo operations during detachment of block (%v) "+ 2102 "in reorg", nodeToDetach) 2103 } 2104 2105 // Fetch the block itself since we need some info from it to roll 2106 // it back. 2107 blockToDetach, err := GetBlock(nodeToDetach.Hash, bc.db) 2108 if err != nil { 2109 return false, false, errors.Wrapf(err, "ProcessBlock: Problem fetching "+ 2110 "block (%v) during detach in reorg", nodeToDetach) 2111 } 2112 2113 // Compute the hashes for all the transactions. 2114 txHashes, err := ComputeTransactionHashes(blockToDetach.Txns) 2115 if err != nil { 2116 return false, false, errors.Wrapf(err, "ProcessBlock: Problem computing "+ 2117 "transaction hashes during detachment of block (%v)", nodeToDetach) 2118 } 2119 2120 // Now roll the block back in the view. 2121 if err := utxoView.DisconnectBlock(blockToDetach, txHashes, utxoOps); err != nil { 2122 return false, false, errors.Wrapf(err, "ProcessBlock: Problem rolling back "+ 2123 "block (%v) during detachment in reorg", nodeToDetach) 2124 } 2125 // Double-check that the view's hash is now at the block's parent. 2126 if *utxoView.TipHash != *blockToDetach.Header.PrevBlockHash { 2127 return false, false, fmt.Errorf("ProcessBlock: Block hash in utxo view (%v) "+ 2128 "does not match parent block hash (%v) after executing "+ 2129 "DisconnectBlock", utxoView.TipHash, blockToDetach.Header.PrevBlockHash) 2130 } 2131 } 2132 2133 // If we made it here, we were able to successfully detach all of the blocks 2134 // such that the view is now at the common ancestor. Double-check that this is 2135 // the case. 2136 if *utxoView.TipHash != *commonAncestor.Hash { 2137 return false, false, fmt.Errorf("ProcessBlock: Block hash in utxo view (%v) "+ 2138 "does not match common ancestor hash (%v) after executing "+ 2139 "DisconnectBlock", utxoView.TipHash, commonAncestor.Hash) 2140 } 2141 2142 // Now that the view has the common ancestor as the tip, we can try and attach 2143 // each new block to it to see if the reorg will work. 2144 // 2145 // Keep track of the utxo operations we get from attaching the blocks. 2146 utxoOpsForAttachBlocks := [][][]*UtxoOperation{} 2147 // Also keep track of any errors that we might have come across. 2148 ruleErrorsFound := []RuleError{} 2149 // The first element will be the node right after the common ancestor and 2150 // the last element will be the new node we need to attach. 2151 for _, attachNode := range attachBlocks { 2152 2153 // Fetch the block itself since we need some info from it to try and 2154 // connect it. 2155 blockToAttach, err := GetBlock(attachNode.Hash, bc.db) 2156 if err != nil { 2157 return false, false, errors.Wrapf(err, "ProcessBlock: Problem fetching "+ 2158 "block (%v) during attach in reorg", attachNode) 2159 } 2160 2161 // If the parent node has been marked as invalid then mark this node as 2162 // invalid as well. 2163 if (attachNode.Parent.Status & StatusBlockValidateFailed) != 0 { 2164 bc.MarkBlockInvalid(attachNode, RuleErrorPreviousBlockInvalid) 2165 continue 2166 } 2167 2168 // Compute the tx hashes for the block since we need them to perform 2169 // the connection. 2170 txHashes, err := ComputeTransactionHashes(blockToAttach.Txns) 2171 if err != nil { 2172 return false, false, errors.Wrapf(err, "ProcessBlock: Problem computing "+ 2173 "transaction hashes during attachment of block (%v) in reorg", blockToAttach) 2174 } 2175 2176 // Initialize the utxo operations slice. 2177 utxoOps, err := utxoView.ConnectBlock( 2178 blockToAttach, txHashes, verifySignatures, nil) 2179 if err != nil { 2180 if IsRuleError(err) { 2181 // If we have a RuleError, mark the block as invalid. But don't return 2182 // yet because we need to mark all of the child blocks as invalid as 2183 // well first. 2184 bc.MarkBlockInvalid(attachNode, RuleError(err.Error())) 2185 ruleErrorsFound = append(ruleErrorsFound, RuleError(err.Error())) 2186 continue 2187 } else { 2188 // If the error wasn't a RuleError, return without marking the 2189 // block as invalid, since this means the block may benefit from 2190 // being reprocessed in the future. 2191 return false, false, errors.Wrapf(err, "ProcessBlock: Problem trying to attach block (%v) in reorg", attachNode) 2192 } 2193 } 2194 2195 // If we made it here then we were able to connect the block successfully. 2196 // So mark its status as valid and update the node index accordingly. 2197 attachNode.Status |= StatusBlockValidated 2198 if err := PutHeightHashToNodeInfo(attachNode, bc.db, false /*bitcoinNodes*/); err != nil { 2199 return false, false, errors.Wrapf( 2200 err, "ProcessBlock: Problem calling PutHeightHashToNodeInfo after validation in reorg") 2201 } 2202 2203 // Add the utxo operations to our list. 2204 utxoOpsForAttachBlocks = append(utxoOpsForAttachBlocks, utxoOps) 2205 } 2206 2207 // At this point, either we were able to attach all of the blocks OR the block 2208 // we are processing is invalid (possibly due to one of its parents to being 2209 // invalid). Regardless, because the attach worked if and only if the block we 2210 // are processing is valid, it is sufficient to use this block's validity to decide 2211 // if we want to perform this reorg. 2212 // 2213 // Recall that newNode is the node at the tip of the new chain we're trying to 2214 // reorg to which is also the last node in attachBlocks. 2215 newTipNode := attachBlocks[len(attachBlocks)-1] 2216 if (newTipNode.Status & StatusBlockValidateFailed) != 0 { 2217 // In the case where the new tip is invalid, we encountered an error while 2218 // processing. Return the first error we encountered. Note we should already 2219 // have marked all the blocks as invalid so no need to do it here. 2220 return false, false, ruleErrorsFound[0] 2221 } 2222 2223 // If we made it this far, we know the reorg will succeed and the view contains 2224 // the state after applying the reorg. With this information, it is possible to 2225 // roll back the blocks and fast forward the db to the post-reorg state with a 2226 // single transaction. 2227 err = bc.db.Update(func(txn *badger.Txn) error { 2228 // Set the best node hash to the new tip. 2229 if err := PutBestHashWithTxn(txn, newTipNode.Hash, ChainTypeDeSoBlock); err != nil { 2230 return err 2231 } 2232 2233 for _, detachNode := range detachBlocks { 2234 // Delete the utxo operations for the blocks we're detaching since we don't need 2235 // them anymore. 2236 if err := DeleteUtxoOperationsForBlockWithTxn(txn, detachNode.Hash); err != nil { 2237 return errors.Wrapf(err, "ProcessBlock: Problem deleting utxo operations for block") 2238 } 2239 2240 // Note we could be even more aggressive here by deleting the nodes and 2241 // corresponding blocks from the db here (i.e. not storing any side chain 2242 // data on the db). But this seems like a minor optimization that comes at 2243 // the minor cost of side chains not being retained by the network as reliably. 2244 } 2245 2246 for ii, attachNode := range attachBlocks { 2247 // Add the utxo operations for the blocks we're attaching so we can roll them back 2248 // in the future if necessary. 2249 if err := PutUtxoOperationsForBlockWithTxn(txn, attachNode.Hash, utxoOpsForAttachBlocks[ii]); err != nil { 2250 return errors.Wrapf(err, "ProcessBlock: Problem putting utxo operations for block") 2251 } 2252 } 2253 2254 // Write the modified utxo set to the view. 2255 if err := utxoView.FlushToDbWithTxn(txn); err != nil { 2256 return errors.Wrapf(err, "ProcessBlock: Problem flushing to db") 2257 } 2258 2259 return nil 2260 }) 2261 if err != nil { 2262 return false, false, errors.Errorf("ProcessBlock: Problem updating: %v", err) 2263 } 2264 2265 // Now the the db has been updated, update our in-memory best chain. Note that there 2266 // is no need to update the node index because it was updated as we went along. 2267 newBestChain, newBestChainMap := bc.CopyBestChain() 2268 newBestChain, newBestChainMap = updateBestChainInMemory( 2269 newBestChain, newBestChainMap, detachBlocks, attachBlocks) 2270 bc.bestChain, bc.bestChainMap = newBestChain, newBestChainMap 2271 2272 // If we made it here then this block is on the main chain. 2273 isMainChain = true 2274 2275 // Signal to the server about all the blocks that were disconnected and 2276 // connected as a result of this operation. Do this in a goroutine so that 2277 // if ProcessBlock is called by a consumer of incomingMessages we don't 2278 // have any risk of deadlocking. 2279 for _, nodeToDetach := range detachBlocks { 2280 // Fetch the block itself since we need some info from it to roll 2281 // it back. 2282 blockToDetach, err := GetBlock(nodeToDetach.Hash, bc.db) 2283 if err != nil { 2284 return false, false, errors.Wrapf(err, "ProcessBlock: Problem fetching "+ 2285 "block (%v) during detach in server signal", nodeToDetach) 2286 } 2287 2288 // If we have a Server object then call its function 2289 if bc.eventManager != nil { 2290 // FIXME: We need to add the UtxoOps here to handle reorgs properly in Rosetta 2291 // For now it's fine because reorgs are virtually impossible. 2292 bc.eventManager.blockDisconnected(&BlockEvent{Block: blockToDetach}) 2293 } 2294 } 2295 for _, attachNode := range attachBlocks { 2296 2297 // Fetch the block itself since we need some info from it to try and 2298 // connect it. 2299 blockToAttach, err := GetBlock(attachNode.Hash, bc.db) 2300 if err != nil { 2301 return false, false, errors.Wrapf(err, "ProcessBlock: Problem fetching "+ 2302 "block (%v) during attach in server signal", attachNode) 2303 } 2304 // If we have a Server object then call its function 2305 if bc.eventManager != nil { 2306 // FIXME: We need to add the UtxoOps here to handle reorgs properly in Rosetta 2307 // For now it's fine because reorgs are virtually impossible. 2308 bc.eventManager.blockConnected(&BlockEvent{Block: blockToAttach}) 2309 } 2310 } 2311 2312 // If we have a Server object then call its function 2313 // TODO: Is this duplicated / necessary? 2314 if bc.eventManager != nil { 2315 // FIXME: We need to add the UtxoOps here to handle reorgs properly in Rosetta 2316 // For now it's fine because reorgs are virtually impossible. 2317 bc.eventManager.blockConnected(&BlockEvent{Block: desoBlock}) 2318 } 2319 } 2320 2321 // If we've made it this far, the block has been validated and we have either added 2322 // the block to the tip, done nothing with it (because its cumwork isn't high enough) 2323 // or added it via a reorg and the db and our in-memory data structures reflect this 2324 // change. 2325 // 2326 // Now that we've done all of the above, we need to signal to the server that we've 2327 // accepted the block 2328 2329 // Signal the server that we've accepted this block in some way. 2330 if bc.eventManager != nil { 2331 bc.eventManager.blockAccepted(&BlockEvent{Block: desoBlock}) 2332 } 2333 2334 // At this point, the block we were processing originally should have been added 2335 // to our data structures and any unconnectedTxns that are no longer unconnectedTxns should have 2336 // also been processed. 2337 return isMainChain, false, nil 2338 } 2339 2340 // ValidateTransaction creates a UtxoView and sees if the transaction can be connected 2341 // to it. If a mempool is provided, this function tries to find dependencies of the 2342 // passed-in transaction in the pool and connect them before trying to connect the 2343 // passed-in transaction. 2344 func (bc *Blockchain) ValidateTransaction( 2345 txnMsg *MsgDeSoTxn, blockHeight uint32, verifySignatures bool, mempool *DeSoMempool) error { 2346 2347 // Create a new UtxoView. If we have access to a mempool object, use it to 2348 // get an augmented view that factors in pending transactions. 2349 utxoView, err := NewUtxoView(bc.db, bc.params, bc.postgres) 2350 if err != nil { 2351 return errors.Wrapf(err, "ValidateTransaction: Problem Problem creating new utxo view: ") 2352 } 2353 if mempool != nil { 2354 utxoView, err = mempool.GetAugmentedUtxoViewForPublicKey(txnMsg.PublicKey, txnMsg) 2355 if err != nil { 2356 return errors.Wrapf(err, "ValidateTransaction: Problem getting augmented UtxoView from mempool: ") 2357 } 2358 } 2359 2360 // Hash the transaction. 2361 txHash := txnMsg.Hash() 2362 txnBytes, err := txnMsg.ToBytes(false) 2363 if err != nil { 2364 return errors.Wrapf(err, "ValidateTransaction: Error serializing txn: %v", err) 2365 } 2366 txnSize := int64(len(txnBytes)) 2367 // We don't care about the utxoOps or the fee it returns. 2368 _, _, _, _, err = utxoView._connectTransaction( 2369 txnMsg, 2370 txHash, 2371 txnSize, 2372 blockHeight, 2373 verifySignatures, 2374 false, /*ignoreUtxos*/ 2375 ) 2376 if err != nil { 2377 return errors.Wrapf(err, "ValidateTransaction: Problem validating transaction: ") 2378 } 2379 2380 return nil 2381 } 2382 2383 var ( 2384 maxHash = BlockHash{ 2385 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 2386 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 2387 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 2388 0xff, 0xff} 2389 maxHashBigint = HashToBigint(&maxHash) 2390 bigOneInt = big.NewInt(1) 2391 ) 2392 2393 // The number of hashing attempts in expectation it would take to produce the 2394 // hash passed in. This is computed as: 2395 // E(min(X_i, ..., X_n)) where: 2396 // - n = (number of attempted hashes) and 2397 // - the X_i are all U(0, MAX_HASH) 2398 // -> E(min(X_i, ..., X_n)) = MAX_HASH / (n + 1) 2399 // -> E(n) ~= MAX_HASH / min_hash - 1 2400 // - where min_hash is the block hash 2401 // 2402 // We approximate this as MAX_HASH / (min_hash + 1), adding 1 to min_hash in 2403 // order to mitigate the possibility of a divide-by-zero error. 2404 // 2405 // The value returned is the expected number of hashes performed to produce 2406 // the input hash formatted as a big-endian big integer that uses the 2407 // BlockHash type for convenience (though it is likely to be much lower 2408 // in terms of magnitude than a typical BlockHash object). 2409 func ExpectedWorkForBlockHash(hash *BlockHash) *BlockHash { 2410 hashBigint := HashToBigint(hash) 2411 ratioBigint := new(big.Int) 2412 ratioBigint.Div(maxHashBigint, hashBigint.Add(hashBigint, bigOneInt)) 2413 return BigintToHash(ratioBigint) 2414 } 2415 2416 func ComputeTransactionHashes(txns []*MsgDeSoTxn) ([]*BlockHash, error) { 2417 txHashes := make([]*BlockHash, len(txns)) 2418 2419 for ii, currentTxn := range txns { 2420 txHashes[ii] = currentTxn.Hash() 2421 } 2422 2423 return txHashes, nil 2424 } 2425 2426 func ComputeMerkleRoot(txns []*MsgDeSoTxn) (_merkle *BlockHash, _txHashes []*BlockHash, _err error) { 2427 if len(txns) == 0 { 2428 return nil, nil, fmt.Errorf("ComputeMerkleRoot: Block must contain at least one txn") 2429 } 2430 2431 // Compute the hashes of all the transactions. 2432 hashes := [][]byte{} 2433 for _, txn := range txns { 2434 txHash := txn.Hash() 2435 hashes = append(hashes, txHash[:]) 2436 } 2437 2438 merkleTree := merkletree.NewTreeFromHashes(merkletree.Sha256DoubleHash, hashes) 2439 2440 rootHash := &BlockHash{} 2441 copy(rootHash[:], merkleTree.Root.GetHash()[:]) 2442 2443 txHashes := []*BlockHash{} 2444 for _, leafNode := range merkleTree.Rows[0] { 2445 currentHash := &BlockHash{} 2446 copy(currentHash[:], leafNode.GetHash()) 2447 txHashes = append(txHashes, currentHash) 2448 } 2449 2450 return rootHash, txHashes, nil 2451 } 2452 2453 func (bc *Blockchain) GetSpendableUtxosForPublicKey(spendPublicKeyBytes []byte, mempool *DeSoMempool, referenceUtxoView *UtxoView) ([]*UtxoEntry, error) { 2454 // If we have access to a mempool, use it to account for utxos we might not 2455 // get otherwise. 2456 utxoView, err := NewUtxoView(bc.db, bc.params, bc.postgres) 2457 if err != nil { 2458 return nil, errors.Wrapf(err, "Blockchain.GetSpendableUtxosForPublicKey: Problem initializing UtxoView: ") 2459 } 2460 // Use the reference UtxoView if provided. Otherwise try to get one from the mempool. 2461 // This improves efficiency when we have a UtxoView already handy. 2462 if referenceUtxoView != nil { 2463 utxoView = referenceUtxoView 2464 } else { 2465 if mempool != nil { 2466 utxoView, err = mempool.GetAugmentedUtxoViewForPublicKey(spendPublicKeyBytes, nil) 2467 if err != nil { 2468 return nil, errors.Wrapf(err, "Blockchain.GetSpendableUtxosForPublicKey: Problem getting augmented UtxoView from mempool: ") 2469 } 2470 } 2471 } 2472 2473 // Get unspent utxos from the view. 2474 utxoEntriesFound, err := utxoView.GetUnspentUtxoEntrysForPublicKey(spendPublicKeyBytes) 2475 if err != nil { 2476 return nil, errors.Wrapf(err, "Blockchain.GetSpendableUtxosForPublicKey: Problem getting spendable utxos from UtxoView: ") 2477 } 2478 2479 // Sort the UTXOs putting the smallest amounts first. 2480 // 2481 // TODO: There has generally been a lot of discussion and thought about 2482 // what the optimal coin selection algorithm should be over the years. 2483 // Here, we choose to keep things simple and just use the smallest UTXOs 2484 // first. It has its drawbacks and we should revisit it at some point, 2485 // but for now it seems like it should be fine, and the reduction of the 2486 // size of the UTXO set seems like a reasonable benefit of using it. See below 2487 // for more discussion: 2488 // https://bitcoin.stackexchange.com/questions/32145/what-are-the-trade-offs-between-the-different-algorithms-for-deciding-which-utxo 2489 sort.Slice(utxoEntriesFound, func(ii, jj int) bool { 2490 return utxoEntriesFound[ii].AmountNanos < utxoEntriesFound[jj].AmountNanos 2491 }) 2492 2493 // Add UtxoEntrys to our list filtering out ones that aren't valid for various 2494 // reasons. 2495 spendableUtxoEntries := []*UtxoEntry{} 2496 for _, utxoEntry := range utxoEntriesFound { 2497 // If the utxo is an immature block reward, skip it. Use the block chain height 2498 // not the header chain height since the transaction will need to be validated 2499 // against existing transactions which are present only if we have blocks. 2500 // 2501 // Note we add one to the current block height since it is presumed this 2502 // transaction will at best be mined into the next block. 2503 blockHeight := bc.blockTip().Height + 1 2504 if _isEntryImmatureBlockReward(utxoEntry, blockHeight, bc.params) { 2505 continue 2506 } 2507 2508 // Don't consider utxos that are already consumed by the mempool. 2509 if mempool != nil && mempool.CheckSpend(*utxoEntry.UtxoKey) != nil { 2510 continue 2511 } 2512 2513 // If we get here we know the utxo is spendable so add it to our list. 2514 spendableUtxoEntries = append(spendableUtxoEntries, utxoEntry) 2515 } 2516 2517 return spendableUtxoEntries, nil 2518 } 2519 2520 func amountEqualsAdditionalOutputs(spendAmount uint64, additionalOutputs []*DeSoOutput) error { 2521 expectedAdditionalOutputSum := uint64(0) 2522 for _, output := range additionalOutputs { 2523 expectedAdditionalOutputSum += output.AmountNanos 2524 } 2525 if spendAmount != expectedAdditionalOutputSum { 2526 return fmt.Errorf("expected spendAmount to be %d, instead got %d", expectedAdditionalOutputSum, spendAmount) 2527 } 2528 return nil 2529 } 2530 2531 // Define a helper function for computing the upper bound of the size 2532 // of a transaction and associated fees. This basically serializes the 2533 // transaction without the signature and then accounts for the maximum possible 2534 // size the signature could be. 2535 func _computeMaxTxSize(_tx *MsgDeSoTxn) uint64 { 2536 // Compute the size of the transaction without the signature. 2537 txBytesNoSignature, _ := _tx.ToBytes(true /*preSignature*/) 2538 // Return the size the transaction would be if the signature had its 2539 // absolute maximum length. 2540 2541 // MaxDERSigLen is the maximum size that a DER signature can be. 2542 // 2543 // Note: I am pretty sure the true maximum is 71. But since this value is 2544 // dependent on the size of R and S, and since it's generally used for 2545 // safety purposes (e.g. ensuring that enough space has been allocated), 2546 // it seems better to pad it a bit and stay on the safe side. You can see 2547 // some discussion on getting to this number here: 2548 // https://bitcoin.stackexchange.com/questions/77191/what-is-the-maximum-size-of-a-der-encoded-ecdsa-signature 2549 const MaxDERSigLen = 74 2550 2551 return uint64(len(txBytesNoSignature)) + MaxDERSigLen 2552 } 2553 2554 // A helper for computing the max fee given a txn. Assumes the longest signature 2555 // length. 2556 func _computeMaxTxFee(_tx *MsgDeSoTxn, minFeeRateNanosPerKB uint64) uint64 { 2557 maxSizeBytes := _computeMaxTxSize(_tx) 2558 return maxSizeBytes * minFeeRateNanosPerKB / 1000 2559 } 2560 2561 func (bc *Blockchain) CreatePrivateMessageTxn( 2562 senderPublicKey []byte, recipientPublicKey []byte, 2563 unencryptedMessageText string, encryptedMessageText string, 2564 tstampNanos uint64, 2565 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 2566 _txn *MsgDeSoTxn, _totalInput uint64, _changeAmount uint64, _fees uint64, _err error) { 2567 2568 var encryptedMessageBytes []byte 2569 messageExtraData := make(map[string][]byte) 2570 2571 if encryptedMessageText == "" { 2572 // Encrypt the passed-in message text with the recipient's public key. 2573 // 2574 // Parse the recipient public key. 2575 recipientPk, err := btcec.ParsePubKey(recipientPublicKey, btcec.S256()) 2576 if err != nil { 2577 return nil, 0, 0, 0, errors.Wrapf(err, "CreatePrivateMessageTxn: Problem parsing "+ 2578 "recipient public key: ") 2579 } 2580 encryptedMessageBytes, err = EncryptBytesWithPublicKey( 2581 []byte(unencryptedMessageText), recipientPk.ToECDSA()) 2582 if err != nil { 2583 return nil, 0, 0, 0, errors.Wrapf(err, "CreatePrivateMessageTxn: Problem "+ 2584 "encrypting message text to hex: ") 2585 } 2586 2587 // Add {V : 1} version field to ExtraData to indicate we are 2588 // encrypting using legacy public key method. 2589 messageExtraData["V"] = UintToBuf(1) 2590 } else { 2591 var err error 2592 // Message is already encrypted, so just decode it to hex format 2593 encryptedMessageBytes, err = hex.DecodeString(encryptedMessageText) 2594 if err != nil { 2595 return nil, 0, 0, 0, errors.Wrapf(err, "CreatePrivateMessageTxn: Problem "+ 2596 "decoding message text to hex: ") 2597 } 2598 2599 // Add {V : 2} version field to ExtraData to indicate we are 2600 // encrypting using shared secret. 2601 messageExtraData["V"] = UintToBuf(2) 2602 } 2603 2604 // Don't allow encryptedMessageBytes to be nil. 2605 if len(encryptedMessageBytes) == 0 { 2606 encryptedMessageBytes = []byte{} 2607 } 2608 2609 // Create a transaction containing the encrypted message text. 2610 // A PrivateMessage transaction doesn't need any inputs or outputs (except additionalOutputs provided). 2611 txn := &MsgDeSoTxn{ 2612 PublicKey: senderPublicKey, 2613 TxnMeta: &PrivateMessageMetadata{ 2614 RecipientPublicKey: recipientPublicKey, 2615 EncryptedText: encryptedMessageBytes, 2616 TimestampNanos: tstampNanos, 2617 }, 2618 ExtraData: messageExtraData, 2619 TxOutputs: additionalOutputs, 2620 2621 // We wait to compute the signature until we've added all the 2622 // inputs and change. 2623 } 2624 2625 totalInput, spendAmount, changeAmount, fees, err := 2626 bc.AddInputsAndChangeToTransaction(txn, minFeeRateNanosPerKB, mempool) 2627 if err != nil { 2628 return nil, 0, 0, 0, errors.Wrapf(err, "CreatePrivateMessageTxn: Problem adding inputs: ") 2629 } 2630 2631 // Sanity-check that the spendAmount is zero. 2632 if err = amountEqualsAdditionalOutputs(spendAmount, additionalOutputs); err != nil { 2633 return nil, 0, 0, 0, fmt.Errorf("CreatePrivateMessageTxn: %v", err) 2634 } 2635 2636 return txn, totalInput, changeAmount, fees, nil 2637 } 2638 2639 func (bc *Blockchain) CreateLikeTxn( 2640 userPublicKey []byte, likedPostHash BlockHash, isUnlike bool, 2641 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 2642 _txn *MsgDeSoTxn, _totalInput uint64, _changeAmount uint64, _fees uint64, 2643 _err error) { 2644 2645 // A Like transaction doesn't need any inputs or outputs (except additionalOutputs provided). 2646 txn := &MsgDeSoTxn{ 2647 PublicKey: userPublicKey, 2648 TxnMeta: &LikeMetadata{ 2649 LikedPostHash: &likedPostHash, 2650 IsUnlike: isUnlike, 2651 }, 2652 TxOutputs: additionalOutputs, 2653 // We wait to compute the signature until we've added all the 2654 // inputs and change. 2655 } 2656 2657 totalInput, spendAmount, changeAmount, fees, err := 2658 bc.AddInputsAndChangeToTransaction(txn, minFeeRateNanosPerKB, mempool) 2659 if err != nil { 2660 return nil, 0, 0, 0, errors.Wrapf( 2661 err, "CreateLikeTxn: Problem adding inputs: ") 2662 } 2663 2664 // Sanity-check that the spendAmount is zero. 2665 if err = amountEqualsAdditionalOutputs(spendAmount, additionalOutputs); err != nil { 2666 return nil, 0, 0, 0, fmt.Errorf("CreateLikeTxn: %v", err) 2667 } 2668 2669 return txn, totalInput, changeAmount, fees, nil 2670 } 2671 2672 func (bc *Blockchain) CreateFollowTxn( 2673 senderPublicKey []byte, followedPublicKey []byte, isUnfollow bool, 2674 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 2675 _txn *MsgDeSoTxn, _totalInput uint64, _changeAmount uint64, _fees uint64, 2676 _err error) { 2677 2678 // A Follow transaction doesn't need any inputs or outputs (except additionalOutputs provided). 2679 txn := &MsgDeSoTxn{ 2680 PublicKey: senderPublicKey, 2681 TxnMeta: &FollowMetadata{ 2682 FollowedPublicKey: followedPublicKey, 2683 IsUnfollow: isUnfollow, 2684 }, 2685 TxOutputs: additionalOutputs, 2686 // We wait to compute the signature until we've added all the 2687 // inputs and change. 2688 } 2689 2690 totalInput, spendAmount, changeAmount, fees, err := 2691 bc.AddInputsAndChangeToTransaction(txn, minFeeRateNanosPerKB, mempool) 2692 if err != nil { 2693 return nil, 0, 0, 0, errors.Wrapf( 2694 err, "CreateFollowTxn: Problem adding inputs: ") 2695 } 2696 2697 // Sanity-check that the spendAmount is zero. 2698 if err = amountEqualsAdditionalOutputs(spendAmount, additionalOutputs); err != nil { 2699 return nil, 0, 0, 0, fmt.Errorf("CreateFollowTxn: %v", err) 2700 } 2701 2702 return txn, totalInput, changeAmount, fees, nil 2703 } 2704 2705 func (bc *Blockchain) CreateUpdateGlobalParamsTxn(updaterPublicKey []byte, 2706 usdCentsPerBitcoin int64, 2707 createProfileFeesNanos int64, 2708 createNFTFeesNanos int64, 2709 maxCopiesPerNFT int64, 2710 minimumNetworkFeeNanosPerKb int64, 2711 forbiddenPubKey []byte, 2712 // Standard transaction fields 2713 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 2714 _txn *MsgDeSoTxn, _totalInput uint64, _changeAmount uint64, _fees uint64, _err error) { 2715 2716 // Set RepostedPostHash and IsQuotedRepost on the extra data map as necessary to track reposting. 2717 extraData := make(map[string][]byte) 2718 if usdCentsPerBitcoin >= 0 { 2719 extraData[USDCentsPerBitcoinKey] = UintToBuf(uint64(usdCentsPerBitcoin)) 2720 } 2721 if createProfileFeesNanos >= 0 { 2722 extraData[CreateProfileFeeNanosKey] = UintToBuf(uint64(createProfileFeesNanos)) 2723 } 2724 if createNFTFeesNanos >= 0 { 2725 extraData[CreateNFTFeeNanosKey] = UintToBuf(uint64(createNFTFeesNanos)) 2726 } 2727 if maxCopiesPerNFT >= 0 { 2728 extraData[MaxCopiesPerNFTKey] = UintToBuf(uint64(maxCopiesPerNFT)) 2729 } 2730 if minimumNetworkFeeNanosPerKb >= 0 { 2731 extraData[MinNetworkFeeNanosPerKBKey] = UintToBuf(uint64(minimumNetworkFeeNanosPerKb)) 2732 } 2733 if len(forbiddenPubKey) > 0 { 2734 extraData[ForbiddenBlockSignaturePubKeyKey] = forbiddenPubKey 2735 } 2736 2737 txn := &MsgDeSoTxn{ 2738 PublicKey: updaterPublicKey, 2739 TxnMeta: &UpdateGlobalParamsMetadata{}, 2740 ExtraData: extraData, 2741 TxOutputs: additionalOutputs, 2742 } 2743 2744 // We don't need to make any tweaks to the amount because it's basically 2745 // a standard "pay per kilobyte" transaction. 2746 totalInput, spendAmount, changeAmount, fees, err := 2747 bc.AddInputsAndChangeToTransaction(txn, minFeeRateNanosPerKB, mempool) 2748 if err != nil { 2749 return nil, 0, 0, 0, errors.Wrapf(err, "CreateUpdateGlobalParamsTxn: Problem adding inputs: ") 2750 } 2751 2752 // The spend amount should be zero for these txns. 2753 if err = amountEqualsAdditionalOutputs(spendAmount, additionalOutputs); err != nil { 2754 return nil, 0, 0, 0, fmt.Errorf("CreateUpdateGlobalParamsTxn %v", err) 2755 } 2756 2757 return txn, totalInput, changeAmount, fees, nil 2758 } 2759 2760 func (bc *Blockchain) CreateUpdateBitcoinUSDExchangeRateTxn( 2761 // Exchange rate update fields 2762 updaterPublicKey []byte, 2763 usdCentsPerbitcoin uint64, 2764 // Standard transaction fields 2765 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 2766 _txn *MsgDeSoTxn, _totalInput uint64, _changeAmount uint64, _fees uint64, _err error) { 2767 2768 // Create a transaction containing the UpdateBitcoinUSDExchangeRate fields. 2769 txn := &MsgDeSoTxn{ 2770 PublicKey: updaterPublicKey, 2771 TxnMeta: &UpdateBitcoinUSDExchangeRateMetadataa{ 2772 USDCentsPerBitcoin: usdCentsPerbitcoin, 2773 }, 2774 TxOutputs: additionalOutputs, 2775 // We wait to compute the signature until we've added all the 2776 // inputs and change. 2777 } 2778 2779 // We don't need to make any tweaks to the amount because it's basically 2780 // a standard "pay per kilobyte" transaction. 2781 totalInput, spendAmount, changeAmount, fees, err := 2782 bc.AddInputsAndChangeToTransaction(txn, minFeeRateNanosPerKB, mempool) 2783 if err != nil { 2784 return nil, 0, 0, 0, errors.Wrapf(err, "CreateUpdateBitcoinUSDExchangeRateTxn: Problem adding inputs: ") 2785 } 2786 2787 // The spend amount should be zero for these txns. 2788 if err = amountEqualsAdditionalOutputs(spendAmount, additionalOutputs); err != nil { 2789 return nil, 0, 0, 0, fmt.Errorf("CreateUpdateBitcoinUSDExchangeRateTxn: %v", err) 2790 } 2791 2792 return txn, totalInput, changeAmount, fees, nil 2793 } 2794 2795 func (bc *Blockchain) CreateSubmitPostTxn( 2796 // Post fields 2797 updaterPublicKey []byte, 2798 postHashToModify []byte, 2799 parentStakeID []byte, 2800 body []byte, 2801 repostPostHashBytes []byte, 2802 isQuotedRepost bool, 2803 tstampNanos uint64, 2804 postExtraData map[string][]byte, 2805 isHidden bool, 2806 // Standard transaction fields 2807 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 2808 _txn *MsgDeSoTxn, _totalInput uint64, _changeAmount uint64, _fees uint64, _err error) { 2809 2810 // Initialize txnExtraData to postExtraData. 2811 txnExtraData := postExtraData 2812 // Remove consensus level attributes from TxnExtraData if they exist. The consensus logic will set them correctly. 2813 for _, key := range PostExtraDataConsensusKeys { 2814 delete(txnExtraData, key) 2815 } 2816 2817 // Set RepostedPostHash and IsQuotedRepost on the extra data map as necessary to track reposting. 2818 if len(repostPostHashBytes) > 0 { 2819 txnExtraData[RepostedPostHash] = repostPostHashBytes 2820 if isQuotedRepost { 2821 txnExtraData[IsQuotedRepostKey] = QuotedRepostVal 2822 } else { 2823 txnExtraData[IsQuotedRepostKey] = NotQuotedRepostVal 2824 } 2825 } 2826 2827 // Create a transaction containing the post fields. 2828 txn := &MsgDeSoTxn{ 2829 PublicKey: updaterPublicKey, 2830 TxnMeta: &SubmitPostMetadata{ 2831 PostHashToModify: postHashToModify, 2832 ParentStakeID: parentStakeID, 2833 Body: body, 2834 CreatorBasisPoints: 10 * 100, 2835 StakeMultipleBasisPoints: 1.25 * 100 * 100, 2836 TimestampNanos: tstampNanos, 2837 IsHidden: isHidden, 2838 }, 2839 TxOutputs: additionalOutputs, 2840 // We wait to compute the signature until we've added all the 2841 // inputs and change. 2842 } 2843 // Only set transaction's ExtraData if there is at least one key in the extra data map. 2844 if len(txnExtraData) > 0 { 2845 txn.ExtraData = txnExtraData 2846 } 2847 2848 // We don't need to make any tweaks to the amount because it's basically 2849 // a standard "pay per kilobyte" transaction. 2850 totalInput, spendAmount, changeAmount, fees, err := 2851 bc.AddInputsAndChangeToTransaction(txn, minFeeRateNanosPerKB, mempool) 2852 if err != nil { 2853 return nil, 0, 0, 0, errors.Wrapf(err, "CreateSubmitPostTxn: Problem adding inputs: ") 2854 } 2855 2856 // The spend amount should be zero for post submissions. 2857 if err = amountEqualsAdditionalOutputs(spendAmount, additionalOutputs); err != nil { 2858 return nil, 0, 0, 0, fmt.Errorf("CreateSubmitPostTxn: %v", err) 2859 } 2860 2861 return txn, totalInput, changeAmount, fees, nil 2862 } 2863 2864 func (bc *Blockchain) CreateUpdateProfileTxn( 2865 UpdaterPublicKeyBytes []byte, 2866 // Optional. Only set when the owner of the profile is != to the updater. 2867 OptionalProfilePublicKeyBytes []byte, 2868 NewUsername string, 2869 NewDescription string, 2870 NewProfilePic string, 2871 NewCreatorBasisPoints uint64, 2872 NewStakeMultipleBasisPoints uint64, 2873 IsHidden bool, 2874 AdditionalFees uint64, 2875 // Standard transaction fields 2876 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 2877 _txn *MsgDeSoTxn, _totalInput uint64, _changeAmount uint64, _fees uint64, _err error) { 2878 2879 // Create a transaction containing the profile fields. 2880 txn := &MsgDeSoTxn{ 2881 PublicKey: UpdaterPublicKeyBytes, 2882 TxnMeta: &UpdateProfileMetadata{ 2883 ProfilePublicKey: OptionalProfilePublicKeyBytes, 2884 NewUsername: []byte(NewUsername), 2885 NewDescription: []byte(NewDescription), 2886 NewProfilePic: []byte(NewProfilePic), 2887 NewCreatorBasisPoints: NewCreatorBasisPoints, 2888 NewStakeMultipleBasisPoints: NewStakeMultipleBasisPoints, 2889 IsHidden: IsHidden, 2890 }, 2891 TxOutputs: additionalOutputs, 2892 // We wait to compute the signature until we've added all the 2893 // inputs and change. 2894 2895 } 2896 2897 // We directly call AddInputsAndChangeToTransactionWithSubsidy so we can pass through the create profile fee. 2898 totalInput, spendAmount, changeAmount, fees, err := 2899 bc.AddInputsAndChangeToTransactionWithSubsidy(txn, minFeeRateNanosPerKB, 0, mempool, AdditionalFees) 2900 if err != nil { 2901 return nil, 0, 0, 0, errors.Wrapf(err, "CreateUpdateProfileTxn: Problem adding inputs: ") 2902 } 2903 2904 // The spend amount should equal to the additional fees for profile submissions. 2905 if err = amountEqualsAdditionalOutputs(spendAmount-AdditionalFees, additionalOutputs); err != nil { 2906 return nil, 0, 0, 0, fmt.Errorf("CreateUpdateProfileTxn: %v", err) 2907 } 2908 2909 return txn, totalInput, changeAmount, fees, nil 2910 } 2911 2912 func (bc *Blockchain) CreateSwapIdentityTxn( 2913 UpdaterPublicKeyBytes []byte, 2914 FromPublicKeyBytes []byte, 2915 ToPublicKeyBytes []byte, 2916 2917 // Standard transaction fields 2918 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 2919 _txn *MsgDeSoTxn, _totalInput uint64, _changeAmount uint64, _fees uint64, _err error) { 2920 2921 // Create a transaction containing the profile fields. 2922 txn := &MsgDeSoTxn{ 2923 PublicKey: UpdaterPublicKeyBytes, 2924 TxnMeta: &SwapIdentityMetadataa{ 2925 FromPublicKey: FromPublicKeyBytes, 2926 ToPublicKey: ToPublicKeyBytes, 2927 }, 2928 TxOutputs: additionalOutputs, 2929 // We wait to compute the signature until we've added all the 2930 // inputs and change. 2931 } 2932 2933 // We don't need to make any tweaks to the amount because it's basically 2934 // a standard "pay per kilobyte" transaction. 2935 totalInput, spendAmount, changeAmount, fees, err := 2936 bc.AddInputsAndChangeToTransaction(txn, minFeeRateNanosPerKB, mempool) 2937 if err != nil { 2938 return nil, 0, 0, 0, errors.Wrapf(err, "CreateUpdateProfileTxn: Problem adding inputs: ") 2939 } 2940 2941 // The spend amount should be zero for SwapIdentity txns. 2942 if err = amountEqualsAdditionalOutputs(spendAmount, additionalOutputs); err != nil { 2943 return nil, 0, 0, 0, fmt.Errorf("CreateUpdateProfileTxn: %v", err) 2944 } 2945 2946 return txn, totalInput, changeAmount, fees, nil 2947 } 2948 2949 func (bc *Blockchain) CreateCreatorCoinTxn( 2950 UpdaterPublicKey []byte, 2951 // See CreatorCoinMetadataa for an explanation of these fields. 2952 ProfilePublicKey []byte, 2953 OperationType CreatorCoinOperationType, 2954 DeSoToSellNanos uint64, 2955 CreatorCoinToSellNanos uint64, 2956 DeSoToAddNanos uint64, 2957 MinDeSoExpectedNanos uint64, 2958 MinCreatorCoinExpectedNanos uint64, 2959 // Standard transaction fields 2960 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 2961 _txn *MsgDeSoTxn, _totalInput uint64, _changeAmount uint64, _fees uint64, _err error) { 2962 2963 // Create a transaction containing the creator coin fields. 2964 txn := &MsgDeSoTxn{ 2965 PublicKey: UpdaterPublicKey, 2966 TxnMeta: &CreatorCoinMetadataa{ 2967 ProfilePublicKey, 2968 OperationType, 2969 DeSoToSellNanos, 2970 CreatorCoinToSellNanos, 2971 DeSoToAddNanos, 2972 MinDeSoExpectedNanos, 2973 MinCreatorCoinExpectedNanos, 2974 }, 2975 TxOutputs: additionalOutputs, 2976 // We wait to compute the signature until we've added all the 2977 // inputs and change. 2978 } 2979 2980 // We don't need to make any tweaks to the amount because it's basically 2981 // a standard "pay per kilobyte" transaction. 2982 totalInput, spendAmount, changeAmount, fees, err := 2983 bc.AddInputsAndChangeToTransaction( 2984 txn, minFeeRateNanosPerKB, mempool) 2985 if err != nil { 2986 return nil, 0, 0, 0, errors.Wrapf(err, "CreateCreatorCoinTxn: Problem adding inputs: ") 2987 } 2988 _ = spendAmount 2989 2990 // We want our transaction to have at least one input, even if it all 2991 // goes to change. This ensures that the transaction will not be "replayable." 2992 if len(txn.TxInputs) == 0 { 2993 return nil, 0, 0, 0, fmt.Errorf("CreateCreatorCoinTxn: CreatorCoin txn " + 2994 "must have at least one input but had zero inputs " + 2995 "instead. Try increasing the fee rate.") 2996 } 2997 2998 return txn, totalInput, changeAmount, fees, nil 2999 } 3000 3001 func (bc *Blockchain) CreateCreatorCoinTransferTxn( 3002 UpdaterPublicKey []byte, 3003 ProfilePublicKey []byte, 3004 CreatorCoinToTransferNanos uint64, 3005 RecipientPublicKey []byte, 3006 // Standard transaction fields 3007 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 3008 _txn *MsgDeSoTxn, _totalInput uint64, _changeAmount uint64, _fees uint64, _err error) { 3009 3010 // Create a transaction containing the creator coin fields. 3011 txn := &MsgDeSoTxn{ 3012 PublicKey: UpdaterPublicKey, 3013 TxnMeta: &CreatorCoinTransferMetadataa{ 3014 ProfilePublicKey, 3015 CreatorCoinToTransferNanos, 3016 RecipientPublicKey, 3017 }, 3018 TxOutputs: additionalOutputs, 3019 // We wait to compute the signature until we've added all the 3020 // inputs and change. 3021 } 3022 3023 // We don't need to make any tweaks to the amount because it's basically 3024 // a standard "pay per kilobyte" transaction. 3025 totalInput, spendAmount, changeAmount, fees, err := 3026 bc.AddInputsAndChangeToTransaction(txn, minFeeRateNanosPerKB, mempool) 3027 if err != nil { 3028 return nil, 0, 0, 0, errors.Wrapf(err, "CreateCreatorCoinTransferTxn: Problem adding inputs: ") 3029 } 3030 _ = spendAmount 3031 3032 // We want our transaction to have at least one input, even if it all 3033 // goes to change. This ensures that the transaction will not be "replayable." 3034 if len(txn.TxInputs) == 0 { 3035 return nil, 0, 0, 0, fmt.Errorf("CreateCreatorCoinTransferTxn: CreatorCoinTransfer txn " + 3036 "must have at least one input but had zero inputs " + 3037 "instead. Try increasing the fee rate.") 3038 } 3039 3040 return txn, totalInput, changeAmount, fees, nil 3041 } 3042 3043 func (bc *Blockchain) CreateCreateNFTTxn( 3044 UpdaterPublicKey []byte, 3045 NFTPostHash *BlockHash, 3046 NumCopies uint64, 3047 HasUnlockable bool, 3048 IsForSale bool, 3049 MinBidAmountNanos uint64, 3050 NFTFee uint64, 3051 NFTRoyaltyToCreatorBasisPoints uint64, 3052 NFTRoyaltyToCoinBasisPoints uint64, 3053 // Standard transaction fields 3054 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 3055 _txn *MsgDeSoTxn, _totalInput uint64, _changeAmount uint64, _fees uint64, _err error) { 3056 3057 // Create a transaction containing the create NFT fields. 3058 txn := &MsgDeSoTxn{ 3059 PublicKey: UpdaterPublicKey, 3060 TxnMeta: &CreateNFTMetadata{ 3061 NFTPostHash, 3062 NumCopies, 3063 HasUnlockable, 3064 IsForSale, 3065 MinBidAmountNanos, 3066 NFTRoyaltyToCreatorBasisPoints, 3067 NFTRoyaltyToCoinBasisPoints, 3068 }, 3069 TxOutputs: additionalOutputs, 3070 // We wait to compute the signature until we've added all the 3071 // inputs and change. 3072 } 3073 3074 // We directly call AddInputsAndChangeToTransactionWithSubsidy so we can pass through the NFT fee. 3075 totalInput, _, changeAmount, fees, err := 3076 bc.AddInputsAndChangeToTransactionWithSubsidy(txn, minFeeRateNanosPerKB, 0, mempool, NFTFee) 3077 if err != nil { 3078 return nil, 0, 0, 0, errors.Wrapf(err, "CreateCreateNFTTxn: Problem adding inputs: ") 3079 } 3080 3081 // We want our transaction to have at least one input, even if it all 3082 // goes to change. This ensures that the transaction will not be "replayable." 3083 if len(txn.TxInputs) == 0 { 3084 return nil, 0, 0, 0, fmt.Errorf("CreateCreateNFTTxn: CreateNFT txn " + 3085 "must have at least one input but had zero inputs " + 3086 "instead. Try increasing the fee rate.") 3087 } 3088 3089 return txn, totalInput, changeAmount, fees, nil 3090 } 3091 3092 func (bc *Blockchain) CreateNFTBidTxn( 3093 UpdaterPublicKey []byte, 3094 NFTPostHash *BlockHash, 3095 SerialNumber uint64, 3096 BidAmountNanos uint64, 3097 // Standard transaction fields 3098 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 3099 _txn *MsgDeSoTxn, _totalInput uint64, _changeAmount uint64, _fees uint64, _err error) { 3100 3101 // Create a transaction containing the NFT bid fields. 3102 txn := &MsgDeSoTxn{ 3103 PublicKey: UpdaterPublicKey, 3104 TxnMeta: &NFTBidMetadata{ 3105 NFTPostHash, 3106 SerialNumber, 3107 BidAmountNanos, 3108 }, 3109 TxOutputs: additionalOutputs, 3110 // We wait to compute the signature until we've added all the 3111 // inputs and change. 3112 } 3113 3114 // Add inputs and change for a standard pay per KB transaction. 3115 totalInput, _, changeAmount, fees, err := 3116 bc.AddInputsAndChangeToTransaction(txn, minFeeRateNanosPerKB, mempool) 3117 if err != nil { 3118 return nil, 0, 0, 0, errors.Wrapf(err, "CreateNFTBidTxn: Problem adding inputs: ") 3119 } 3120 3121 // We want our transaction to have at least one input, even if it all 3122 // goes to change. This ensures that the transaction will not be "replayable." 3123 if len(txn.TxInputs) == 0 { 3124 return nil, 0, 0, 0, fmt.Errorf("CreateNFTBidTxn: NFTBid txn " + 3125 "must have at least one input but had zero inputs " + 3126 "instead. Try increasing the fee rate.") 3127 } 3128 3129 return txn, totalInput, changeAmount, fees, nil 3130 } 3131 3132 func (bc *Blockchain) CreateNFTTransferTxn( 3133 SenderPublicKey []byte, 3134 ReceiverPublicKey []byte, 3135 NFTPostHash *BlockHash, 3136 SerialNumber uint64, 3137 EncryptedUnlockableTextBytes []byte, 3138 // Standard transaction fields 3139 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 3140 _txn *MsgDeSoTxn, _totalInput uint64, _changeAmount uint64, _fees uint64, _err error) { 3141 3142 // Create a transaction containing the NFT transfer fields. 3143 txn := &MsgDeSoTxn{ 3144 PublicKey: SenderPublicKey, 3145 TxnMeta: &NFTTransferMetadata{ 3146 NFTPostHash, 3147 SerialNumber, 3148 ReceiverPublicKey, 3149 EncryptedUnlockableTextBytes, 3150 }, 3151 TxOutputs: additionalOutputs, 3152 // We wait to compute the signature until we've added all the 3153 // inputs and change. 3154 } 3155 3156 // Add inputs and change for a standard pay per KB transaction. 3157 totalInput, _, changeAmount, fees, err := 3158 bc.AddInputsAndChangeToTransaction(txn, minFeeRateNanosPerKB, mempool) 3159 if err != nil { 3160 return nil, 0, 0, 0, errors.Wrapf(err, "CreateNFTTransferTxn: Problem adding inputs: ") 3161 } 3162 3163 // We want our transaction to have at least one input, even if it all 3164 // goes to change. This ensures that the transaction will not be "replayable." 3165 if len(txn.TxInputs) == 0 { 3166 return nil, 0, 0, 0, fmt.Errorf("CreateNFTTransferTxn: NFTTransfer txn must have " + 3167 "at least one input but had zero inputs instead. Try increasing the fee rate.") 3168 } 3169 3170 return txn, totalInput, changeAmount, fees, nil 3171 } 3172 3173 func (bc *Blockchain) CreateAcceptNFTTransferTxn( 3174 UpdaterPublicKey []byte, 3175 NFTPostHash *BlockHash, 3176 SerialNumber uint64, 3177 // Standard transaction fields 3178 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 3179 _txn *MsgDeSoTxn, _totalInput uint64, _changeAmount uint64, _fees uint64, _err error) { 3180 3181 // Create a transaction containing the accept NFT transfer fields. 3182 txn := &MsgDeSoTxn{ 3183 PublicKey: UpdaterPublicKey, 3184 TxnMeta: &AcceptNFTTransferMetadata{ 3185 NFTPostHash, 3186 SerialNumber, 3187 }, 3188 TxOutputs: additionalOutputs, 3189 // We wait to compute the signature until we've added all the 3190 // inputs and change. 3191 } 3192 3193 // Add inputs and change for a standard pay per KB transaction. 3194 totalInput, _, changeAmount, fees, err := 3195 bc.AddInputsAndChangeToTransaction(txn, minFeeRateNanosPerKB, mempool) 3196 if err != nil { 3197 return nil, 0, 0, 0, errors.Wrapf(err, 3198 "CreateAcceptNFTTransferTxn: Problem adding inputs: ") 3199 } 3200 3201 // We want our transaction to have at least one input, even if it all 3202 // goes to change. This ensures that the transaction will not be "replayable." 3203 if len(txn.TxInputs) == 0 { 3204 return nil, 0, 0, 0, fmt.Errorf( 3205 "CreateAcceptNFTTransferTxn: AcceptNFTTransfer txn must have at least one input" + 3206 " but had zero inputs instead. Try increasing the fee rate.") 3207 } 3208 3209 return txn, totalInput, changeAmount, fees, nil 3210 } 3211 3212 func (bc *Blockchain) CreateBurnNFTTxn( 3213 UpdaterPublicKey []byte, 3214 NFTPostHash *BlockHash, 3215 SerialNumber uint64, 3216 // Standard transaction fields 3217 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 3218 _txn *MsgDeSoTxn, _totalInput uint64, _changeAmount uint64, _fees uint64, _err error) { 3219 3220 // Create a transaction containing the burn NFT fields. 3221 txn := &MsgDeSoTxn{ 3222 PublicKey: UpdaterPublicKey, 3223 TxnMeta: &BurnNFTMetadata{ 3224 NFTPostHash, 3225 SerialNumber, 3226 }, 3227 TxOutputs: additionalOutputs, 3228 // We wait to compute the signature until we've added all the 3229 // inputs and change. 3230 } 3231 3232 // Add inputs and change for a standard pay per KB transaction. 3233 totalInput, _, changeAmount, fees, err := 3234 bc.AddInputsAndChangeToTransaction(txn, minFeeRateNanosPerKB, mempool) 3235 if err != nil { 3236 return nil, 0, 0, 0, errors.Wrapf(err, "CreateBurnNFTTxn: Problem adding inputs: ") 3237 } 3238 3239 // We want our transaction to have at least one input, even if it all 3240 // goes to change. This ensures that the transaction will not be "replayable." 3241 if len(txn.TxInputs) == 0 { 3242 return nil, 0, 0, 0, fmt.Errorf("CreateBurnNFTTxn: BurnNFT txn must have at least " + 3243 "one input but had zero inputs instead. Try increasing the fee rate.") 3244 } 3245 3246 return txn, totalInput, changeAmount, fees, nil 3247 } 3248 3249 func (bc *Blockchain) CreateAcceptNFTBidTxn( 3250 UpdaterPublicKey []byte, 3251 NFTPostHash *BlockHash, 3252 SerialNumber uint64, 3253 BidderPKID *PKID, 3254 BidAmountNanos uint64, 3255 EncryptedUnlockableTextBytes []byte, 3256 // Standard transaction fields 3257 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 3258 _txn *MsgDeSoTxn, _totalInput uint64, _changeAmount uint64, _fees uint64, _err error) { 3259 3260 // Create a new UtxoView. If we have access to a mempool object, use it to 3261 // get an augmented view that factors in pending transactions. 3262 utxoView, err := NewUtxoView(bc.db, bc.params, bc.postgres) 3263 if err != nil { 3264 return nil, 0, 0, 0, errors.Wrapf(err, 3265 "Blockchain.CreateAcceptNFTBidTxn: Problem creating new utxo view: ") 3266 } 3267 if mempool != nil { 3268 utxoView, err = mempool.GetAugmentedUniversalView() 3269 if err != nil { 3270 return nil, 0, 0, 0, errors.Wrapf(err, 3271 "Blockchain.CreateAcceptNFTBidTxn: Problem getting augmented UtxoView from mempool: ") 3272 } 3273 } 3274 3275 // Get the spendable UtxoEntrys. 3276 bidderPkBytes := utxoView.GetPublicKeyForPKID(BidderPKID) 3277 bidderSpendableUtxos, err := bc.GetSpendableUtxosForPublicKey(bidderPkBytes, nil, utxoView) 3278 if err != nil { 3279 return nil, 0, 0, 0, errors.Wrapf(err, "Blockchain.CreateAcceptNFTBidTxn: Problem getting spendable UtxoEntrys: ") 3280 } 3281 3282 // Add input utxos to the transaction until we have enough total input to cover 3283 // the amount we want to spend plus the maximum fee (or until we've exhausted 3284 // all the utxos available). 3285 bidderInputs := []*DeSoInput{} 3286 totalBidderInput := uint64(0) 3287 for _, utxoEntry := range bidderSpendableUtxos { 3288 3289 // If the amount of input we have isn't enough to cover the bid amount, add an input and continue. 3290 if totalBidderInput < BidAmountNanos { 3291 bidderInputs = append(bidderInputs, (*DeSoInput)(utxoEntry.UtxoKey)) 3292 3293 amountToAdd := utxoEntry.AmountNanos 3294 // For Bitcoin burns, we subtract a tiny amount of slippage to the amount we can 3295 // spend. This makes reorderings more forgiving. 3296 if utxoEntry.UtxoType == UtxoTypeBitcoinBurn { 3297 amountToAdd = uint64(float64(amountToAdd) * .999) 3298 } 3299 3300 totalBidderInput += amountToAdd 3301 continue 3302 } 3303 3304 // If we get here, we know we have enough input to cover the upper bound 3305 // estimate of our amount needed so break. 3306 break 3307 } 3308 3309 // If we get here and we don't have sufficient input to cover the bid, error. 3310 if totalBidderInput < BidAmountNanos { 3311 return nil, 0, 0, 0, fmt.Errorf("Blockchain.CreateAcceptNFTBidTxn: Bidder has insufficient "+ 3312 "UTXOs (%d total) to cover BidAmountNanos %d: ", totalBidderInput, BidAmountNanos) 3313 } 3314 3315 // Create a transaction containing the accept nft bid fields. 3316 txn := &MsgDeSoTxn{ 3317 PublicKey: UpdaterPublicKey, 3318 TxnMeta: &AcceptNFTBidMetadata{ 3319 NFTPostHash, 3320 SerialNumber, 3321 BidderPKID, 3322 BidAmountNanos, 3323 EncryptedUnlockableTextBytes, 3324 bidderInputs, 3325 }, 3326 TxOutputs: additionalOutputs, 3327 // We wait to compute the signature until we've added all the 3328 // inputs and change. 3329 } 3330 3331 // Add inputs and change for a standard pay per KB transaction. 3332 totalInput, _, changeAmount, fees, err := 3333 bc.AddInputsAndChangeToTransaction(txn, minFeeRateNanosPerKB, mempool) 3334 if err != nil { 3335 return nil, 0, 0, 0, errors.Wrapf(err, "CreateAcceptNFTBidTxn: Problem adding inputs: ") 3336 } 3337 3338 // We want our transaction to have at least one input, even if it all 3339 // goes to change. This ensures that the transaction will not be "replayable." 3340 if len(txn.TxInputs) == 0 { 3341 return nil, 0, 0, 0, fmt.Errorf("CreateAcceptNFTBidTxn: AcceptNFTBid txn " + 3342 "must have at least one input but had zero inputs " + 3343 "instead. Try increasing the fee rate.") 3344 } 3345 3346 return txn, totalInput, changeAmount, fees, nil 3347 } 3348 3349 func (bc *Blockchain) CreateUpdateNFTTxn( 3350 UpdaterPublicKey []byte, 3351 NFTPostHash *BlockHash, 3352 SerialNumber uint64, 3353 IsForSale bool, 3354 MinBidAmountNanos uint64, 3355 // Standard transaction fields 3356 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 3357 _txn *MsgDeSoTxn, _totalInput uint64, _changeAmount uint64, _fees uint64, _err error) { 3358 3359 // Create a transaction containing the update NFT fields. 3360 txn := &MsgDeSoTxn{ 3361 PublicKey: UpdaterPublicKey, 3362 TxnMeta: &UpdateNFTMetadata{ 3363 NFTPostHash, 3364 SerialNumber, 3365 IsForSale, 3366 MinBidAmountNanos, 3367 }, 3368 TxOutputs: additionalOutputs, 3369 // We wait to compute the signature until we've added all the 3370 // inputs and change. 3371 } 3372 3373 // Add inputs and change for a standard pay per KB transaction. 3374 totalInput, spendAmount, changeAmount, fees, err := 3375 bc.AddInputsAndChangeToTransaction(txn, minFeeRateNanosPerKB, mempool) 3376 if err != nil { 3377 return nil, 0, 0, 0, errors.Wrapf(err, "CreateUpdateNFTTxn: Problem adding inputs: ") 3378 } 3379 _ = spendAmount 3380 3381 // We want our transaction to have at least one input, even if it all 3382 // goes to change. This ensures that the transaction will not be "replayable." 3383 if len(txn.TxInputs) == 0 { 3384 return nil, 0, 0, 0, fmt.Errorf("CreateUpdateNFTTxn: AcceptNFTBid txn " + 3385 "must have at least one input but had zero inputs " + 3386 "instead. Try increasing the fee rate.") 3387 } 3388 3389 return txn, totalInput, changeAmount, fees, nil 3390 } 3391 3392 // Each diamond level is worth a fixed amount of DeSo. These amounts can be changed 3393 // in the future by simply returning a new set of values after a particular block height. 3394 func GetDeSoNanosDiamondLevelMapAtBlockHeight( 3395 blockHeight int64) map[int64]uint64 { 3396 3397 return map[int64]uint64{ 3398 1: 50000, 3399 2: 500000, 3400 3: 5000000, 3401 4: 50000000, 3402 5: 500000000, 3403 6: 5000000000, 3404 7: 50000000000, 3405 8: 500000000000, 3406 } 3407 } 3408 3409 func GetDeSoNanosForDiamondLevelAtBlockHeight( 3410 diamondLevel int64, blockHeight int64) uint64 { 3411 3412 // Caller is responsible for passing a valid diamond level. 3413 desoNanosMap := GetDeSoNanosDiamondLevelMapAtBlockHeight(blockHeight) 3414 desoNanosForLevel, levelExists := desoNanosMap[diamondLevel] 3415 if !levelExists { 3416 // We allow a special case for diamondLevel zero, in which case we 3417 // know that the value should also be zero. 3418 if diamondLevel != 0 { 3419 // If a non-existent level is requested, return zero 3420 glog.Errorf("GetDeSoNanosForDiamondLevelAtBlockHeight: "+ 3421 "Diamond level %v does not exist in map %v; this should never happen", 3422 diamondLevel, desoNanosMap) 3423 } 3424 return 0 3425 } 3426 3427 return desoNanosForLevel 3428 } 3429 3430 // At a particular diamond level, a fixed amount of DeSo is converted into creator coins 3431 // and then sent to a user. This function computes the amount of creator coins required for 3432 // a particular level. 3433 func GetCreatorCoinNanosForDiamondLevelAtBlockHeight( 3434 coinsInCirculationNanos uint64, desoLockedNanos uint64, 3435 diamondLevel int64, blockHeight int64, params *DeSoParams) uint64 { 3436 3437 // No creator coins are required at level zero 3438 if diamondLevel == 0 { 3439 return 0 3440 } 3441 3442 // First get the amount of DeSo required by this level. 3443 desoNanosForLevel := GetDeSoNanosForDiamondLevelAtBlockHeight( 3444 diamondLevel, blockHeight) 3445 3446 // Figure out the amount of creator coins to print based on the user's CoinEntry. 3447 return CalculateCreatorCoinToMint( 3448 desoNanosForLevel, coinsInCirculationNanos, 3449 desoLockedNanos, params) 3450 } 3451 3452 func (bc *Blockchain) CreateCreatorCoinTransferTxnWithDiamonds( 3453 SenderPublicKey []byte, 3454 ReceiverPublicKey []byte, 3455 DiamondPostHash *BlockHash, 3456 DiamondLevel int64, 3457 // Standard transaction fields 3458 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 3459 _txn *MsgDeSoTxn, _totalInput uint64, _changeAmount uint64, _fees uint64, _err error) { 3460 3461 // Create a new UtxoView. If we have access to a mempool object, use it to 3462 // get an augmented view that factors in pending transactions. 3463 utxoView, err := NewUtxoView(bc.db, bc.params, bc.postgres) 3464 if err != nil { 3465 return nil, 0, 0, 0, errors.Wrapf(err, 3466 "Blockchain.CreateCreatorCoinTransferTxnWithDiamonds: "+ 3467 "Problem creating new utxo view: ") 3468 } 3469 if mempool != nil { 3470 utxoView, err = mempool.GetAugmentedUniversalView() 3471 if err != nil { 3472 return nil, 0, 0, 0, errors.Wrapf(err, 3473 "Blockchain.CreateCreatorCoinTransferTxnWithDiamonds: "+ 3474 "Problem getting augmented UtxoView from mempool: ") 3475 } 3476 } 3477 3478 blockHeight := bc.blockTip().Height + 1 3479 creatorCoinToTransferNanos, _, err := utxoView.ValidateDiamondsAndGetNumCreatorCoinNanos( 3480 SenderPublicKey, ReceiverPublicKey, DiamondPostHash, DiamondLevel, blockHeight) 3481 if err != nil { 3482 return nil, 0, 0, 0, errors.Wrapf( 3483 err, "Blockchain.CreateCreatorCoinTransferTxnWithDiamonds: Problem getting creator coin nanos: ") 3484 } 3485 3486 // Create a transaction containing the creator coin fields. 3487 txn := &MsgDeSoTxn{ 3488 PublicKey: SenderPublicKey, 3489 TxnMeta: &CreatorCoinTransferMetadataa{ 3490 SenderPublicKey, 3491 // Buffer the creatorCoinToTransferNanos to factor in some slippage in the 3492 // creator coin price. Transferring more than is needed is allowed, but 3493 // undershooting will cause the transaction to be rejected. 3494 uint64(float64(creatorCoinToTransferNanos) * 1.05), 3495 ReceiverPublicKey, 3496 }, 3497 TxOutputs: additionalOutputs, 3498 // We wait to compute the signature until we've added all the 3499 // inputs and change. 3500 } 3501 3502 // Make a map for the diamond extra data. 3503 diamondsExtraData := make(map[string][]byte) 3504 diamondsExtraData[DiamondLevelKey] = IntToBuf(DiamondLevel) 3505 diamondsExtraData[DiamondPostHashKey] = DiamondPostHash[:] 3506 txn.ExtraData = diamondsExtraData 3507 3508 // We don't need to make any tweaks to the amount because it's basically 3509 // a standard "pay per kilobyte" transaction. 3510 totalInput, spendAmount, changeAmount, fees, err := 3511 bc.AddInputsAndChangeToTransaction(txn, minFeeRateNanosPerKB, mempool) 3512 if err != nil { 3513 return nil, 0, 0, 0, errors.Wrapf( 3514 err, "CreateCreatorCoinTransferTxnWithDiamonds: Problem adding inputs: ") 3515 } 3516 _ = spendAmount 3517 3518 // We want our transaction to have at least one input, even if it all 3519 // goes to change. This ensures that the transaction will not be "replayable." 3520 if len(txn.TxInputs) == 0 { 3521 return nil, 0, 0, 0, fmt.Errorf( 3522 "CreateCreatorCoinTransferTxnWithDiamonds: CreatorCoinTransfer txn must have at" + 3523 " least one input but had zero inputs instead. Try increasing the fee rate.") 3524 } 3525 3526 return txn, totalInput, changeAmount, fees, nil 3527 } 3528 3529 func (bc *Blockchain) CreateAuthorizeDerivedKeyTxn( 3530 ownerPublicKey []byte, 3531 derivedPublicKey []byte, 3532 expirationBlock uint64, 3533 accessSignature []byte, 3534 deleteKey bool, 3535 derivedKeySignature bool, 3536 // Standard transaction fields 3537 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 3538 _txn *MsgDeSoTxn, _totalInput uint64, _changeAmount uint64, _fees uint64, _err error) { 3539 3540 // Verify that the signature is valid. 3541 err := _verifyAccessSignature(ownerPublicKey, derivedPublicKey, 3542 expirationBlock, accessSignature) 3543 if err != nil { 3544 return nil, 0, 0, 0, errors.Wrapf(err, 3545 "Blockchain.CreateAuthorizeDerivedKeyTxn: Problem verifying access signature") 3546 } 3547 3548 // Check that the expiration block is valid. 3549 blockHeight := bc.blockTip().Height + 1 3550 if expirationBlock <= uint64(blockHeight) { 3551 return nil, 0, 0, 0, fmt.Errorf( 3552 "Blockchain.CreateAuthorizeDerivedKeyTxn: Expired access signature") 3553 } 3554 3555 // Get the appropriate operation type. 3556 var operationType AuthorizeDerivedKeyOperationType 3557 if deleteKey { 3558 operationType = AuthorizeDerivedKeyOperationNotValid 3559 } else { 3560 operationType = AuthorizeDerivedKeyOperationValid 3561 } 3562 3563 extraData := make(map[string][]byte) 3564 if derivedKeySignature { 3565 extraData[DerivedPublicKey] = derivedPublicKey 3566 } 3567 3568 // Create a transaction containing the authorize derived key fields. 3569 txn := &MsgDeSoTxn{ 3570 PublicKey: ownerPublicKey, 3571 TxnMeta: &AuthorizeDerivedKeyMetadata{ 3572 derivedPublicKey, 3573 expirationBlock, 3574 operationType, 3575 accessSignature, 3576 }, 3577 TxOutputs: additionalOutputs, 3578 ExtraData: extraData, 3579 // We wait to compute the signature until we've added all the 3580 // inputs and change. 3581 } 3582 3583 // We don't need to make any tweaks to the amount because it's basically 3584 // a standard "pay per kilobyte" transaction. 3585 totalInput, spendAmount, changeAmount, fees, err := 3586 bc.AddInputsAndChangeToTransaction(txn, minFeeRateNanosPerKB, mempool) 3587 if err != nil { 3588 return nil, 0, 0, 0, errors.Wrapf(err, "CreateAuthorizeDerivedKeyTxn: Problem adding inputs: ") 3589 } 3590 3591 // Sanity-check that the spendAmount is zero. 3592 if spendAmount != 0 { 3593 return nil, 0, 0, 0, fmt.Errorf("CreateAuthorizeDerivedKeyTxn: Spend amount "+ 3594 "should be zero but was %d instead: ", spendAmount) 3595 } 3596 3597 return txn, totalInput, changeAmount, fees, nil 3598 } 3599 3600 func (bc *Blockchain) CreateBasicTransferTxnWithDiamonds( 3601 SenderPublicKey []byte, 3602 DiamondPostHash *BlockHash, 3603 DiamondLevel int64, 3604 // Standard transaction fields 3605 minFeeRateNanosPerKB uint64, mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 3606 _txn *MsgDeSoTxn, _totalInput uint64, _spendAmount uint64, _changeAmount uint64, _fees uint64, _err error) { 3607 3608 // Create a new UtxoView. If we have access to a mempool object, use it to 3609 // get an augmented view that factors in pending transactions. 3610 utxoView, err := NewUtxoView(bc.db, bc.params, bc.postgres) 3611 if err != nil { 3612 return nil, 0, 0, 0, 0, errors.Wrapf(err, 3613 "Blockchain.CreateBasicTransferTxnWithDiamonds: "+ 3614 "Problem creating new utxo view: ") 3615 } 3616 if mempool != nil { 3617 utxoView, err = mempool.GetAugmentedUniversalView() 3618 if err != nil { 3619 return nil, 0, 0, 0, 0, errors.Wrapf(err, 3620 "Blockchain.CreateBasicTransferTxnWithDiamonds: "+ 3621 "Problem getting augmented UtxoView from mempool: ") 3622 } 3623 } 3624 3625 // Get the post that we are trying to diamond so that we have the receiver public key. 3626 diamondPostEntry := utxoView.GetPostEntryForPostHash(DiamondPostHash) 3627 if diamondPostEntry == nil || diamondPostEntry.isDeleted { 3628 return nil, 0, 0, 0, 0, fmt.Errorf( 3629 "Blockchain.CreateBasicTransferTxnWithDiamonds: " + 3630 "Problem getting post entry for post hash") 3631 } 3632 3633 blockHeight := bc.blockTip().Height + 1 3634 desoToTransferNanos, _, err := utxoView.ValidateDiamondsAndGetNumDeSoNanos( 3635 SenderPublicKey, diamondPostEntry.PosterPublicKey, DiamondPostHash, DiamondLevel, blockHeight) 3636 if err != nil { 3637 return nil, 0, 0, 0, 0, errors.Wrapf( 3638 err, "Blockchain.CreateBasicTransferTxnWithDiamonds: Problem getting deso nanos: ") 3639 } 3640 3641 // Build the basic transfer txn. 3642 txn := &MsgDeSoTxn{ 3643 PublicKey: SenderPublicKey, 3644 TxnMeta: &BasicTransferMetadata{}, 3645 TxOutputs: append(additionalOutputs, &DeSoOutput{ 3646 PublicKey: diamondPostEntry.PosterPublicKey, 3647 AmountNanos: desoToTransferNanos, 3648 }), 3649 // TxInputs and TxOutputs will be set below. 3650 // This function does not compute a signature. 3651 } 3652 3653 // Make a map for the diamond extra data and add it. 3654 diamondsExtraData := make(map[string][]byte) 3655 diamondsExtraData[DiamondLevelKey] = IntToBuf(DiamondLevel) 3656 diamondsExtraData[DiamondPostHashKey] = DiamondPostHash[:] 3657 txn.ExtraData = diamondsExtraData 3658 3659 // We don't need to make any tweaks to the amount because it's basically 3660 // a standard "pay per kilobyte" transaction. 3661 totalInput, spendAmount, changeAmount, fees, err := 3662 bc.AddInputsAndChangeToTransaction(txn, minFeeRateNanosPerKB, mempool) 3663 if err != nil { 3664 return nil, 0, 0, 0, 0, errors.Wrapf( 3665 err, "CreateBasicTransferTxnWithDiamonds: Problem adding inputs: ") 3666 } 3667 _ = spendAmount 3668 3669 // We want our transaction to have at least one input, even if it all 3670 // goes to change. This ensures that the transaction will not be "replayable." 3671 if len(txn.TxInputs) == 0 { 3672 return nil, 0, 0, 0, 0, fmt.Errorf( 3673 "CreateBasicTransferTxnWithDiamonds: CreatorCoinTransfer txn must have at" + 3674 " least one input but had zero inputs instead. Try increasing the fee rate.") 3675 } 3676 3677 return txn, totalInput, spendAmount, changeAmount, fees, nil 3678 } 3679 3680 func (bc *Blockchain) CreateMaxSpend( 3681 senderPkBytes []byte, recipientPkBytes []byte, minFeeRateNanosPerKB uint64, 3682 mempool *DeSoMempool, additionalOutputs []*DeSoOutput) ( 3683 _txn *MsgDeSoTxn, _totalInputAdded uint64, _spendAmount uint64, _fee uint64, _err error) { 3684 3685 txn := &MsgDeSoTxn{ 3686 PublicKey: senderPkBytes, 3687 TxnMeta: &BasicTransferMetadata{}, 3688 // Set a single output with the maximum possible size to ensure we don't 3689 // underestimate the fee. Note it must be a max size output because outputs 3690 // are encoded as uvarints. 3691 TxOutputs: append(additionalOutputs, &DeSoOutput{ 3692 PublicKey: recipientPkBytes, 3693 AmountNanos: math.MaxUint64, 3694 }), 3695 // TxInputs and TxOutputs will be set below. 3696 // This function does not compute a signature. 3697 } 3698 3699 // Get the spendable UtxoEntrys. 3700 spendableUtxos, err := bc.GetSpendableUtxosForPublicKey(senderPkBytes, mempool, nil) 3701 if err != nil { 3702 return nil, 0, 0, 0, errors.Wrapf(err, "CreateMaxSpend: Problem getting spendable UtxoEntrys: ") 3703 } 3704 3705 totalInput := uint64(0) 3706 for _, utxoEntry := range spendableUtxos { 3707 amountToAdd := utxoEntry.AmountNanos 3708 // For Bitcoin burns, we subtract a tiny amount of slippage to the amount we can 3709 // spend. This makes reorderings more forgiving. 3710 if utxoEntry.UtxoType == UtxoTypeBitcoinBurn { 3711 amountToAdd = uint64(float64(amountToAdd) * .999) 3712 } 3713 totalInput += amountToAdd 3714 txn.TxInputs = append(txn.TxInputs, (*DeSoInput)(utxoEntry.UtxoKey)) 3715 3716 // Avoid creating transactions that are ridiculously huge. Note this is smaller 3717 // than what AddInputsAndChangeToTransaction will allow because we want to leave 3718 // some breathing room to avoid this transaction getting rejected. 3719 currentTxnSize := _computeMaxTxSize(txn) 3720 if currentTxnSize > bc.params.MaxBlockSizeBytes/3 { 3721 if len(txn.TxInputs) > 0 { 3722 // Cut off the last input if the transaction just became too large. 3723 txn.TxInputs = txn.TxInputs[:len(txn.TxInputs)-1] 3724 } 3725 break 3726 } 3727 } 3728 3729 txnFee := _computeMaxTxFee(txn, minFeeRateNanosPerKB) 3730 3731 if totalInput < txnFee { 3732 return nil, 0, 0, 0, fmt.Errorf("CreateMaxSpend: Total input value %d would "+ 3733 "be less than the fee required to spend it %d", totalInput, txnFee) 3734 } 3735 3736 // We have multiple outputs, the last one of which pays the receiver whatever is left after subtracting off 3737 // the fee. We can just set the value of the dummy output we set up earlier. 3738 txn.TxOutputs[len(txn.TxOutputs)-1].AmountNanos = totalInput - txnFee 3739 3740 return txn, totalInput, totalInput - txnFee, txnFee, nil 3741 } 3742 3743 // AddInputsAndChangeToTransaction fetches and adds utxos to the transaction passed 3744 // in to meet the desired spend amount while also satisfying the desired minimum fee 3745 // rate. Additionally, if it's worth it, this function will add a change output 3746 // sending excess DeSo back to the spend public key. Note that the final feerate of the 3747 // transaction after calling this function may exceed the minimum feerate requested. 3748 // This can happen if the signature occupies fewer bytes than the expected maximum 3749 // number of bytes or if the change output occupies fewer bytes than the expected 3750 // maximum (though there could be other ways for this to happen). 3751 // 3752 // The transaction passed in should not have any inputs on it before calling this 3753 // function (an error is returned if it does). Additionally, the output of the 3754 // transaction passed in is assumed to be the amount the caller wishes us to find 3755 // inputs for. 3756 // 3757 // An error is returned if there is not enough input associated with this 3758 // public key to satisfy the transaction's output (subject to the minimum feerate). 3759 func (bc *Blockchain) AddInputsAndChangeToTransaction( 3760 txArg *MsgDeSoTxn, minFeeRateNanosPerKB uint64, mempool *DeSoMempool) ( 3761 _totalInputAdded uint64, _spendAmount uint64, _totalChangeAdded uint64, _fee uint64, _err error) { 3762 3763 return bc.AddInputsAndChangeToTransactionWithSubsidy(txArg, minFeeRateNanosPerKB, 0, mempool, 0) 3764 } 3765 3766 func (bc *Blockchain) AddInputsAndChangeToTransactionWithSubsidy( 3767 txArg *MsgDeSoTxn, minFeeRateNanosPerKB uint64, inputSubsidy uint64, mempool *DeSoMempool, additionalFees uint64) ( 3768 _totalInputAdded uint64, _spendAmount uint64, _totalChangeAdded uint64, _fee uint64, _err error) { 3769 3770 // The transaction we're working with should never have any inputs 3771 // set since we'll be setting the inputs here and dealing with a case where 3772 // inputs are partially set before-hand would significantly complicate this 3773 // function. So return an error if we find any inputs. 3774 if len(txArg.TxInputs) > 0 { 3775 return 0, 0, 0, 0, fmt.Errorf("_computeInputsForTxn: Transaction passed in "+ 3776 "txArg should not have any inputs set but found the found %d inputs", 3777 len(txArg.TxInputs)) 3778 } 3779 3780 // The output of the transaction is assumed to be the desired amount the 3781 // caller wants to find inputs for. Start by computing it. 3782 spendAmount := uint64(0) 3783 for _, desoOutput := range txArg.TxOutputs { 3784 spendAmount += desoOutput.AmountNanos 3785 } 3786 // If this is a CreatorCoin buy transaction, add the amount of DeSo the 3787 // user wants to spend on the buy to the amount of output we're asking this 3788 // function to provide for us. 3789 if txArg.TxnMeta.GetTxnType() == TxnTypeCreatorCoin { 3790 txMeta := txArg.TxnMeta.(*CreatorCoinMetadataa) 3791 if txMeta.OperationType == CreatorCoinOperationTypeBuy { 3792 // If this transaction is a buy then we need enough DeSo to 3793 // cover the buy. 3794 spendAmount += txMeta.DeSoToSellNanos 3795 } 3796 } 3797 3798 // Add additional fees to the spend amount. 3799 spendAmount += additionalFees 3800 // The public key of the transaction is assumed to be the one set at its 3801 // top level. 3802 spendPublicKeyBytes := txArg.PublicKey 3803 3804 // Make a copy of the transaction. This makes it so that we don't need 3805 // to modify the passed-in transaction until we're absolutely sure we don't 3806 // have an error. 3807 txCopyWithChangeOutput, err := txArg.Copy() 3808 if err != nil { 3809 return 0, 0, 0, 0, errors.Wrapf(err, "AddInputsAndChangeToTransaction: ") 3810 } 3811 // Since we generally want to compute an upper bound on the transaction 3812 // size, add a change output to the transaction to factor in the 3813 // worst-case situation in which a change output is required. This 3814 // assignment and ones like it that follow should leave the original 3815 // transaction's outputs/slices unchanged. 3816 changeOutput := &DeSoOutput{ 3817 PublicKey: make([]byte, btcec.PubKeyBytesLenCompressed), 3818 // Since we want an upper bound on the transaction size, set the amount 3819 // to the maximum value since that will induce the serializer to encode 3820 // a maximum-sized uvarint. 3821 AmountNanos: math.MaxUint64, 3822 } 3823 txCopyWithChangeOutput.TxOutputs = append(txCopyWithChangeOutput.TxOutputs, changeOutput) 3824 3825 // Get the spendable UtxoEntrys. 3826 spendableUtxos, err := bc.GetSpendableUtxosForPublicKey(spendPublicKeyBytes, mempool, nil) 3827 if err != nil { 3828 return 0, 0, 0, 0, errors.Wrapf(err, "AddInputsAndChangeToTransaction: Problem getting spendable UtxoEntrys: ") 3829 } 3830 3831 // Add input utxos to the transaction until we have enough total input to cover 3832 // the amount we want to spend plus the maximum fee (or until we've exhausted 3833 // all the utxos available). 3834 utxoEntriesBeingUsed := []*UtxoEntry{} 3835 totalInput := inputSubsidy 3836 for _, utxoEntry := range spendableUtxos { 3837 // As an optimization, don't worry about the fee until the total input has 3838 // definitively exceeded the amount we want to spend. We do this because computing 3839 // the fee each time we add an input would result in N^2 behavior. 3840 maxAmountNeeded := spendAmount 3841 if totalInput >= spendAmount { 3842 maxAmountNeeded += _computeMaxTxFee(txCopyWithChangeOutput, minFeeRateNanosPerKB) 3843 } 3844 3845 // If the amount of input we have isn't enough to cover our upper bound on 3846 // the total amount we could need, add an input and continue. 3847 if totalInput < maxAmountNeeded { 3848 txCopyWithChangeOutput.TxInputs = append(txCopyWithChangeOutput.TxInputs, (*DeSoInput)(utxoEntry.UtxoKey)) 3849 utxoEntriesBeingUsed = append(utxoEntriesBeingUsed, utxoEntry) 3850 3851 amountToAdd := utxoEntry.AmountNanos 3852 // For Bitcoin burns, we subtract a tiny amount of slippage to the amount we can 3853 // spend. This makes reorderings more forgiving. 3854 if utxoEntry.UtxoType == UtxoTypeBitcoinBurn { 3855 amountToAdd = uint64(float64(amountToAdd) * .999) 3856 } 3857 totalInput += amountToAdd 3858 continue 3859 } 3860 3861 // If we get here, we know we have enough input to cover the upper bound 3862 // estimate of our amount needed so break. 3863 break 3864 } 3865 3866 // At this point, utxoEntriesBeingUsed should contain enough to cover the 3867 // maximum amount we'd need in a worst-case scenario (or as close as we could 3868 // get to that point). Now we add these utxos to a new transaction in order 3869 // to properly compute the change we might need. 3870 3871 // Re-copy the passed-in transaction and re-add all the inputs we deemed 3872 // were necessary but this time don't add a change output unless it's strictly 3873 // necessary. 3874 finalTxCopy, _ := txArg.Copy() 3875 for _, utxoEntry := range utxoEntriesBeingUsed { 3876 finalTxCopy.TxInputs = append(finalTxCopy.TxInputs, (*DeSoInput)(utxoEntry.UtxoKey)) 3877 } 3878 maxFeeWithoutChange := _computeMaxTxFee(finalTxCopy, minFeeRateNanosPerKB) 3879 if totalInput < (spendAmount + maxFeeWithoutChange) { 3880 // In this case the total input we were able to gather for the 3881 // transaction is insufficient to cover the amount we want to 3882 // spend plus the fee. Return an error in this case so that 3883 // either the spend amount or the fee rate can be adjusted. 3884 return 0, 0, 0, 0, fmt.Errorf("AddInputsAndChangeToTransaction: Sanity check failed: Total "+ 3885 "input %d is not sufficient to "+ 3886 "cover the spend amount (=%d) plus the fee (=%d, feerate=%d, txsize=%d), "+ 3887 "total=%d", totalInput, spendAmount, maxFeeWithoutChange, minFeeRateNanosPerKB, 3888 _computeMaxTxSize(finalTxCopy), spendAmount+maxFeeWithoutChange) 3889 } 3890 3891 // Now that we know the input will cover the spend amount plus the fee, add 3892 // a change output if the value of including one definitely exceeds the cost. 3893 // 3894 // Note this is an approximation that will result in change not being included 3895 // in circumstances where the value of including it is very marginal but that 3896 // seems OK. It also will short-change the user a bit if their output is not 3897 // at the maximum size but that seems OK as well. In all of these circumstances 3898 // the user will get a slightly higher feerate than they asked for which isn't 3899 // really a problem. 3900 maxChangeFee := MaxDeSoOutputSizeBytes * minFeeRateNanosPerKB / 1000 3901 changeAmount := int64(totalInput) - int64(spendAmount) - int64(maxFeeWithoutChange) - int64(maxChangeFee) 3902 if changeAmount > 0 { 3903 finalTxCopy.TxOutputs = append(finalTxCopy.TxOutputs, &DeSoOutput{ 3904 PublicKey: spendPublicKeyBytes, 3905 AmountNanos: uint64(changeAmount), 3906 }) 3907 } else { 3908 changeAmount = 0 3909 } 3910 3911 // The final fee is what's left after subtracting the spend amount and the 3912 // change from the total input. 3913 finalFee := totalInput - spendAmount - uint64(changeAmount) 3914 3915 // If the final transaction is absolutely huge, return an error. 3916 finalTxnSize := _computeMaxTxSize(finalTxCopy) 3917 if finalTxnSize > bc.params.MaxBlockSizeBytes/2 { 3918 return 0, 0, 0, 0, fmt.Errorf("AddInputsAndChangeToTransaction: "+ 3919 "Transaction size (%d bytes) exceeds the maximum sane amount "+ 3920 "allowed (%d bytes)", finalTxnSize, bc.params.MaxBlockSizeBytes/2) 3921 } 3922 3923 // At this point, the inputs cover the (spend amount plus transaction fee) 3924 // and the change output has been added if needed, with the total fees of 3925 // the transaction set such that the feerate exceeds the minFeeRatePerKB 3926 // passed in. Set the inputs and outputs of the transaction passed in and 3927 // return. 3928 txArg.TxInputs = finalTxCopy.TxInputs 3929 txArg.TxOutputs = finalTxCopy.TxOutputs 3930 3931 return totalInput, spendAmount, uint64(changeAmount), finalFee, nil 3932 } 3933 3934 func (bc *Blockchain) EstimateDefaultFeeRateNanosPerKB( 3935 medianThreshold float64, minFeeRateNanosPerKB uint64) uint64 { 3936 3937 // Get the block at the tip of our block chain. 3938 tipNode := bc.blockTip() 3939 blk, err := GetBlock(tipNode.Hash, bc.db) 3940 if err != nil { 3941 return minFeeRateNanosPerKB 3942 } 3943 3944 // If the block is less than X% full, use the min fee rate. 3945 blockBytes, err := blk.ToBytes(false /*preSignature*/) 3946 if err != nil { 3947 return minFeeRateNanosPerKB 3948 } 3949 numBytes := len(blockBytes) 3950 if float64(numBytes)/float64(bc.params.MaxBlockSizeBytes) < medianThreshold { 3951 return minFeeRateNanosPerKB 3952 } 3953 3954 // If the block is more than X% full, use the maximum between the min 3955 // fee rate and the median fees of all the transactions in the block. 3956 utxoView, err := NewUtxoView(bc.db, bc.params, bc.postgres) 3957 if err != nil { 3958 return minFeeRateNanosPerKB 3959 } 3960 utxoOps, err := GetUtxoOperationsForBlock(bc.db, tipNode.Hash) 3961 if err != nil { 3962 return minFeeRateNanosPerKB 3963 } 3964 // Compute the hashes for all the transactions. 3965 txHashes, err := ComputeTransactionHashes(blk.Txns) 3966 if err != nil { 3967 return minFeeRateNanosPerKB 3968 } 3969 if err := utxoView.DisconnectBlock(blk, txHashes, utxoOps); err != nil { 3970 return minFeeRateNanosPerKB 3971 } 3972 3973 allFeesNanosPerKB := []uint64{} 3974 for _, txn := range blk.Txns { 3975 txnBytes, err := txn.ToBytes(false /*preSignature*/) 3976 if err != nil { 3977 return minFeeRateNanosPerKB 3978 } 3979 numBytesInTxn := len(txnBytes) 3980 _, _, _, fees, err := utxoView.ConnectTransaction( 3981 txn, txn.Hash(), int64(numBytesInTxn), tipNode.Height, false /*verifySignatures*/, false /*ignoreUtxos*/) 3982 if err != nil { 3983 return minFeeRateNanosPerKB 3984 } 3985 allFeesNanosPerKB = append( 3986 allFeesNanosPerKB, uint64(fees)*1000/uint64(numBytesInTxn)) 3987 } 3988 3989 // Sort all the fees. 3990 sort.Slice(allFeesNanosPerKB, func(ii, jj int) bool { 3991 return allFeesNanosPerKB[ii] < allFeesNanosPerKB[jj] 3992 }) 3993 3994 // Choose a fee at the middle of the range, which represents the median. 3995 medianPos := len(allFeesNanosPerKB) / 2 3996 3997 // Useful for debugging. 3998 /* 3999 for _, val := range allFeesNanosPerKB { 4000 fmt.Printf("%d ", val) 4001 } 4002 fmt.Println() 4003 */ 4004 4005 if minFeeRateNanosPerKB > allFeesNanosPerKB[medianPos] { 4006 return minFeeRateNanosPerKB 4007 } 4008 return allFeesNanosPerKB[medianPos] 4009 }