Skip to content

Commit

Permalink
rhp4: add rpc replenish types
Browse files Browse the repository at this point in the history
  • Loading branch information
n8maninger committed Feb 14, 2025
1 parent 261f960 commit c51a0f7
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 10 deletions.
7 changes: 7 additions & 0 deletions .changeset/add_rpcreplenish_to_rhp4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
default: minor
---

# Add RPCReplenish to RHP4

Adds an RPC to RHP4 that enables renters to set a target balance instead of first fetching the current balance and then funding the account with the difference. This is primarily to speed up account funding and reduce round trips when managing a large number of accounts.
46 changes: 46 additions & 0 deletions rhp/v4/encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,52 @@ func (r *RPCAccountBalanceResponse) maxLen() int {
return sizeofCurrency
}

func (r *RPCReplenishAccountsRequest) encodeTo(e *types.Encoder) {
types.EncodeSlice(e, r.Accounts)
types.V2Currency(r.Target).EncodeTo(e)
r.ContractID.EncodeTo(e)
r.ChallengeSignature.EncodeTo(e)
}
func (r *RPCReplenishAccountsRequest) decodeFrom(d *types.Decoder) {
types.DecodeSlice(d, &r.Accounts)
(*types.V2Currency)(&r.Target).DecodeFrom(d)
r.ContractID.DecodeFrom(d)
r.ChallengeSignature.DecodeFrom(d)
}
func (r *RPCReplenishAccountsRequest) maxLen() int {
return reasonableObjectSize
}

func (r *RPCReplenishAccountsResponse) encodeTo(e *types.Encoder) {
types.V2Currency(r.Cost).EncodeTo(e)
}
func (r *RPCReplenishAccountsResponse) decodeFrom(d *types.Decoder) {
(*types.V2Currency)(&r.Cost).DecodeFrom(d)
}
func (r *RPCReplenishAccountsResponse) maxLen() int {
return sizeofCurrency
}

func (r *RPCReplenishAccountsSecondResponse) encodeTo(e *types.Encoder) {
r.RenterSignature.EncodeTo(e)
}
func (r *RPCReplenishAccountsSecondResponse) decodeFrom(d *types.Decoder) {
r.RenterSignature.DecodeFrom(d)
}
func (r *RPCReplenishAccountsSecondResponse) maxLen() int {
return sizeofSignature
}

func (r *RPCReplenishAccountsThirdResponse) encodeTo(e *types.Encoder) {
r.HostSignature.EncodeTo(e)
}
func (r *RPCReplenishAccountsThirdResponse) decodeFrom(d *types.Decoder) {
r.HostSignature.DecodeFrom(d)
}
func (r *RPCReplenishAccountsThirdResponse) maxLen() int {
return sizeofSignature
}

func (r *RPCFundAccountsRequest) encodeTo(e *types.Encoder) {
r.ContractID.EncodeTo(e)
types.EncodeSlice(e, r.Deposits)
Expand Down
63 changes: 53 additions & 10 deletions rhp/v4/rhp.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,23 @@ const (

// RPC identifiers.
var (
RPCAccountBalanceID = types.NewSpecifier("AccountBalance")
RPCAccountBalanceID = types.NewSpecifier("AccountBalance")
RPCFundAccountsID = types.NewSpecifier("FundAccounts")
RPCReplenishAccountsID = types.NewSpecifier("ReplAccounts")

RPCAppendSectorsID = types.NewSpecifier("AppendSectors")
RPCFreeSectorsID = types.NewSpecifier("FreeSectors")
RPCSectorRootsID = types.NewSpecifier("SectorRoots")

RPCFormContractID = types.NewSpecifier("FormContract")
RPCFundAccountsID = types.NewSpecifier("FundAccounts")
RPCLatestRevisionID = types.NewSpecifier("LatestRevision")
RPCAppendSectorsID = types.NewSpecifier("AppendSectors")
RPCFreeSectorsID = types.NewSpecifier("FreeSectors")
RPCReadSectorID = types.NewSpecifier("ReadSector")
RPCRenewContractID = types.NewSpecifier("RenewContract")
RPCRefreshContractID = types.NewSpecifier("RefreshContract")
RPCSectorRootsID = types.NewSpecifier("SectorRoots")
RPCSettingsID = types.NewSpecifier("Settings")
RPCWriteSectorID = types.NewSpecifier("WriteSector")
RPCVerifySectorID = types.NewSpecifier("VerifySector")
RPCRenewContractID = types.NewSpecifier("RenewContract")

RPCReadSectorID = types.NewSpecifier("ReadSector")
RPCWriteSectorID = types.NewSpecifier("WriteSector")
RPCVerifySectorID = types.NewSpecifier("VerifySector")
RPCSettingsID = types.NewSpecifier("Settings")
)

func round4KiB(n uint64) uint64 {
Expand Down Expand Up @@ -458,6 +462,22 @@ type (
Balance types.Currency `json:"balance"`
}

RPCReplenishAccountsRequest struct {

Check failure on line 465 in rhp/v4/rhp.go

View workflow job for this annotation

GitHub Actions / test / test (1.22, ubuntu-latest)

exported: exported type RPCReplenishAccountsRequest should have comment or be unexported (revive)

Check failure on line 465 in rhp/v4/rhp.go

View workflow job for this annotation

GitHub Actions / test / test (1.23, ubuntu-latest)

exported: exported type RPCReplenishAccountsRequest should have comment or be unexported (revive)

Check failure on line 465 in rhp/v4/rhp.go

View workflow job for this annotation

GitHub Actions / test / test (1.23, macos-latest)

exported: exported type RPCReplenishAccountsRequest should have comment or be unexported (revive)
Accounts []Account `json:"accounts"`
Target types.Currency `json:"target"`
ContractID types.FileContractID `json:"contractID"`
ChallengeSignature types.Signature `json:"challengeSignature"`
}
RPCReplenishAccountsResponse struct {

Check failure on line 471 in rhp/v4/rhp.go

View workflow job for this annotation

GitHub Actions / test / test (1.22, ubuntu-latest)

exported: exported type RPCReplenishAccountsResponse should have comment or be unexported (revive)

Check failure on line 471 in rhp/v4/rhp.go

View workflow job for this annotation

GitHub Actions / test / test (1.23, ubuntu-latest)

exported: exported type RPCReplenishAccountsResponse should have comment or be unexported (revive)

Check failure on line 471 in rhp/v4/rhp.go

View workflow job for this annotation

GitHub Actions / test / test (1.23, macos-latest)

exported: exported type RPCReplenishAccountsResponse should have comment or be unexported (revive)
Cost types.Currency `json:"cost"`
}
RPCReplenishAccountsSecondResponse struct {

Check failure on line 474 in rhp/v4/rhp.go

View workflow job for this annotation

GitHub Actions / test / test (1.22, ubuntu-latest)

exported: exported type RPCReplenishAccountsSecondResponse should have comment or be unexported (revive)

Check failure on line 474 in rhp/v4/rhp.go

View workflow job for this annotation

GitHub Actions / test / test (1.23, ubuntu-latest)

exported: exported type RPCReplenishAccountsSecondResponse should have comment or be unexported (revive)

Check failure on line 474 in rhp/v4/rhp.go

View workflow job for this annotation

GitHub Actions / test / test (1.23, macos-latest)

exported: exported type RPCReplenishAccountsSecondResponse should have comment or be unexported (revive)
RenterSignature types.Signature `json:"renterSignature"`
}
RPCReplenishAccountsThirdResponse struct {

Check failure on line 477 in rhp/v4/rhp.go

View workflow job for this annotation

GitHub Actions / test / test (1.22, ubuntu-latest)

exported: exported type RPCReplenishAccountsThirdResponse should have comment or be unexported (revive)

Check failure on line 477 in rhp/v4/rhp.go

View workflow job for this annotation

GitHub Actions / test / test (1.23, ubuntu-latest)

exported: exported type RPCReplenishAccountsThirdResponse should have comment or be unexported (revive)

Check failure on line 477 in rhp/v4/rhp.go

View workflow job for this annotation

GitHub Actions / test / test (1.23, macos-latest)

exported: exported type RPCReplenishAccountsThirdResponse should have comment or be unexported (revive)
HostSignature types.Signature `json:"hostSignature"`
}

// RPCVerifySectorRequest implements Object.
RPCVerifySectorRequest struct {
Prices HostPrices `json:"prices"`
Expand Down Expand Up @@ -547,6 +567,22 @@ func (r *RPCRefreshContractRequest) ValidChallengeSignature(existing types.V2Fil
return existing.RenterPublicKey.VerifyHash(r.ChallengeSigHash(existing.RevisionNumber), r.ChallengeSignature)
}

// ChallengeSigHash returns the hash of the challenge signature used for
// signing.
func (r *RPCReplenishAccountsRequest) ChallengeSigHash(revisionNumber uint64) types.Hash256 {
h := types.NewHasher()
types.EncodeSlice(h.E, r.Accounts)
types.V2Currency(r.Target).EncodeTo(h.E)
r.ContractID.EncodeTo(h.E)
h.E.WriteUint64(revisionNumber)
return h.Sum()
}

// ValidChallengeSignature checks the challenge signature for validity.
func (r *RPCReplenishAccountsRequest) ValidChallengeSignature(fc types.V2FileContract) bool {
return fc.RenterPublicKey.VerifyHash(r.ChallengeSigHash(fc.RevisionNumber), r.ChallengeSignature)
}

// NewContract creates a new file contract with the given settings.
func NewContract(p HostPrices, cp RPCFormContractParams, hostKey types.PublicKey, hostAddress types.Address) (types.V2FileContract, Usage) {
return types.V2FileContract{
Expand Down Expand Up @@ -656,6 +692,13 @@ func ReviseForFundAccounts(fc types.V2FileContract, amount types.Currency) (type
return fc, usage, err
}

// ReviseForReplenish creates a contract revision for the replenish accounts RPC
func ReviseForReplenish(fc types.V2FileContract, amount types.Currency) (types.V2FileContract, Usage, error) {
usage := Usage{AccountFunding: amount}
err := PayWithContract(&fc, usage)
return fc, usage, err
}

// MinRenterAllowance returns the minimum allowance required to justify the given
// host collateral.
func MinRenterAllowance(hp HostPrices, duration uint64, collateral types.Currency) types.Currency {
Expand Down
13 changes: 13 additions & 0 deletions rhp/v4/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,3 +249,16 @@ func (req *RPCAppendSectorsRequest) Validate(pk types.PublicKey) error {
}
return nil
}

// Validate checks that the request is valid
func (req *RPCReplenishAccountsRequest) Validate() error {
switch {
case len(req.Accounts) == 0:
return errors.New("no accounts to replenish")
case len(req.Accounts) > 100:
return fmt.Errorf("too many accounts to replenish: %d > %d", len(req.Accounts), 1000)
case req.Target.IsZero():
return errors.New("target must be greater than zero")
}
return nil
}

0 comments on commit c51a0f7

Please sign in to comment.