Skip to content

Commit 83ba3e0

Browse files
committed
rhp4: fix missing signatures, add regression checks
1 parent 2bcb90e commit 83ba3e0

File tree

4 files changed

+64
-11
lines changed

4 files changed

+64
-11
lines changed

rhp/v4/rpc.go

+1
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ func RPCAppendSectors(ctx context.Context, t TransportClient, cs consensus.State
418418
} else if !contract.Revision.HostPublicKey.VerifyHash(sigHash, hostSignature.HostSignature) {
419419
return RPCAppendSectorsResult{}, rhp4.ErrInvalidSignature
420420
}
421+
revision.HostSignature = hostSignature.HostSignature
421422
return RPCAppendSectorsResult{
422423
Revision: revision,
423424
Usage: usage,

rhp/v4/rpc_test.go

+24
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,27 @@ func TestAppendSectors(t *testing.T) {
865865
}
866866
revision := formResult.Contract
867867

868+
assertLastRevision := func(t *testing.T) {
869+
t.Helper()
870+
871+
lastRev, err := rhp4.RPCLatestRevision(context.Background(), transport, revision.ID)
872+
if err != nil {
873+
t.Fatal(err)
874+
} else if !reflect.DeepEqual(lastRev, revision.Revision) {
875+
t.Log(lastRev)
876+
t.Log(revision.Revision)
877+
t.Fatalf("expected last revision to match")
878+
}
879+
880+
sigHash := cm.TipState().ContractSigHash(revision.Revision)
881+
if !renterKey.PublicKey().VerifyHash(sigHash, lastRev.RenterSignature) {
882+
t.Fatal("renter signature invalid")
883+
} else if !hostKey.PublicKey().VerifyHash(sigHash, lastRev.HostSignature) {
884+
t.Fatal("host signature invalid")
885+
}
886+
}
887+
assertLastRevision(t)
888+
868889
cs := cm.TipState()
869890
account := proto4.Account(renterKey.PublicKey())
870891

@@ -876,6 +897,7 @@ func TestAppendSectors(t *testing.T) {
876897
t.Fatal(err)
877898
}
878899
revision.Revision = fundResult.Revision
900+
assertLastRevision(t)
879901

880902
token := proto4.AccountToken{
881903
Account: account,
@@ -915,6 +937,8 @@ func TestAppendSectors(t *testing.T) {
915937
if appendResult.Revision.FileMerkleRoot != proto4.MetaRoot(roots) {
916938
t.Fatal("root mismatch")
917939
}
940+
revision.Revision = appendResult.Revision
941+
assertLastRevision(t)
918942

919943
// read the sectors back
920944
buf := bytes.NewBuffer(make([]byte, 0, proto4.SectorSize))

rhp/v4/server.go

+2-11
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,6 @@ import (
1717
"lukechampine.com/frand"
1818
)
1919

20-
const (
21-
sectorsPerTiB = (1 << 40) / (1 << 22)
22-
memoryPer1TiB = sectorsPerTiB * 32
23-
24-
sectorsPer10TiB = 10 * sectorsPerTiB
25-
memoryPer10TiB = sectorsPer10TiB * 32
26-
27-
sectorsPer100TiB = 100 * sectorsPerTiB
28-
memoryPer100TiB = sectorsPer100TiB * 32
29-
)
30-
3120
var protocolVersion = [3]byte{4, 0, 0}
3221

3322
type (
@@ -435,6 +424,7 @@ func (s *Server) handleRPCFundAccounts(stream net.Conn) error {
435424
if !revision.RenterPublicKey.VerifyHash(sigHash, req.RenterSignature) {
436425
return rhp4.ErrInvalidSignature
437426
}
427+
revision.RenterSignature = req.RenterSignature
438428
revision.HostSignature = s.hostKey.SignHash(sigHash)
439429

440430
balances, err := s.contractor.CreditAccountsWithContract(req.Deposits, req.ContractID, revision, usage)
@@ -498,6 +488,7 @@ func (s *Server) handleRPCSectorRoots(stream net.Conn) error {
498488

499489
// sign the revision
500490
revision.HostSignature = s.hostKey.SignHash(sigHash)
491+
revision.RenterSignature = req.RenterSignature
501492

502493
// update the contract
503494
err = s.contractor.ReviseV2Contract(req.ContractID, revision, state.Roots, usage)

testutil/host.go

+37
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"sync"
88
"testing"
99

10+
"go.sia.tech/core/consensus"
1011
proto4 "go.sia.tech/core/rhp/v4"
1112
"go.sia.tech/core/types"
1213
"go.sia.tech/coreutils/chain"
@@ -119,6 +120,13 @@ func (ec *EphemeralContractor) AddV2Contract(formationSet rhp4.TransactionSet, _
119120
}
120121
fc := formationTxn.FileContracts[0]
121122

123+
sigHash := consensus.State{}.ContractSigHash(fc)
124+
if !fc.RenterPublicKey.VerifyHash(sigHash, fc.RenterSignature) {
125+
return errors.New("invalid renter signature")
126+
} else if !fc.HostPublicKey.VerifyHash(sigHash, fc.HostSignature) {
127+
return errors.New("invalid host signature")
128+
}
129+
122130
contractID := formationTxn.V2FileContractID(formationTxn.ID(), 0)
123131
if _, ok := ec.contracts[contractID]; ok {
124132
return errors.New("contract already exists")
@@ -160,6 +168,13 @@ func (ec *EphemeralContractor) RenewV2Contract(renewalSet rhp4.TransactionSet, _
160168
return errors.New("contract already exists")
161169
}
162170

171+
sigHash := consensus.State{}.ContractSigHash(renewal.NewContract)
172+
if !existing.RenterPublicKey.VerifyHash(sigHash, renewal.NewContract.RenterSignature) {
173+
return errors.New("invalid renter signature")
174+
} else if !existing.HostPublicKey.VerifyHash(sigHash, renewal.NewContract.HostSignature) {
175+
return errors.New("invalid host signature")
176+
}
177+
163178
delete(ec.contracts, existingID) // remove the existing contract
164179
ec.contracts[contractID] = renewal.NewContract
165180
ec.roots[contractID] = append([]types.Hash256(nil), ec.roots[existingID]...)
@@ -179,6 +194,13 @@ func (ec *EphemeralContractor) ReviseV2Contract(contractID types.FileContractID,
179194
return errors.New("revision number must be greater than existing")
180195
}
181196

197+
sigHash := consensus.State{}.ContractSigHash(revision)
198+
if !existing.RenterPublicKey.VerifyHash(sigHash, revision.RenterSignature) {
199+
return errors.New("invalid renter signature")
200+
} else if !existing.HostPublicKey.VerifyHash(sigHash, revision.HostSignature) {
201+
return errors.New("invalid host signature")
202+
}
203+
182204
ec.contracts[contractID] = revision
183205
ec.roots[contractID] = append([]types.Hash256(nil), roots...)
184206
return nil
@@ -202,11 +224,26 @@ func (ec *EphemeralContractor) CreditAccountsWithContract(deposits []proto4.Acco
202224
ec.mu.Lock()
203225
defer ec.mu.Unlock()
204226

227+
existing, ok := ec.contracts[contractID]
228+
if !ok {
229+
return nil, errors.New("contract not found")
230+
} else if revision.RevisionNumber <= existing.RevisionNumber {
231+
return nil, errors.New("revision number must be greater than existing")
232+
}
233+
234+
sigHash := consensus.State{}.ContractSigHash(revision)
235+
if !existing.RenterPublicKey.VerifyHash(sigHash, revision.RenterSignature) {
236+
return nil, errors.New("invalid renter signature")
237+
} else if !existing.HostPublicKey.VerifyHash(sigHash, revision.HostSignature) {
238+
return nil, errors.New("invalid host signature")
239+
}
240+
205241
var balance = make([]types.Currency, 0, len(deposits))
206242
for _, deposit := range deposits {
207243
ec.accounts[deposit.Account] = ec.accounts[deposit.Account].Add(deposit.Amount)
208244
balance = append(balance, ec.accounts[deposit.Account])
209245
}
246+
210247
ec.contracts[contractID] = revision
211248
return balance, nil
212249
}

0 commit comments

Comments
 (0)