gitlab.com/SiaPrime/SiaPrime@v1.4.1/modules/explorer/info_test.go (about)

     1  package explorer
     2  
     3  import (
     4  	"testing"
     5  
     6  	"gitlab.com/NebulousLabs/fastrand"
     7  	"gitlab.com/SiaPrime/SiaPrime/crypto"
     8  	"gitlab.com/SiaPrime/SiaPrime/types"
     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, err := et.wallet.StartTransaction()
    91  	if err != nil {
    92  		t.Fatal(err)
    93  	}
    94  	payout := types.NewCurrency64(1e9)
    95  	err = builder.FundSiacoins(payout)
    96  	if err != nil {
    97  		t.Fatal(err)
    98  	}
    99  
   100  	windowStart := et.cs.Height() + 2
   101  	windowEnd := et.cs.Height() + 5
   102  
   103  	fc := types.FileContract{
   104  		WindowStart:        windowStart,
   105  		WindowEnd:          windowEnd,
   106  		Payout:             payout,
   107  		ValidProofOutputs:  []types.SiacoinOutput{{Value: types.PostTax(et.cs.Height(), payout)}},
   108  		MissedProofOutputs: []types.SiacoinOutput{{Value: types.PostTax(et.cs.Height(), payout)}},
   109  		UnlockHash:         types.UnlockConditions{}.UnlockHash(),
   110  	}
   111  
   112  	fcIndex := builder.AddFileContract(fc)
   113  	tSet, err := builder.Sign(true)
   114  	if err != nil {
   115  		t.Fatal(err)
   116  	}
   117  
   118  	if err != nil {
   119  		t.Fatal(err)
   120  	}
   121  
   122  	err = et.tpool.AcceptTransactionSet(tSet)
   123  	if err != nil {
   124  		t.Fatal(err)
   125  	}
   126  
   127  	// Mine until contract payout is in consensus
   128  	for i := et.cs.Height(); i < windowEnd+types.MaturityDelay; i++ {
   129  		_, err := et.miner.AddBlock()
   130  		if err != nil {
   131  			t.Fatal(err)
   132  		}
   133  	}
   134  
   135  	ti := len(tSet) - 1
   136  	fcid := tSet[ti].FileContractID(fcIndex)
   137  	txns := et.explorer.FileContractID(fcid)
   138  	if len(txns) == 0 {
   139  		t.Error("Filecontract ID does not appear in blockchain")
   140  	}
   141  
   142  	outputs, err := et.explorer.FileContractPayouts(fcid)
   143  	if err != nil {
   144  		t.Fatal(err)
   145  	}
   146  
   147  	// Check if MissedProofOutputs were added to spendable outputs
   148  	if len(outputs) != len(fc.MissedProofOutputs) {
   149  		t.Error("Incorrect number of outputs returned")
   150  		t.Error("Expecting -> ", len(fc.MissedProofOutputs))
   151  		t.Error("But was -> ", len(outputs))
   152  	}
   153  }
   154  
   155  func TestFileContractsPayoutValidProof(t *testing.T) {
   156  	if testing.Short() {
   157  		t.SkipNow()
   158  	}
   159  
   160  	et, err := createExplorerTester(t.Name())
   161  	if err != nil {
   162  		t.Fatal(err)
   163  	}
   164  
   165  	// COMPATv0.4.0 - Step the block height up past the hardfork amount. This
   166  	// code stops nondeterministic failures when producing storage proofs that
   167  	// is related to buggy old code.
   168  	for et.cs.Height() <= 10 {
   169  		_, err := et.miner.AddBlock()
   170  		if err != nil {
   171  			t.Fatal(err)
   172  		}
   173  	}
   174  
   175  	// Create a file (as a bytes.Buffer) that will be used for the file
   176  	// contract.
   177  	filesize := uint64(4e3)
   178  	file := fastrand.Bytes(int(filesize))
   179  	merkleRoot := crypto.MerkleRoot(file)
   180  
   181  	// Create a funded file contract
   182  	payout := types.NewCurrency64(400e6)
   183  	fc := types.FileContract{
   184  		FileSize:           filesize,
   185  		FileMerkleRoot:     merkleRoot,
   186  		WindowStart:        et.cs.Height() + 1,
   187  		WindowEnd:          et.cs.Height() + 2,
   188  		Payout:             payout,
   189  		ValidProofOutputs:  []types.SiacoinOutput{{Value: types.PostTax(et.cs.Height(), payout)}},
   190  		MissedProofOutputs: []types.SiacoinOutput{{Value: types.PostTax(et.cs.Height(), payout)}},
   191  	}
   192  
   193  	// Submit a transaction with the file contract.
   194  	//oldSiafundPool := cst.cs.dbGetSiafundPool()
   195  	builder, err := et.wallet.StartTransaction()
   196  	if err != nil {
   197  		t.Fatal(err)
   198  	}
   199  	err = builder.FundSiacoins(payout)
   200  	if err != nil {
   201  		t.Fatal(err)
   202  	}
   203  
   204  	fcIndex := builder.AddFileContract(fc)
   205  	tSet, err := builder.Sign(true)
   206  	if err != nil {
   207  		t.Fatal(err)
   208  	}
   209  
   210  	err = et.tpool.AcceptTransactionSet(tSet)
   211  	if err != nil {
   212  		t.Fatal(err)
   213  	}
   214  	_, err = et.miner.AddBlock()
   215  	if err != nil {
   216  		t.Fatal(err)
   217  	}
   218  
   219  	ti := len(tSet) - 1
   220  	fcid := tSet[ti].FileContractID(fcIndex)
   221  
   222  	// Create and submit a storage proof for the file contract.
   223  	segmentIndex, err := et.cs.StorageProofSegment(fcid)
   224  	if err != nil {
   225  		t.Fatal(err)
   226  	}
   227  	segment, hashSet := crypto.MerkleProof(file, segmentIndex)
   228  	sp := types.StorageProof{
   229  		ParentID: fcid,
   230  		HashSet:  hashSet,
   231  	}
   232  	copy(sp.Segment[:], segment)
   233  	builder, err = et.wallet.StartTransaction()
   234  	if err != nil {
   235  		t.Fatal(err)
   236  	}
   237  	builder.AddStorageProof(sp)
   238  	tSet, err = builder.Sign(true)
   239  	if err != nil {
   240  		t.Fatal(err)
   241  	}
   242  	err = et.tpool.AcceptTransactionSet(tSet)
   243  	if err != nil {
   244  		t.Fatal(err)
   245  	}
   246  
   247  	// Mine until contract payout is in consensus
   248  	for i := types.BlockHeight(0); i < types.MaturityDelay+1; i++ {
   249  		_, err := et.miner.AddBlock()
   250  		if err != nil {
   251  			t.Fatal(err)
   252  		}
   253  	}
   254  
   255  	txns := et.explorer.FileContractID(fcid)
   256  	if len(txns) == 0 {
   257  		t.Error("Filecontract ID does not appear in blockchain")
   258  	}
   259  
   260  	// Check that the storageproof was added to the explorer after
   261  	// the filecontract was removed from the consensus set
   262  	outputs, err := et.explorer.FileContractPayouts(fcid)
   263  	if err != nil {
   264  		t.Fatal(err)
   265  	}
   266  
   267  	if len(outputs) != len(fc.ValidProofOutputs) {
   268  		t.Errorf("expected %v, got %v ", fc.MissedProofOutputs, outputs)
   269  	}
   270  }