github.com/Synthesix/Sia@v1.3.3-0.20180413141344-f863baeed3ca/modules/explorer/info_test.go (about)

     1  package explorer
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/Synthesix/Sia/crypto"
     7  	"github.com/Synthesix/Sia/types"
     8  	"github.com/NebulousLabs/fastrand"
     9  )
    10  
    11  // TestImmediateBlockFacts grabs the block facts object from the block explorer
    12  // at the current height and verifies that the data has been filled out.
    13  func TestImmediateBlockFacts(t *testing.T) {
    14  	if testing.Short() {
    15  		t.SkipNow()
    16  	}
    17  	et, err := createExplorerTester(t.Name())
    18  	if err != nil {
    19  		t.Fatal(err)
    20  	}
    21  
    22  	facts := et.explorer.LatestBlockFacts()
    23  	var explorerHeight types.BlockHeight
    24  	err = et.explorer.db.View(dbGetInternal(internalBlockHeight, &explorerHeight))
    25  	if err != nil {
    26  		t.Fatal(err)
    27  	}
    28  	if facts.Height != explorerHeight || explorerHeight == 0 {
    29  		t.Error("wrong height reported in facts object")
    30  	}
    31  	if !facts.TotalCoins.Equals(types.CalculateNumSiacoins(et.cs.Height())) {
    32  		t.Error("wrong number of total coins:", facts.TotalCoins, et.cs.Height())
    33  	}
    34  }
    35  
    36  // TestBlock probes the Block function of the explorer.
    37  func TestBlock(t *testing.T) {
    38  	if testing.Short() {
    39  		t.SkipNow()
    40  	}
    41  	et, err := createExplorerTester(t.Name())
    42  	if err != nil {
    43  		t.Fatal(err)
    44  	}
    45  
    46  	gb := types.GenesisBlock
    47  	gbFetch, height, exists := et.explorer.Block(gb.ID())
    48  	if !exists || height != 0 || gbFetch.ID() != gb.ID() {
    49  		t.Error("call to 'Block' inside explorer failed")
    50  	}
    51  }
    52  
    53  // TestBlockFacts checks that the correct block facts are returned for a query.
    54  func TestBlockFacts(t *testing.T) {
    55  	if testing.Short() {
    56  		t.SkipNow()
    57  	}
    58  	et, err := createExplorerTester(t.Name())
    59  	if err != nil {
    60  		t.Fatal(err)
    61  	}
    62  
    63  	gb := types.GenesisBlock
    64  	bf, exists := et.explorer.BlockFacts(0)
    65  	if !exists || bf.BlockID != gb.ID() || bf.Height != 0 {
    66  		t.Error("call to 'BlockFacts' inside explorer failed")
    67  		t.Error("Expecting true ->", exists)
    68  		t.Error("Expecting", gb.ID(), "->", bf.BlockID)
    69  		t.Error("Expecting 0 ->", bf.Height)
    70  	}
    71  
    72  	bf, exists = et.explorer.BlockFacts(1)
    73  	if !exists || bf.Height != 1 {
    74  		t.Error("call to 'BlockFacts' has failed")
    75  	}
    76  }
    77  
    78  // TestFileContractPayouts checks that file contract outputs are tracked by the explorer
    79  func TestFileContractPayoutsMissingProof(t *testing.T) {
    80  	if testing.Short() {
    81  		t.SkipNow()
    82  	}
    83  
    84  	et, err := createExplorerTester(t.Name())
    85  	if err != nil {
    86  		t.Fatal(err)
    87  	}
    88  
    89  	// Create and fund valid file contracts.
    90  	builder := et.wallet.StartTransaction()
    91  	payout := types.NewCurrency64(1e9)
    92  	err = builder.FundSiacoins(payout)
    93  	if err != nil {
    94  		t.Fatal(err)
    95  	}
    96  
    97  	windowStart := et.cs.Height() + 2
    98  	windowEnd := et.cs.Height() + 5
    99  
   100  	fc := types.FileContract{
   101  		WindowStart:        windowStart,
   102  		WindowEnd:          windowEnd,
   103  		Payout:             payout,
   104  		ValidProofOutputs:  []types.SiacoinOutput{{Value: types.PostTax(et.cs.Height(), payout)}},
   105  		MissedProofOutputs: []types.SiacoinOutput{{Value: types.PostTax(et.cs.Height(), payout)}},
   106  		UnlockHash:         types.UnlockConditions{}.UnlockHash(),
   107  	}
   108  
   109  	fcIndex := builder.AddFileContract(fc)
   110  	tSet, err := builder.Sign(true)
   111  	if err != nil {
   112  		t.Fatal(err)
   113  	}
   114  
   115  	if err != nil {
   116  		t.Fatal(err)
   117  	}
   118  
   119  	err = et.tpool.AcceptTransactionSet(tSet)
   120  	if err != nil {
   121  		t.Fatal(err)
   122  	}
   123  
   124  	// Mine until contract payout is in consensus
   125  	for i := et.cs.Height(); i < windowEnd+types.MaturityDelay; i++ {
   126  		_, err := et.miner.AddBlock()
   127  		if err != nil {
   128  			t.Fatal(err)
   129  		}
   130  	}
   131  
   132  	ti := len(tSet) - 1
   133  	fcid := tSet[ti].FileContractID(fcIndex)
   134  	txns := et.explorer.FileContractID(fcid)
   135  	if len(txns) == 0 {
   136  		t.Error("Filecontract ID does not appear in blockchain")
   137  	}
   138  
   139  	outputs, err := et.explorer.FileContractPayouts(fcid)
   140  	if err != nil {
   141  		t.Fatal(err)
   142  	}
   143  
   144  	// Check if MissedProofOutputs were added to spendable outputs
   145  	if len(outputs) != len(fc.MissedProofOutputs) {
   146  		t.Error("Incorrect number of outputs returned")
   147  		t.Error("Expecting -> ", len(fc.MissedProofOutputs))
   148  		t.Error("But was -> ", len(outputs))
   149  	}
   150  }
   151  
   152  func TestFileContractsPayoutValidProof(t *testing.T) {
   153  	if testing.Short() {
   154  		t.SkipNow()
   155  	}
   156  
   157  	et, err := createExplorerTester(t.Name())
   158  	if err != nil {
   159  		t.Fatal(err)
   160  	}
   161  
   162  	// COMPATv0.4.0 - Step the block height up past the hardfork amount. This
   163  	// code stops nondeterministic failures when producing storage proofs that
   164  	// is related to buggy old code.
   165  	for et.cs.Height() <= 10 {
   166  		_, err := et.miner.AddBlock()
   167  		if err != nil {
   168  			t.Fatal(err)
   169  		}
   170  	}
   171  
   172  	// Create a file (as a bytes.Buffer) that will be used for the file
   173  	// contract.
   174  	filesize := uint64(4e3)
   175  	file := fastrand.Bytes(int(filesize))
   176  	merkleRoot := crypto.MerkleRoot(file)
   177  
   178  	// Create a funded file contract
   179  	payout := types.NewCurrency64(400e6)
   180  	fc := types.FileContract{
   181  		FileSize:           filesize,
   182  		FileMerkleRoot:     merkleRoot,
   183  		WindowStart:        et.cs.Height() + 1,
   184  		WindowEnd:          et.cs.Height() + 2,
   185  		Payout:             payout,
   186  		ValidProofOutputs:  []types.SiacoinOutput{{Value: types.PostTax(et.cs.Height(), payout)}},
   187  		MissedProofOutputs: []types.SiacoinOutput{{Value: types.PostTax(et.cs.Height(), payout)}},
   188  	}
   189  
   190  	// Submit a transaction with the file contract.
   191  	//oldSiafundPool := cst.cs.dbGetSiafundPool()
   192  	builder := et.wallet.StartTransaction()
   193  	err = builder.FundSiacoins(payout)
   194  	if err != nil {
   195  		t.Fatal(err)
   196  	}
   197  
   198  	fcIndex := builder.AddFileContract(fc)
   199  	tSet, err := builder.Sign(true)
   200  	if err != nil {
   201  		t.Fatal(err)
   202  	}
   203  
   204  	err = et.tpool.AcceptTransactionSet(tSet)
   205  	if err != nil {
   206  		t.Fatal(err)
   207  	}
   208  	_, err = et.miner.AddBlock()
   209  	if err != nil {
   210  		t.Fatal(err)
   211  	}
   212  
   213  	ti := len(tSet) - 1
   214  	fcid := tSet[ti].FileContractID(fcIndex)
   215  
   216  	// Create and submit a storage proof for the file contract.
   217  	segmentIndex, err := et.cs.StorageProofSegment(fcid)
   218  	if err != nil {
   219  		t.Fatal(err)
   220  	}
   221  	segment, hashSet := crypto.MerkleProof(file, segmentIndex)
   222  	sp := types.StorageProof{
   223  		ParentID: fcid,
   224  		HashSet:  hashSet,
   225  	}
   226  	copy(sp.Segment[:], segment)
   227  	builder = et.wallet.StartTransaction()
   228  	builder.AddStorageProof(sp)
   229  	tSet, err = builder.Sign(true)
   230  	if err != nil {
   231  		t.Fatal(err)
   232  	}
   233  	err = et.tpool.AcceptTransactionSet(tSet)
   234  	if err != nil {
   235  		t.Fatal(err)
   236  	}
   237  
   238  	// Mine until contract payout is in consensus
   239  	for i := types.BlockHeight(0); i < types.MaturityDelay+1; i++ {
   240  		_, err := et.miner.AddBlock()
   241  		if err != nil {
   242  			t.Fatal(err)
   243  		}
   244  	}
   245  
   246  	txns := et.explorer.FileContractID(fcid)
   247  	if len(txns) == 0 {
   248  		t.Error("Filecontract ID does not appear in blockchain")
   249  	}
   250  
   251  	// Check that the storageproof was added to the explorer after
   252  	// the filecontract was removed from the consensus set
   253  	outputs, err := et.explorer.FileContractPayouts(fcid)
   254  	if err != nil {
   255  		t.Fatal(err)
   256  	}
   257  
   258  	if len(outputs) != len(fc.ValidProofOutputs) {
   259  		t.Errorf("expected %v, got %v ", fc.MissedProofOutputs, outputs)
   260  	}
   261  }