Skip to content

Commit

Permalink
Merge pull request #517 from SiaFoundation/nate/revenue-tests
Browse files Browse the repository at this point in the history
refactor(contracts,sqlite): unify revenue logic, enable revenue tests
  • Loading branch information
n8maninger authored Dec 4, 2024
2 parents a010a9c + b530bbc commit 1809129
Show file tree
Hide file tree
Showing 8 changed files with 556 additions and 582 deletions.
42 changes: 16 additions & 26 deletions host/contracts/integrity_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
//go:build ignore

package contracts_test

import (
Expand All @@ -10,11 +8,11 @@ import (
"os"
"path/filepath"
"testing"
"time"

rhp2 "go.sia.tech/core/rhp/v2"
"go.sia.tech/core/types"
"go.sia.tech/hostd/host/contracts"
"go.sia.tech/hostd/internal/testutil"
"go.uber.org/zap/zaptest"
"lukechampine.com/frand"
)
Expand Down Expand Up @@ -67,47 +65,39 @@ func TestIntegrityResultJSON(t *testing.T) {
}

func TestCheckIntegrity(t *testing.T) {
hostKey, renterKey := types.NewPrivateKeyFromSeed(frand.Bytes(32)), types.NewPrivateKeyFromSeed(frand.Bytes(32))

dir := t.TempDir()
log := zaptest.NewLogger(t)
db, cm, _, wm, c, s := testNode(t, hostKey, log)
hostKey, renterKey := types.NewPrivateKeyFromSeed(frand.Bytes(32)), types.NewPrivateKeyFromSeed(frand.Bytes(32))
n, genesis := testutil.V1Network()
host := testutil.NewHostNode(t, hostKey, n, genesis, log)

volumePath := filepath.Join(t.TempDir(), "data.dat")
result := make(chan error, 1)
if _, err := s.AddVolume(context.Background(), filepath.Join(dir, "data.dat"), 10, result); err != nil {
if _, err := host.Volumes.AddVolume(context.Background(), volumePath, 10, result); err != nil {
t.Fatal(err)
} else if err := <-result; err != nil {
t.Fatal(err)
}

// mine enough for the wallet to have some funds
mineAndSync(t, cm, db, wm.Address(), cm.Tip().Network.MaturityDelay+5)
testutil.MineAndSync(t, host, host.Wallet.Address(), int(n.MaturityDelay+5))

rev, err := formContract(renterKey, hostKey, 50, 60, types.Siacoins(500), types.Siacoins(1000), c, node, node.ChainManager(), node.TPool())
if err != nil {
t.Fatal(err)
}

contract, err := c.Contract(rev.Revision.ParentID)
rev := formContract(t, host.Chain, host.Contracts, host.Wallet, host.Syncer, host.Settings, renterKey, hostKey, types.Siacoins(500), types.Siacoins(1000), 10, true)
contract, err := host.Contracts.Contract(rev.Revision.ParentID)
if err != nil {
t.Fatal(err)
} else if contract.Status != contracts.ContractStatusPending {
t.Fatal("expected contract to be pending")
}
testutil.MineAndSync(t, host, types.VoidAddress, 1)

if err := node.MineBlocks(types.VoidAddress, 1); err != nil {
t.Fatal(err)
}
time.Sleep(100 * time.Millisecond) // sync time

contract, err = c.Contract(rev.Revision.ParentID)
contract, err = host.Contracts.Contract(rev.Revision.ParentID)
if err != nil {
t.Fatal(err)
} else if contract.Status != contracts.ContractStatusActive {
t.Fatal("expected contract to be active")
}

updater, err := c.ReviseContract(rev.Revision.ParentID)
updater, err := host.Contracts.ReviseContract(rev.Revision.ParentID)
if err != nil {
t.Fatal(err)
}
Expand All @@ -119,7 +109,7 @@ func TestCheckIntegrity(t *testing.T) {
var sector [rhp2.SectorSize]byte
frand.Read(sector[:256])
root := rhp2.SectorRoot(&sector)
release, err := s.Write(root, &sector)
release, err := host.Volumes.Write(root, &sector)
if err != nil {
t.Fatal(err)
}
Expand All @@ -144,7 +134,7 @@ func TestCheckIntegrity(t *testing.T) {

// helper func to serialize integrity check
checkIntegrity := func() (issues, checked, sectors uint64, err error) {
results, sectors, err := c.CheckIntegrity(context.Background(), rev.Revision.ParentID)
results, sectors, err := host.Contracts.CheckIntegrity(context.Background(), rev.Revision.ParentID)
if err != nil {
return 0, 0, 0, fmt.Errorf("failed to check integrity: %w", err)
}
Expand All @@ -171,7 +161,7 @@ func TestCheckIntegrity(t *testing.T) {
}

// delete a sector
if err := s.RemoveSector(roots[3]); err != nil {
if err := host.Volumes.RemoveSector(roots[3]); err != nil {
t.Fatal(err)
}

Expand All @@ -188,7 +178,7 @@ func TestCheckIntegrity(t *testing.T) {
}

// open the data file and corrupt the first sector
f, err := os.OpenFile(filepath.Join(dir, "data.dat"), os.O_RDWR, 0)
f, err := os.OpenFile(volumePath, os.O_RDWR, 0)
if err != nil {
t.Fatal(err)
}
Expand Down
25 changes: 16 additions & 9 deletions host/contracts/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"go.sia.tech/coreutils/syncer"
"go.sia.tech/coreutils/wallet"
"go.sia.tech/hostd/host/contracts"
"go.sia.tech/hostd/host/settings"
"go.sia.tech/hostd/host/storage"
"go.sia.tech/hostd/internal/testutil"
"go.sia.tech/hostd/persist/sqlite"
Expand Down Expand Up @@ -87,12 +88,16 @@ func formV2Contract(t *testing.T, cm *chain.Manager, c *contracts.Manager, w *wa
return txn.V2FileContractID(txn.ID(), 0), fc
}

func formContract(t *testing.T, cm *chain.Manager, c *contracts.Manager, w *wallet.SingleAddressWallet, s *syncer.Syncer, renterKey, hostKey types.PrivateKey, renterFunds, hostFunds types.Currency, duration uint64, broadcast bool) contracts.SignedRevision {
func formContract(t *testing.T, cm *chain.Manager, c *contracts.Manager, w *wallet.SingleAddressWallet, s *syncer.Syncer, sm *settings.ConfigManager, renterKey, hostKey types.PrivateKey, renterFunds, hostFunds types.Currency, duration uint64, broadcast bool) contracts.SignedRevision {
t.Helper()

contract := rhp2.PrepareContractFormation(renterKey.PublicKey(), hostKey.PublicKey(), renterFunds, hostFunds, cm.Tip().Height+duration, rhp2.HostSettings{WindowSize: 10}, w.Address())
settings, err := sm.RHP2Settings()
if err != nil {
t.Fatalf("failed to get rhp2 settings: %v", err)
}
contract := rhp2.PrepareContractFormation(renterKey.PublicKey(), hostKey.PublicKey(), renterFunds, hostFunds, cm.Tip().Height+duration, settings, w.Address())
state := cm.TipState()
formationCost := rhp2.ContractFormationCost(state, contract, types.ZeroCurrency)
formationCost := rhp2.ContractFormationCost(state, contract, settings.ContractPrice)
contractUnlockConditions := types.UnlockConditions{
PublicKeys: []types.UnlockKey{
renterKey.PublicKey().UnlockKey(),
Expand Down Expand Up @@ -128,7 +133,9 @@ func formContract(t *testing.T, cm *chain.Manager, c *contracts.Manager, w *wall
HostSignature: hostKey.SignHash(sigHash),
RenterSignature: renterKey.SignHash(sigHash),
}
if err := c.AddContract(rev, formationSet, hostFunds, contracts.Usage{}); err != nil {
if err := c.AddContract(rev, formationSet, hostFunds, contracts.Usage{
RPCRevenue: settings.ContractPrice,
}); err != nil {
t.Fatal(err)
}
return rev
Expand Down Expand Up @@ -293,7 +300,7 @@ func TestContractLifecycle(t *testing.T) {
node := testutil.NewHostNode(t, hostKey, network, genesis, log)
testutil.MineAndSync(t, node, node.Wallet.Address(), int(network.MaturityDelay+5))

rev := formContract(t, node.Chain, node.Contracts, node.Wallet, node.Syncer, renterKey, hostKey, types.Siacoins(10), types.Siacoins(20), 10, false)
rev := formContract(t, node.Chain, node.Contracts, node.Wallet, node.Syncer, node.Settings, renterKey, hostKey, types.Siacoins(10), types.Siacoins(20), 10, false)
assertContractStatus(t, node.Contracts, rev.Revision.ParentID, contracts.ContractStatusPending)
assertContractMetrics(t, node.Store, 0, 0, types.ZeroCurrency, types.ZeroCurrency)

Expand Down Expand Up @@ -333,7 +340,7 @@ func TestContractLifecycle(t *testing.T) {

renterFunds := types.Siacoins(500)
hostCollateral := types.Siacoins(1000)
rev := formContract(t, node.Chain, node.Contracts, node.Wallet, node.Syncer, renterKey, hostKey, renterFunds, hostCollateral, 10, true)
rev := formContract(t, node.Chain, node.Contracts, node.Wallet, node.Syncer, node.Settings, renterKey, hostKey, renterFunds, hostCollateral, 10, true)

assertContractStatus(t, node.Contracts, rev.Revision.ParentID, contracts.ContractStatusPending)
// pending contracts do not contribute to metrics
Expand Down Expand Up @@ -445,7 +452,7 @@ func TestContractLifecycle(t *testing.T) {

renterFunds := types.Siacoins(500)
hostCollateral := types.Siacoins(1000)
rev := formContract(t, node.Chain, node.Contracts, node.Wallet, node.Syncer, renterKey, hostKey, renterFunds, hostCollateral, 10, true)
rev := formContract(t, node.Chain, node.Contracts, node.Wallet, node.Syncer, node.Settings, renterKey, hostKey, renterFunds, hostCollateral, 10, true)

assertContractStatus(t, node.Contracts, rev.Revision.ParentID, contracts.ContractStatusPending)
assertContractMetrics(t, node.Store, 0, 0, types.ZeroCurrency, types.ZeroCurrency)
Expand Down Expand Up @@ -539,7 +546,7 @@ func TestContractLifecycle(t *testing.T) {

renterFunds := types.Siacoins(500)
hostCollateral := types.Siacoins(1000)
rev := formContract(t, node.Chain, node.Contracts, node.Wallet, node.Syncer, renterKey, hostKey, renterFunds, hostCollateral, 10, true)
rev := formContract(t, node.Chain, node.Contracts, node.Wallet, node.Syncer, node.Settings, renterKey, hostKey, renterFunds, hostCollateral, 10, true)

assertContractStatus(t, node.Contracts, rev.Revision.ParentID, contracts.ContractStatusPending)
assertContractMetrics(t, node.Store, 0, 0, types.ZeroCurrency, types.ZeroCurrency)
Expand Down Expand Up @@ -618,7 +625,7 @@ func TestContractLifecycle(t *testing.T) {

renterFunds := types.Siacoins(500)
hostCollateral := types.Siacoins(1000)
rev := formContract(t, node.Chain, node.Contracts, node.Wallet, node.Syncer, renterKey, hostKey, renterFunds, hostCollateral, 10, true)
rev := formContract(t, node.Chain, node.Contracts, node.Wallet, node.Syncer, node.Settings, renterKey, hostKey, renterFunds, hostCollateral, 10, true)

assertContractStatus(t, node.Contracts, rev.Revision.ParentID, contracts.ContractStatusPending)
assertContractMetrics(t, node.Store, 0, 0, types.ZeroCurrency, types.ZeroCurrency)
Expand Down
Loading

0 comments on commit 1809129

Please sign in to comment.