github.com/ZuluSpl0it/Sia@v1.3.7/types/block_test.go (about)

     1  package types
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/NebulousLabs/Sia/crypto"
     7  	"github.com/NebulousLabs/Sia/encoding"
     8  )
     9  
    10  // TestCalculateCoinbase probes the CalculateCoinbase function. The test code
    11  // is probably too similar to the function code to be of value.
    12  func TestCalculateCoinbase(t *testing.T) {
    13  	c := CalculateCoinbase(0)
    14  	if c.Cmp(NewCurrency64(InitialCoinbase).Mul(SiacoinPrecision)) != 0 {
    15  		t.Error("Unexpected CalculateCoinbase result")
    16  	}
    17  
    18  	c = CalculateCoinbase(1)
    19  	if c.Cmp(NewCurrency64(InitialCoinbase-1).Mul(SiacoinPrecision)) != 0 {
    20  		t.Error("Unexpected CalculateCoinbase result")
    21  	}
    22  
    23  	c = CalculateCoinbase(295000)
    24  	if c.Cmp(NewCurrency64(MinimumCoinbase).Mul(SiacoinPrecision)) != 0 {
    25  		t.Error(c)
    26  		t.Error(NewCurrency64(MinimumCoinbase).Mul(SiacoinPrecision))
    27  		t.Error("Unexpected CalculateCoinbase result")
    28  	}
    29  
    30  	c = CalculateCoinbase(1000000000)
    31  	if c.Cmp(NewCurrency64(MinimumCoinbase).Mul(SiacoinPrecision)) != 0 {
    32  		t.Error(c)
    33  		t.Error(NewCurrency64(MinimumCoinbase).Mul(SiacoinPrecision))
    34  		t.Error("Unexpected CalculateCoinbase result")
    35  	}
    36  }
    37  
    38  // TestCalculateNumSiacoins checks that the siacoin calculator is correctly
    39  // determining the number of siacoins in circulation. The check is performed by
    40  // doing a naive computation, instead of by doing the optimized computation.
    41  func TestCalculateNumSiacoins(t *testing.T) {
    42  	c := CalculateNumSiacoins(0)
    43  	if c.Cmp(CalculateCoinbase(0)) != 0 {
    44  		t.Error("unexpected circulation result for value 0, got", c)
    45  	}
    46  
    47  	if testing.Short() {
    48  		t.SkipNow()
    49  	}
    50  	totalCoins := NewCurrency64(0)
    51  	for i := BlockHeight(0); i < 500e3; i++ {
    52  		totalCoins = totalCoins.Add(CalculateCoinbase(i))
    53  		if totalCoins.Cmp(CalculateNumSiacoins(i)) != 0 {
    54  			t.Fatal("coin miscalculation", i, totalCoins, CalculateNumSiacoins(i))
    55  		}
    56  	}
    57  }
    58  
    59  // TestBlockHeader checks that BlockHeader returns the correct value, and that
    60  // the hash is consistent with the old method for obtaining the hash.
    61  func TestBlockHeader(t *testing.T) {
    62  	var b Block
    63  	b.ParentID[1] = 1
    64  	b.Nonce[2] = 2
    65  	b.Timestamp = 3
    66  	b.MinerPayouts = []SiacoinOutput{{Value: NewCurrency64(4)}}
    67  	b.Transactions = []Transaction{{ArbitraryData: [][]byte{{'5'}}}}
    68  
    69  	id1 := b.ID()
    70  	id2 := BlockID(crypto.HashBytes(encoding.Marshal(b.Header())))
    71  	id3 := BlockID(crypto.HashAll(
    72  		b.ParentID,
    73  		b.Nonce,
    74  		b.Timestamp,
    75  		b.MerkleRoot(),
    76  	))
    77  
    78  	if id1 != id2 || id2 != id3 || id3 != id1 {
    79  		t.Error("Methods for getting block id don't return the same results")
    80  	}
    81  }
    82  
    83  // TestBlockID probes the ID function of the block type.
    84  func TestBlockID(t *testing.T) {
    85  	// Create a bunch of different blocks and check that all of them have
    86  	// unique ids.
    87  	var b Block
    88  	var ids []BlockID
    89  
    90  	ids = append(ids, b.ID())
    91  	b.ParentID[0] = 1
    92  	ids = append(ids, b.ID())
    93  	b.Nonce[0] = 45
    94  	ids = append(ids, b.ID())
    95  	b.Timestamp = CurrentTimestamp()
    96  	ids = append(ids, b.ID())
    97  	b.MinerPayouts = append(b.MinerPayouts, SiacoinOutput{Value: CalculateCoinbase(0)})
    98  	ids = append(ids, b.ID())
    99  	b.MinerPayouts = append(b.MinerPayouts, SiacoinOutput{Value: CalculateCoinbase(0)})
   100  	ids = append(ids, b.ID())
   101  	b.Transactions = append(b.Transactions, Transaction{MinerFees: []Currency{CalculateCoinbase(1)}})
   102  	ids = append(ids, b.ID())
   103  	b.Transactions = append(b.Transactions, Transaction{MinerFees: []Currency{CalculateCoinbase(1)}})
   104  	ids = append(ids, b.ID())
   105  
   106  	knownIDs := make(map[BlockID]struct{})
   107  	for i, id := range ids {
   108  		_, exists := knownIDs[id]
   109  		if exists {
   110  			t.Error("id repeat for index", i)
   111  		}
   112  		knownIDs[id] = struct{}{}
   113  	}
   114  }
   115  
   116  // TestHeaderID probes the ID function of the BlockHeader type.
   117  func TestHeaderID(t *testing.T) {
   118  	// Create a bunch of different blocks and check that all of them have
   119  	// unique ids.
   120  	var blocks []Block
   121  	var b Block
   122  
   123  	blocks = append(blocks, b)
   124  	b.ParentID[0] = 1
   125  	blocks = append(blocks, b)
   126  	b.Nonce[0] = 45
   127  	blocks = append(blocks, b)
   128  	b.Timestamp = CurrentTimestamp()
   129  	blocks = append(blocks, b)
   130  	b.MinerPayouts = append(b.MinerPayouts, SiacoinOutput{Value: CalculateCoinbase(0)})
   131  	blocks = append(blocks, b)
   132  	b.MinerPayouts = append(b.MinerPayouts, SiacoinOutput{Value: CalculateCoinbase(0)})
   133  	blocks = append(blocks, b)
   134  	b.Transactions = append(b.Transactions, Transaction{MinerFees: []Currency{CalculateCoinbase(1)}})
   135  	blocks = append(blocks, b)
   136  	b.Transactions = append(b.Transactions, Transaction{MinerFees: []Currency{CalculateCoinbase(1)}})
   137  	blocks = append(blocks, b)
   138  
   139  	knownIDs := make(map[BlockID]struct{})
   140  	for i, block := range blocks {
   141  		blockID := block.ID()
   142  		headerID := block.Header().ID()
   143  		if blockID != headerID {
   144  			t.Error("headerID does not match blockID for index", i)
   145  		}
   146  		_, exists := knownIDs[headerID]
   147  		if exists {
   148  			t.Error("id repeat for index", i)
   149  		}
   150  		knownIDs[headerID] = struct{}{}
   151  	}
   152  }
   153  
   154  // TestBlockCalculateSubsidy probes the CalculateSubsidy function of the block
   155  // type.
   156  func TestBlockCalculateSubsidy(t *testing.T) {
   157  	// All tests are done at height = 0.
   158  	coinbase := CalculateCoinbase(0)
   159  
   160  	// Calculate the subsidy on a block with 0 fees at height 0. Result should
   161  	// be 300,000.
   162  	var b Block
   163  	if b.CalculateSubsidy(0).Cmp(coinbase) != 0 {
   164  		t.Error("subsidy is miscalculated for an empty block")
   165  	}
   166  
   167  	// Calculate when there is a fee in a transcation.
   168  	expected := coinbase.Add(NewCurrency64(123))
   169  	txn := Transaction{
   170  		MinerFees: []Currency{NewCurrency64(123)},
   171  	}
   172  	b.Transactions = append(b.Transactions, txn)
   173  	if b.CalculateSubsidy(0).Cmp(expected) != 0 {
   174  		t.Error("subsidy is miscalculated for a block with a single transaction")
   175  	}
   176  
   177  	// Add a single no-fee transaction and check again.
   178  	txn = Transaction{
   179  		ArbitraryData: [][]byte{{'6'}},
   180  	}
   181  	b.Transactions = append(b.Transactions, txn)
   182  	if b.CalculateSubsidy(0).Cmp(expected) != 0 {
   183  		t.Error("subsidy is miscalculated with empty transactions.")
   184  	}
   185  
   186  	// Add a transaction with multiple fees.
   187  	expected = expected.Add(NewCurrency64(1 + 2 + 3))
   188  	txn = Transaction{
   189  		MinerFees: []Currency{
   190  			NewCurrency64(1),
   191  			NewCurrency64(2),
   192  			NewCurrency64(3),
   193  		},
   194  	}
   195  	b.Transactions = append(b.Transactions, txn)
   196  	if b.CalculateSubsidy(0).Cmp(expected) != 0 {
   197  		t.Error("subsidy is miscalculated for a block with a single transaction")
   198  	}
   199  
   200  	// Add an empty transaction to the beginning.
   201  	txn = Transaction{
   202  		ArbitraryData: [][]byte{{'7'}},
   203  	}
   204  	b.Transactions = append([]Transaction{txn}, b.Transactions...)
   205  	if b.CalculateSubsidy(0).Cmp(expected) != 0 {
   206  		t.Error("subsidy is miscalculated with empty transactions.")
   207  	}
   208  }
   209  
   210  // TestBlockMinerPayoutID probes the MinerPayout function of the block type.
   211  func TestBlockMinerPayoutID(t *testing.T) {
   212  	// Create a block with 2 miner payouts, and check that each payout has a
   213  	// different id, and that the id is dependent on the block id.
   214  	var ids []SiacoinOutputID
   215  	b := Block{
   216  		MinerPayouts: []SiacoinOutput{
   217  			{Value: CalculateCoinbase(0)},
   218  			{Value: CalculateCoinbase(0)},
   219  		},
   220  	}
   221  	ids = append(ids, b.MinerPayoutID(1), b.MinerPayoutID(2))
   222  	b.ParentID[0] = 1
   223  	ids = append(ids, b.MinerPayoutID(1), b.MinerPayoutID(2))
   224  
   225  	knownIDs := make(map[SiacoinOutputID]struct{})
   226  	for i, id := range ids {
   227  		_, exists := knownIDs[id]
   228  		if exists {
   229  			t.Error("id repeat for index", i)
   230  		}
   231  		knownIDs[id] = struct{}{}
   232  	}
   233  }