Skip to content

Commit

Permalink
feat: implement F3 list participants API
Browse files Browse the repository at this point in the history
  • Loading branch information
simlecode committed Oct 31, 2024
1 parent 7552c55 commit 1cf79da
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 11 deletions.
13 changes: 13 additions & 0 deletions pkg/vf3/f3.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,16 @@ func (fff *F3) IsRunning() bool {
func (fff *F3) Progress() gpbft.Instant {
return fff.inner.Progress()
}

func (fff *F3) ListParticipants() []types.F3Participant {
leases := fff.leaser.getValidLeases()
participants := make([]types.F3Participant, len(leases))
for i, lease := range leases {
participants[i] = types.F3Participant{
MinerID: lease.MinerID,
FromInstance: lease.FromInstance,
ValidityTerm: lease.ValidityTerm,
}
}
return participants
}
37 changes: 26 additions & 11 deletions pkg/vf3/participation_lease.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func (l *leaser) getOrRenewParticipationTicket(participant uint64, previous type
// - it is valid and was issued by this node.
//
// Otherwise, return ErrF3ParticipationIssuerMismatch to signal to the caller the need for retry.
switch _, err := l.validate(manifest.NetworkName, currentInstance, previous); {
switch _, err := l.validateTicket(manifest.NetworkName, currentInstance, previous); {
case errors.Is(err, types.ErrF3ParticipationTicketInvalid):
// Invalid ticket means the miner must have got the ticket from a node with a potentially different version.
// Refuse to issue a new ticket in case there is some other node with active lease for the miner.
Expand Down Expand Up @@ -89,7 +89,7 @@ func (l *leaser) participate(ticket types.F3ParticipationTicket) (types.F3Partic
if manifest == nil {
return types.F3ParticipationLease{}, types.ErrF3NotReady
}
newLease, err := l.validate(manifest.NetworkName, instant.ID, ticket)
newLease, err := l.validateTicket(manifest.NetworkName, instant.ID, ticket)
if err != nil {
return types.F3ParticipationLease{}, err
}
Expand Down Expand Up @@ -118,22 +118,34 @@ func (l *leaser) getParticipantsByInstance(network gpbft.NetworkName, instance u
}
var participants []uint64
for id, lease := range l.leases {
if currentNetwork != lease.Network {
// Lazily delete any lease that does not belong to network, likely acquired from
// prior manifests.
if _, err := l.validateLease(currentNetwork, instance, lease); err != nil {
// Lazily clear old leases.
log.Warnf("lost F3 participation lease for miner %d at instance %d since it is no loger valid: %v ", id, instance, err)
delete(l.leases, id)
log.Warnf("lost F3 participation lease for miner %d at instance %d due to network mismatch: %s != %s", id, instance, currentNetwork, lease.Network)
} else if instance > lease.ToInstance() {
// Lazily delete the expired leases.
delete(l.leases, id)
log.Warnf("lost F3 participation lease for miner %d due to instance (%d) > lease to instance (%d)", id, instance, lease.ToInstance())
} else {
participants = append(participants, id)
}
}
return participants
}

func (l *leaser) getValidLeases() []types.F3ParticipationLease {
l.mutex.Lock()
defer l.mutex.Unlock()
currentManifest, progress := l.status()
var leases []types.F3ParticipationLease
for id, lease := range l.leases {
// Lazily clear old leases.
if validatedLease, err := l.validateLease(currentManifest.NetworkName, progress.ID, lease); err != nil {
log.Warnf("lost F3 participation lease for miner %d at instance %d while getting valid leases since it is no loger valid: %v ", id, progress.ID, err)
delete(l.leases, id)
} else {
leases = append(leases, validatedLease)
}
}
return leases
}

func (l *leaser) newParticipationTicket(nn gpbft.NetworkName, participant uint64, from uint64, instances uint64) (types.F3ParticipationTicket, error) {
// Lotus node API and miners run in a trusted environment. For now we make the
// ticket to simply be the CBOR encoding of the lease. In the future, where the
Expand All @@ -152,13 +164,16 @@ func (l *leaser) newParticipationTicket(nn gpbft.NetworkName, participant uint64
return buf.Bytes(), nil
}

func (l *leaser) validate(currentNetwork gpbft.NetworkName, currentInstance uint64, t types.F3ParticipationTicket) (types.F3ParticipationLease, error) {
func (l *leaser) validateTicket(currentNetwork gpbft.NetworkName, currentInstance uint64, t types.F3ParticipationTicket) (types.F3ParticipationLease, error) {
var lease types.F3ParticipationLease
reader := bytes.NewReader(t)
if err := lease.UnmarshalCBOR(reader); err != nil {
return types.F3ParticipationLease{}, types.ErrF3ParticipationTicketInvalid
}
return l.validateLease(currentNetwork, currentInstance, lease)
}

func (l *leaser) validateLease(currentNetwork gpbft.NetworkName, currentInstance uint64, lease types.F3ParticipationLease) (types.F3ParticipationLease, error) {
// Combine the errors to remove significance of the order by which they are
// checked outside if this function.
var err error
Expand Down
3 changes: 3 additions & 0 deletions venus-shared/api/chain/v1/f3.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,7 @@ type IF3 interface {
F3IsRunning(ctx context.Context) (bool, error) //perm:read
// F3GetProgress returns the progress of the current F3 instance in terms of instance ID, round and phase.
F3GetProgress(ctx context.Context) (gpbft.Instant, error) //perm:read

// F3ListParticipants returns the list of miners that are currently participating in F3 via this node.
F3ListParticipants(ctx context.Context) ([]types.F3Participant, error) //perm:read
}
20 changes: 20 additions & 0 deletions venus-shared/api/chain/v1/method.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ curl http://<ip>:<port>/rpc/v1 -X POST -H "Content-Type: application/json" -H "
* [F3GetOrRenewParticipationTicket](#f3getorrenewparticipationticket)
* [F3GetProgress](#f3getprogress)
* [F3IsRunning](#f3isrunning)
* [F3ListParticipants](#f3listparticipants)
* [F3Participate](#f3participate)
* [Market](#market)
* [StateMarketParticipants](#statemarketparticipants)
Expand Down Expand Up @@ -3803,6 +3804,25 @@ Inputs: `[]`

Response: `true`

### F3ListParticipants
F3ListParticipants returns the list of miners that are currently participating in F3 via this node.


Perms: read

Inputs: `[]`

Response:
```json
[
{
"MinerID": 42,
"FromInstance": 42,
"ValidityTerm": 42
}
]
```

### F3Participate
F3Participate enrolls a storage provider in the F3 consensus process using a
provided participation ticket. This ticket grants a temporary lease that enables
Expand Down
15 changes: 15 additions & 0 deletions venus-shared/api/chain/v1/mock/mock_fullnode.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions venus-shared/api/chain/v1/proxy_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions venus-shared/types/api_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,19 @@ func (l *F3ParticipationLease) ToInstance() uint64 {
return l.FromInstance + l.ValidityTerm
}

// F3Participant captures information about the miners that are currently
// participating in F3, along with the number of instances for which their lease
// is valid.
type F3Participant struct {
// MinerID is the actor ID of the miner that is
MinerID uint64
// FromInstance specifies the instance ID from which this lease is valid.
FromInstance uint64
// ValidityTerm specifies the number of instances for which the lease remains
// valid from the FromInstance.
ValidityTerm uint64
}

var (
// ErrF3Disabled signals that F3 consensus process is disabled.
ErrF3Disabled = errF3Disabled{}
Expand Down

0 comments on commit 1cf79da

Please sign in to comment.