gitlab.com/SiaPrime/SiaPrime@v1.4.1/types/block.go (about)

     1  package types
     2  
     3  // block.go defines the Block type for Sia, and provides some helper functions
     4  // for working with blocks.
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/hex"
     9  	"hash"
    10  	"unsafe"
    11  
    12  	"gitlab.com/SiaPrime/SiaPrime/build"
    13  	"gitlab.com/SiaPrime/SiaPrime/crypto"
    14  	"gitlab.com/SiaPrime/SiaPrime/encoding"
    15  )
    16  
    17  const (
    18  	// BlockHeaderSize is the size, in bytes, of a block header.
    19  	// 32 (ParentID) + 8 (Nonce) + 8 (Timestamp) + 32 (MerkleRoot)
    20  	BlockHeaderSize = 80
    21  )
    22  
    23  type (
    24  	// A Block is a summary of changes to the state that have occurred since the
    25  	// previous block. Blocks reference the ID of the previous block (their
    26  	// "parent"), creating the linked-list commonly known as the blockchain. Their
    27  	// primary function is to bundle together transactions on the network. Blocks
    28  	// are created by "miners," who collect transactions from other nodes, and
    29  	// then try to pick a Nonce that results in a block whose BlockID is below a
    30  	// given Target.
    31  	Block struct {
    32  		ParentID     BlockID         `json:"parentid"`
    33  		Nonce        BlockNonce      `json:"nonce"`
    34  		Timestamp    Timestamp       `json:"timestamp"`
    35  		MinerPayouts []SiacoinOutput `json:"minerpayouts"`
    36  		Transactions []Transaction   `json:"transactions"`
    37  	}
    38  
    39  	// A BlockHeader contains the data that, when hashed, produces the Block's ID.
    40  	BlockHeader struct {
    41  		ParentID   BlockID     `json:"parentid"`
    42  		Nonce      BlockNonce  `json:"nonce"`
    43  		Timestamp  Timestamp   `json:"timestamp"`
    44  		MerkleRoot crypto.Hash `json:"merkleroot"`
    45  	}
    46  
    47  	// BlockHeight is the number of blocks that exist after the genesis block.
    48  	BlockHeight uint64
    49  	// A BlockID is the hash of a BlockHeader. A BlockID uniquely
    50  	// identifies a Block, and indicates the amount of work performed
    51  	// to mine that Block. The more leading zeros in the BlockID, the
    52  	// more work was performed.
    53  	BlockID crypto.Hash
    54  	// The BlockNonce is a "scratch space" that miners can freely alter to produce
    55  	// a BlockID that satisfies a given Target.
    56  	BlockNonce [8]byte
    57  )
    58  
    59  // CalculateDevSubsidy takes a block and a height and determines the block
    60  // subsidies for the dev fund.
    61  func CalculateDevSubsidy(height BlockHeight) Currency {
    62  	coinbase := CalculateCoinbase(height)
    63  
    64  	devSubsidy := NewCurrency64(0)
    65  	if DevFundEnabled && (height >= DevFundInitialBlockHeight) {
    66  		devFundDecayPercentage := uint64(100)
    67  		if height >= DevFundDecayEndBlockHeight {
    68  			devFundDecayPercentage = uint64(0)
    69  		} else if height >= DevFundDecayStartBlockHeight {
    70  			devFundDecayStartBlockHeight := uint64(DevFundDecayStartBlockHeight)
    71  			devFundDecayEndBlockHeight := uint64(DevFundDecayEndBlockHeight)
    72  			devFundDecayPercentage = uint64(100) - (uint64(height)-devFundDecayStartBlockHeight)*uint64(100)/(devFundDecayEndBlockHeight-devFundDecayStartBlockHeight)
    73  		}
    74  
    75  		devFundPercentageRange := DevFundInitialPercentage - DevFundFinalPercentage
    76  		devFundPercentage := DevFundFinalPercentage*uint64(100) + devFundPercentageRange*devFundDecayPercentage
    77  
    78  		devSubsidy = coinbase.Mul(NewCurrency64(devFundPercentage)).Div(NewCurrency64(10000))
    79  	}
    80  
    81  	return devSubsidy
    82  }
    83  
    84  // CalculateCoinbase calculates the coinbase for a given height. The coinbase
    85  // equation is:
    86  //
    87  //     coinbase := max(InitialCoinbase - height, MinimumCoinbase) * SiacoinPrecision
    88  func CalculateCoinbase(height BlockHeight) Currency {
    89  	base := InitialCoinbase - uint64(height)
    90  	if uint64(height) > InitialCoinbase || base < MinimumCoinbase {
    91  		base = MinimumCoinbase
    92  	}
    93  	return NewCurrency64(base).Mul(SiacoinPrecision)
    94  }
    95  
    96  // CalculateNumSiacoins calculates the number of siacoins in circulation at a
    97  // given height.
    98  func CalculateNumSiacoins(height BlockHeight) Currency {
    99  	airdropCoins := AirdropCommunityValue.Add(AirdropPoolValue).Add(AirdropNebulousLabsValue).Add(AirdropSiaPrimeValue)
   100  
   101  	deflationBlocks := BlockHeight(InitialCoinbase - MinimumCoinbase)
   102  	avgDeflationSiacoins := CalculateCoinbase(0).Add(CalculateCoinbase(height)).Div(NewCurrency64(2))
   103  	if height <= deflationBlocks {
   104  		deflationSiacoins := avgDeflationSiacoins.Mul(NewCurrency64(uint64(height + 1)))
   105  		return airdropCoins.Add(deflationSiacoins)
   106  	}
   107  	deflationSiacoins := avgDeflationSiacoins.Mul(NewCurrency64(uint64(deflationBlocks + 1)))
   108  	trailingSiacoins := NewCurrency64(uint64(height - deflationBlocks)).Mul(CalculateCoinbase(height))
   109  	return airdropCoins.Add(deflationSiacoins).Add(trailingSiacoins)
   110  }
   111  
   112  var numGenesisSiacoins = func() Currency {
   113  	// Sum all the values for the genesis siacoin outputs.
   114  	numGenesisSiacoins := NewCurrency64(0)
   115  	for _, transaction := range GenesisBlock.Transactions {
   116  		for _, siacoinOutput := range transaction.SiacoinOutputs {
   117  			numGenesisSiacoins = numGenesisSiacoins.Add(siacoinOutput.Value)
   118  		}
   119  	}
   120  	return numGenesisSiacoins
   121  }()
   122  
   123  // ID returns the ID of a Block, which is calculated by hashing the header.
   124  func (h BlockHeader) ID() BlockID {
   125  	return BlockID(crypto.HashObject(h))
   126  }
   127  
   128  // CalculateMinerFees calculates the sum of a block's miner transaction fees
   129  func (b Block) CalculateMinerFees() Currency {
   130  	fees := NewCurrency64(0)
   131  	for _, txn := range b.Transactions {
   132  		for _, fee := range txn.MinerFees {
   133  			fees = fees.Add(fee)
   134  		}
   135  	}
   136  	return fees
   137  }
   138  
   139  // CalculateSubsidy takes a block and a height and determines the block
   140  // subsidy.
   141  func (b Block) CalculateSubsidy(height BlockHeight) Currency {
   142  	subsidy := CalculateCoinbase(height)
   143  	for _, txn := range b.Transactions {
   144  		for _, fee := range txn.MinerFees {
   145  			subsidy = subsidy.Add(fee)
   146  		}
   147  	}
   148  	return subsidy
   149  }
   150  
   151  // CalculateSubsidies takes a block and a height and determines the block
   152  // subsidies for miners and the dev fund.
   153  func (b Block) CalculateSubsidies(height BlockHeight) (Currency, Currency) {
   154  	coinbase := CalculateCoinbase(height)
   155  	devSubsidy := CalculateDevSubsidy(height)
   156  	minerSubsidy := coinbase.Sub(devSubsidy).Add(b.CalculateMinerFees())
   157  	return minerSubsidy, devSubsidy
   158  }
   159  
   160  // Header returns the header of a block.
   161  func (b Block) Header() BlockHeader {
   162  	return BlockHeader{
   163  		ParentID:   b.ParentID,
   164  		Nonce:      b.Nonce,
   165  		Timestamp:  b.Timestamp,
   166  		MerkleRoot: b.MerkleRoot(),
   167  	}
   168  }
   169  
   170  // ID returns the ID of a Block, which is calculated by hashing the
   171  // concatenation of the block's parent's ID, nonce, and the result of the
   172  // b.MerkleRoot(). It is equivalent to calling block.Header().ID()
   173  func (b Block) ID() BlockID {
   174  	return b.Header().ID()
   175  }
   176  
   177  // MerkleTree return the MerkleTree of the block
   178  func (b Block) MerkleTree() *crypto.MerkleTree {
   179  	tree := crypto.NewTree()
   180  	var buf bytes.Buffer
   181  	e := encoding.NewEncoder(&buf)
   182  	for _, payout := range b.MinerPayouts {
   183  		payout.MarshalSia(e)
   184  		tree.Push(buf.Bytes())
   185  		buf.Reset()
   186  	}
   187  	for _, txn := range b.Transactions {
   188  		txn.MarshalSia(e)
   189  		tree.Push(buf.Bytes())
   190  		buf.Reset()
   191  	}
   192  
   193  	// Sanity check - verify that this root is the same as the root provided in
   194  	// the old implementation.
   195  	if build.DEBUG {
   196  		verifyTree := crypto.NewTree()
   197  		for _, payout := range b.MinerPayouts {
   198  			verifyTree.PushObject(payout)
   199  		}
   200  		for _, txn := range b.Transactions {
   201  			verifyTree.PushObject(txn)
   202  		}
   203  		if tree.Root() != verifyTree.Root() {
   204  			panic("Block MerkleRoot implementation is broken")
   205  		}
   206  	}
   207  	return tree
   208  }
   209  
   210  // MerkleRoot calculates the Merkle root of a Block. The leaves of the Merkle
   211  // tree are composed of the miner outputs (one leaf per payout), and the
   212  // transactions (one leaf per transaction).
   213  func (b Block) MerkleRoot() crypto.Hash {
   214  	return b.MerkleTree().Root()
   215  }
   216  
   217  // MinerPayoutID returns the ID of the miner payout at the given index, which
   218  // is calculated by hashing the concatenation of the BlockID and the payout
   219  // index.
   220  func (b Block) MinerPayoutID(i uint64) SiacoinOutputID {
   221  	return SiacoinOutputID(crypto.HashAll(
   222  		b.ID(),
   223  		i,
   224  	))
   225  }
   226  
   227  // MerkleBranches returns the merkle branches of a block, as used in stratum
   228  // mining.
   229  func (b Block) MerkleBranches() []string {
   230  	mbranch := crypto.NewTree()
   231  	var buf bytes.Buffer
   232  	for _, payout := range b.MinerPayouts {
   233  		payout.MarshalSia(&buf)
   234  		mbranch.Push(buf.Bytes())
   235  		buf.Reset()
   236  	}
   237  
   238  	for _, txn := range b.Transactions {
   239  		txn.MarshalSia(&buf)
   240  		mbranch.Push(buf.Bytes())
   241  		buf.Reset()
   242  	}
   243  	//
   244  	// This whole approach needs to be revisited.  I basically am cheating to look
   245  	// inside the merkle tree struct to determine if the head is a leaf or not
   246  	//
   247  	type SubTree struct {
   248  		next   *SubTree
   249  		height int // Int is okay because a height over 300 is physically unachievable.
   250  		sum    []byte
   251  	}
   252  
   253  	type Tree struct {
   254  		head         *SubTree
   255  		hash         hash.Hash
   256  		currentIndex uint64
   257  		proofIndex   uint64
   258  		proofSet     [][]byte
   259  		cachedTree   bool
   260  	}
   261  	tr := *(*Tree)(unsafe.Pointer(mbranch))
   262  
   263  	var merkle []string
   264  	//	h.log.Debugf("mBranch Hash %s\n", mbranch.Root().String())
   265  	for st := tr.head; st != nil; st = st.next {
   266  		//		h.log.Debugf("Height %d Hash %x\n", st.height, st.sum)
   267  		merkle = append(merkle, hex.EncodeToString(st.sum))
   268  	}
   269  	return merkle
   270  }