Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(test): fix v2 related NDFs in test suite #1758

Merged
merged 9 commits into from
Dec 19, 2024
11 changes: 8 additions & 3 deletions autopilot/contractor/contractor.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ func (c *Contractor) formContract(ctx *mCtx, hs HostScanner, host api.Host, minI
}

// shouldn't go below the minimum immediately so we add some buffer
minCollateral := MinCollateral.Mul64(2)
minCollateral := MinCollateral.Mul64(2).Add(contractPrice)
if hostCollateral.Cmp(minCollateral) < 0 {
hostCollateral = minCollateral
}
Expand Down Expand Up @@ -255,14 +255,17 @@ func (c *Contractor) refreshContract(ctx *mCtx, contract contract, host api.Host
}

var expectedNewStorage uint64
var contractPrice types.Currency
if host.IsV2() {
contractPrice = host.V2Settings.Prices.ContractPrice
expectedNewStorage = renterFundsToExpectedStorageV2(renterFunds, contract.EndHeight()-cs.BlockHeight, host.V2Settings.Prices)
} else {
contractPrice = host.PriceTable.ContractPrice
expectedNewStorage = renterFundsToExpectedStorage(renterFunds, contract.EndHeight()-cs.BlockHeight, pt)
}

// a refresh should always result in a contract that has enough collateral
minNewCollateral := MinCollateral.Mul64(2)
minNewCollateral := MinCollateral.Mul64(2).Add(contractPrice)

// renew the contract
renewal, err := c.bus.RenewContract(ctx, contract.ID, contract.EndHeight(), renterFunds, minNewCollateral, expectedNewStorage)
Expand Down Expand Up @@ -1041,7 +1044,9 @@ func performHostChecks(ctx *mCtx, bus Bus, logger *zap.SugaredLogger) error {
return fmt.Errorf("failed to fetch consensus state: %w", err)
}
for _, h := range scoredHosts {
h.host.PriceTable.HostBlockHeight = cs.BlockHeight // ignore HostBlockHeight
// ignore HostBlockHeight
h.host.PriceTable.HostBlockHeight = cs.BlockHeight
h.host.V2Settings.Prices.TipHeight = cs.BlockHeight
hc := checkHost(ctx.GougingChecker(cs), h, minScore, ctx.Period())
if err := bus.UpdateHostCheck(ctx, h.host.PublicKey, *hc); err != nil {
return fmt.Errorf("failed to update host check for host %v: %w", h.host.PublicKey, err)
Expand Down
4 changes: 3 additions & 1 deletion autopilot/contractor/evaluate.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ func EvaluateConfig(cfg api.AutopilotConfig, cs api.ConsensusState, rs api.Redun

resp.Hosts = uint64(len(hosts))
for i, host := range hosts {
hosts[i].PriceTable.HostBlockHeight = cs.BlockHeight // ignore block height
// ignore block height
hosts[i].PriceTable.HostBlockHeight = cs.BlockHeight
hosts[i].V2Settings.Prices.TipHeight = cs.BlockHeight
hc := checkHost(gc, scoreHost(host, cfg, gs, rs.Redundancy()), minValidScore, cfg.Contracts.Period)
if hc.UsabilityBreakdown.IsUsable() {
resp.Usable++
Expand Down
4 changes: 3 additions & 1 deletion internal/accounts/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,9 @@ func (a *Manager) refillAccounts() {

// fetch all usable hosts
hosts, err := a.hs.UsableHosts(a.shutdownCtx)
if err != nil {
if utils.IsErr(err, context.Canceled) {
return
} else if err != nil {
a.logger.Errorw(fmt.Sprintf("failed to fetch usable hosts for refill: %v", err))
return
}
Expand Down
64 changes: 34 additions & 30 deletions internal/bus/chainsubscriber.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,38 +415,42 @@ func (s *chainSubscriber) broadcastExpiredFileContractResolutions(tx sql.ChainUp
s.logger.Errorf("failed to get expired file contract elements: %v", err)
return
}

for _, fce := range expiredFCEs {
txn := types.V2Transaction{
MinerFee: s.cm.RecommendedFee().Mul64(ContractResolutionTxnWeight),
FileContractResolutions: []types.V2FileContractResolution{
{
Parent: fce,
Resolution: &types.V2FileContractExpiration{},
go func(fce types.V2FileContractElement) {
txn := types.V2Transaction{
MinerFee: s.cm.RecommendedFee().Mul64(ContractResolutionTxnWeight),
FileContractResolutions: []types.V2FileContractResolution{
{
Parent: fce,
Resolution: &types.V2FileContractExpiration{},
},
},
},
}
// fund and sign txn
basis, toSign, err := s.wallet.FundV2Transaction(&txn, txn.MinerFee, true)
if err != nil {
s.logger.Errorf("failed to fund contract expiration txn: %v", err)
continue
}
s.wallet.SignV2Inputs(&txn, toSign)

// verify txn and broadcast it
_, err = s.cm.AddV2PoolTransactions(basis, []types.V2Transaction{txn})
if err != nil &&
(strings.Contains(err.Error(), "has already been resolved") ||
strings.Contains(err.Error(), "not present in the accumulator")) {
s.wallet.ReleaseInputs(nil, []types.V2Transaction{txn})
s.logger.With(zap.Error(err)).Debug("failed to broadcast contract expiration txn")
continue
} else if err != nil {
s.logger.With(zap.Error(err)).Error("failed to broadcast contract expiration txn")
s.wallet.ReleaseInputs(nil, []types.V2Transaction{txn})
continue
}
s.s.BroadcastV2TransactionSet(basis, []types.V2Transaction{txn})
}

// fund and sign txn
basis, toSign, err := s.wallet.FundV2Transaction(&txn, txn.MinerFee, true)
if err != nil {
s.logger.Errorf("failed to fund contract expiration txn: %v", err)
return
}
s.wallet.SignV2Inputs(&txn, toSign)

// verify txn and broadcast it
_, err = s.cm.AddV2PoolTransactions(basis, []types.V2Transaction{txn})
if err != nil &&
(strings.Contains(err.Error(), "has already been resolved") ||
ChrisSchinnerl marked this conversation as resolved.
Show resolved Hide resolved
strings.Contains(err.Error(), "not present in the accumulator")) {
s.wallet.ReleaseInputs(nil, []types.V2Transaction{txn})
s.logger.With(zap.Error(err)).Debug("failed to broadcast contract expiration txn")
return
} else if err != nil {
s.logger.With(zap.Error(err)).Error("failed to broadcast contract expiration txn")
s.wallet.ReleaseInputs(nil, []types.V2Transaction{txn})
return
}
s.s.BroadcastV2TransactionSet(basis, []types.V2Transaction{txn})
}(fce)
}
}

Expand Down
2 changes: 1 addition & 1 deletion internal/test/e2e/build_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ package e2e
// configuration for post-v2-hardfork tests
const (
HardforkV2AllowHeight = 2
HardforkV2RequireHeight = 30000 // TODO: change this to 3 once all the code is updated to use v2 above the allow height
HardforkV2RequireHeight = 3
)
4 changes: 3 additions & 1 deletion internal/test/e2e/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,13 +335,15 @@ func newTestCluster(t *testing.T, opts testClusterOptions) *TestCluster {
})))

cm := opts.cm
network, genesis := testNetwork()
if cm == nil {
// create chain manager
network, genesis := testNetwork()
store, state, err := chain.NewDBStore(chain.NewMemDB(), network, genesis)
tt.OK(err)
cm = chain.NewManager(store, state)
}
network := cm.TipState().Network
genesis := types.Block{Timestamp: network.HardforkOak.GenesisTimestamp}

// Create bus.
busDir := filepath.Join(dir, "bus")
Expand Down
4 changes: 2 additions & 2 deletions internal/test/e2e/cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2932,7 +2932,7 @@ func TestV1ToV2Transition(t *testing.T) {
apCfg := test.AutopilotConfig
apCfg.Contracts.Amount = 2
apCfg.Contracts.Period = 1000 // make sure we handle trying to form contracts with a proof height after the v2 require height
apCfg.Contracts.RenewWindow = 50
apCfg.Contracts.RenewWindow = 1

// create a test cluster
nHosts := 3
Expand All @@ -2949,7 +2949,7 @@ func TestV1ToV2Transition(t *testing.T) {
cluster.AddHosts(nHosts)

// make sure we are still before the v2 allow height
if cm.Tip().Height >= network.HardforkV2.AllowHeight {
if cluster.IsPassedV2AllowHeight() {
t.Fatal("should be before the v2 allow height")
}

Expand Down
70 changes: 1 addition & 69 deletions internal/test/e2e/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"net"
"os"
"path/filepath"
"sync"
"time"

"go.sia.tech/core/consensus"
Expand Down Expand Up @@ -37,73 +36,6 @@ const (
blocksPerMonth = blocksPerDay * 30
)

type ephemeralPeerStore struct {
peers map[string]syncer.PeerInfo
bans map[string]time.Time
mu sync.Mutex
}

func (eps *ephemeralPeerStore) AddPeer(addr string) error {
eps.mu.Lock()
defer eps.mu.Unlock()
eps.peers[addr] = syncer.PeerInfo{Address: addr}
return nil
}

func (eps *ephemeralPeerStore) Peers() ([]syncer.PeerInfo, error) {
eps.mu.Lock()
defer eps.mu.Unlock()
var peers []syncer.PeerInfo
for _, peer := range eps.peers {
peers = append(peers, peer)
}
return peers, nil
}

func (eps *ephemeralPeerStore) PeerInfo(addr string) (syncer.PeerInfo, error) {
eps.mu.Lock()
defer eps.mu.Unlock()
peer, ok := eps.peers[addr]
if !ok {
return syncer.PeerInfo{}, syncer.ErrPeerNotFound
}
return peer, nil
}

func (eps *ephemeralPeerStore) UpdatePeerInfo(addr string, fn func(*syncer.PeerInfo)) error {
eps.mu.Lock()
defer eps.mu.Unlock()
peer, ok := eps.peers[addr]
if !ok {
return syncer.ErrPeerNotFound
}
fn(&peer)
eps.peers[addr] = peer
return nil
}

func (eps *ephemeralPeerStore) Ban(addr string, duration time.Duration, reason string) error {
eps.mu.Lock()
defer eps.mu.Unlock()
eps.bans[addr] = time.Now().Add(duration)
return nil
}

// Banned returns true, nil if the peer is banned.
func (eps *ephemeralPeerStore) Banned(addr string) (bool, error) {
eps.mu.Lock()
defer eps.mu.Unlock()
t, ok := eps.bans[addr]
return ok && time.Now().Before(t), nil
}

func newEphemeralPeerStore() syncer.PeerStore {
return &ephemeralPeerStore{
peers: make(map[string]syncer.PeerInfo),
bans: make(map[string]time.Time),
}
}

// A Host is an ephemeral host that can be used for testing.
type Host struct {
dir string
Expand Down Expand Up @@ -235,7 +167,7 @@ func NewHost(privKey types.PrivateKey, cm *chain.Manager, dir string, network *c
if err != nil {
return nil, fmt.Errorf("failed to create syncer listener: %w", err)
}
s := syncer.New(l, cm, newEphemeralPeerStore(), gateway.Header{
s := syncer.New(l, cm, testutil.NewEphemeralPeerStore(), gateway.Header{
GenesisID: genesisBlock.ID(),
UniqueID: gateway.GenerateUniqueID(),
NetAddress: l.Addr().String(),
Expand Down
Loading