diff --git a/api/node/client/client.gen.go b/api/node/client/client.gen.go index f54d074905..82b0455f8e 100644 --- a/api/node/client/client.gen.go +++ b/api/node/client/client.gen.go @@ -130,26 +130,26 @@ type ClientInterface interface { PostActivationPublish(ctx context.Context, body PostActivationPublishJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetBeaconEpoch request + GetBeaconEpoch(ctx context.Context, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetEligibilitySlotsNodeEpoch request GetEligibilitySlotsNodeEpoch(ctx context.Context, node externalRef0.Bytes32Hex, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*http.Response, error) - // GetHareBeaconEpoch request - GetHareBeaconEpoch(ctx context.Context, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*http.Response, error) - // GetHareRoundTemplateLayerIterRound request GetHareRoundTemplateLayerIterRound(ctx context.Context, layer externalRef0.LayerID, iter externalRef0.HareIter, round externalRef0.HareRound, reqEditors ...RequestEditorFn) (*http.Response, error) - // GetHareTotalWeightEpoch request - GetHareTotalWeightEpoch(ctx context.Context, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*http.Response, error) - - // GetHareWeightNodeIdEpoch request - GetHareWeightNodeIdEpoch(ctx context.Context, nodeId externalRef0.Bytes32Hex, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*http.Response, error) - // GetProposalLayerNode request GetProposalLayerNode(ctx context.Context, layer externalRef0.LayerID, node externalRef0.Bytes32Hex, reqEditors ...RequestEditorFn) (*http.Response, error) // PostPublishProtocolWithBody request with any body PostPublishProtocolWithBody(ctx context.Context, protocol PostPublishProtocolParamsProtocol, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + // GetWeightsMinerNodeIdEpoch request + GetWeightsMinerNodeIdEpoch(ctx context.Context, nodeId externalRef0.Bytes32Hex, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*http.Response, error) + + // GetWeightsTotalEpoch request + GetWeightsTotalEpoch(ctx context.Context, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*http.Response, error) } func (c *Client) GetActivationAtxAtxId(ctx context.Context, atxId externalRef0.Bytes32Hex, reqEditors ...RequestEditorFn) (*http.Response, error) { @@ -212,8 +212,8 @@ func (c *Client) PostActivationPublish(ctx context.Context, body PostActivationP return c.Client.Do(req) } -func (c *Client) GetEligibilitySlotsNodeEpoch(ctx context.Context, node externalRef0.Bytes32Hex, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetEligibilitySlotsNodeEpochRequest(c.Server, node, epoch) +func (c *Client) GetBeaconEpoch(ctx context.Context, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetBeaconEpochRequest(c.Server, epoch) if err != nil { return nil, err } @@ -224,8 +224,8 @@ func (c *Client) GetEligibilitySlotsNodeEpoch(ctx context.Context, node external return c.Client.Do(req) } -func (c *Client) GetHareBeaconEpoch(ctx context.Context, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetHareBeaconEpochRequest(c.Server, epoch) +func (c *Client) GetEligibilitySlotsNodeEpoch(ctx context.Context, node externalRef0.Bytes32Hex, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetEligibilitySlotsNodeEpochRequest(c.Server, node, epoch) if err != nil { return nil, err } @@ -248,8 +248,8 @@ func (c *Client) GetHareRoundTemplateLayerIterRound(ctx context.Context, layer e return c.Client.Do(req) } -func (c *Client) GetHareTotalWeightEpoch(ctx context.Context, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetHareTotalWeightEpochRequest(c.Server, epoch) +func (c *Client) GetProposalLayerNode(ctx context.Context, layer externalRef0.LayerID, node externalRef0.Bytes32Hex, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetProposalLayerNodeRequest(c.Server, layer, node) if err != nil { return nil, err } @@ -260,8 +260,8 @@ func (c *Client) GetHareTotalWeightEpoch(ctx context.Context, epoch externalRef0 return c.Client.Do(req) } -func (c *Client) GetHareWeightNodeIdEpoch(ctx context.Context, nodeId externalRef0.Bytes32Hex, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetHareWeightNodeIdEpochRequest(c.Server, nodeId, epoch) +func (c *Client) PostPublishProtocolWithBody(ctx context.Context, protocol PostPublishProtocolParamsProtocol, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewPostPublishProtocolRequestWithBody(c.Server, protocol, contentType, body) if err != nil { return nil, err } @@ -272,8 +272,8 @@ func (c *Client) GetHareWeightNodeIdEpoch(ctx context.Context, nodeId externalRe return c.Client.Do(req) } -func (c *Client) GetProposalLayerNode(ctx context.Context, layer externalRef0.LayerID, node externalRef0.Bytes32Hex, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewGetProposalLayerNodeRequest(c.Server, layer, node) +func (c *Client) GetWeightsMinerNodeIdEpoch(ctx context.Context, nodeId externalRef0.Bytes32Hex, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetWeightsMinerNodeIdEpochRequest(c.Server, nodeId, epoch) if err != nil { return nil, err } @@ -284,8 +284,8 @@ func (c *Client) GetProposalLayerNode(ctx context.Context, layer externalRef0.La return c.Client.Do(req) } -func (c *Client) PostPublishProtocolWithBody(ctx context.Context, protocol PostPublishProtocolParamsProtocol, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { - req, err := NewPostPublishProtocolRequestWithBody(c.Server, protocol, contentType, body) +func (c *Client) GetWeightsTotalEpoch(ctx context.Context, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetWeightsTotalEpochRequest(c.Server, epoch) if err != nil { return nil, err } @@ -438,20 +438,13 @@ func NewPostActivationPublishRequestWithBody(server string, contentType string, return req, nil } -// NewGetEligibilitySlotsNodeEpochRequest generates requests for GetEligibilitySlotsNodeEpoch -func NewGetEligibilitySlotsNodeEpochRequest(server string, node externalRef0.Bytes32Hex, epoch externalRef0.EpochID) (*http.Request, error) { +// NewGetBeaconEpochRequest generates requests for GetBeaconEpoch +func NewGetBeaconEpochRequest(server string, epoch externalRef0.EpochID) (*http.Request, error) { var err error var pathParam0 string - pathParam0, err = runtime.StyleParamWithLocation("simple", false, "node", runtime.ParamLocationPath, node) - if err != nil { - return nil, err - } - - var pathParam1 string - - pathParam1, err = runtime.StyleParamWithLocation("simple", false, "epoch", runtime.ParamLocationPath, epoch) + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "epoch", runtime.ParamLocationPath, epoch) if err != nil { return nil, err } @@ -461,7 +454,7 @@ func NewGetEligibilitySlotsNodeEpochRequest(server string, node externalRef0.Byt return nil, err } - operationPath := fmt.Sprintf("/eligibility/slots/%s/%s", pathParam0, pathParam1) + operationPath := fmt.Sprintf("/beacon/%s", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -479,13 +472,20 @@ func NewGetEligibilitySlotsNodeEpochRequest(server string, node externalRef0.Byt return req, nil } -// NewGetHareBeaconEpochRequest generates requests for GetHareBeaconEpoch -func NewGetHareBeaconEpochRequest(server string, epoch externalRef0.EpochID) (*http.Request, error) { +// NewGetEligibilitySlotsNodeEpochRequest generates requests for GetEligibilitySlotsNodeEpoch +func NewGetEligibilitySlotsNodeEpochRequest(server string, node externalRef0.Bytes32Hex, epoch externalRef0.EpochID) (*http.Request, error) { var err error var pathParam0 string - pathParam0, err = runtime.StyleParamWithLocation("simple", false, "epoch", runtime.ParamLocationPath, epoch) + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "node", runtime.ParamLocationPath, node) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "epoch", runtime.ParamLocationPath, epoch) if err != nil { return nil, err } @@ -495,7 +495,7 @@ func NewGetHareBeaconEpochRequest(server string, epoch externalRef0.EpochID) (*h return nil, err } - operationPath := fmt.Sprintf("/hare/beacon/%s", pathParam0) + operationPath := fmt.Sprintf("/eligibility/slots/%s/%s", pathParam0, pathParam1) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -561,13 +561,20 @@ func NewGetHareRoundTemplateLayerIterRoundRequest(server string, layer externalR return req, nil } -// NewGetHareTotalWeightEpochRequest generates requests for GetHareTotalWeightEpoch -func NewGetHareTotalWeightEpochRequest(server string, epoch externalRef0.EpochID) (*http.Request, error) { +// NewGetProposalLayerNodeRequest generates requests for GetProposalLayerNode +func NewGetProposalLayerNodeRequest(server string, layer externalRef0.LayerID, node externalRef0.Bytes32Hex) (*http.Request, error) { var err error var pathParam0 string - pathParam0, err = runtime.StyleParamWithLocation("simple", false, "epoch", runtime.ParamLocationPath, epoch) + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "layer", runtime.ParamLocationPath, layer) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "node", runtime.ParamLocationPath, node) if err != nil { return nil, err } @@ -577,7 +584,7 @@ func NewGetHareTotalWeightEpochRequest(server string, epoch externalRef0.EpochID return nil, err } - operationPath := fmt.Sprintf("/hare/total_weight/%s", pathParam0) + operationPath := fmt.Sprintf("/proposal/%s/%s", pathParam0, pathParam1) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -595,20 +602,13 @@ func NewGetHareTotalWeightEpochRequest(server string, epoch externalRef0.EpochID return req, nil } -// NewGetHareWeightNodeIdEpochRequest generates requests for GetHareWeightNodeIdEpoch -func NewGetHareWeightNodeIdEpochRequest(server string, nodeId externalRef0.Bytes32Hex, epoch externalRef0.EpochID) (*http.Request, error) { +// NewPostPublishProtocolRequestWithBody generates requests for PostPublishProtocol with any type of body +func NewPostPublishProtocolRequestWithBody(server string, protocol PostPublishProtocolParamsProtocol, contentType string, body io.Reader) (*http.Request, error) { var err error var pathParam0 string - pathParam0, err = runtime.StyleParamWithLocation("simple", false, "node_id", runtime.ParamLocationPath, nodeId) - if err != nil { - return nil, err - } - - var pathParam1 string - - pathParam1, err = runtime.StyleParamWithLocation("simple", false, "epoch", runtime.ParamLocationPath, epoch) + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "protocol", runtime.ParamLocationPath, protocol) if err != nil { return nil, err } @@ -618,7 +618,7 @@ func NewGetHareWeightNodeIdEpochRequest(server string, nodeId externalRef0.Bytes return nil, err } - operationPath := fmt.Sprintf("/hare/weight/%s/%s", pathParam0, pathParam1) + operationPath := fmt.Sprintf("/publish/%s", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -628,28 +628,30 @@ func NewGetHareWeightNodeIdEpochRequest(server string, nodeId externalRef0.Bytes return nil, err } - req, err := http.NewRequest("GET", queryURL.String(), nil) + req, err := http.NewRequest("POST", queryURL.String(), body) if err != nil { return nil, err } + req.Header.Add("Content-Type", contentType) + return req, nil } -// NewGetProposalLayerNodeRequest generates requests for GetProposalLayerNode -func NewGetProposalLayerNodeRequest(server string, layer externalRef0.LayerID, node externalRef0.Bytes32Hex) (*http.Request, error) { +// NewGetWeightsMinerNodeIdEpochRequest generates requests for GetWeightsMinerNodeIdEpoch +func NewGetWeightsMinerNodeIdEpochRequest(server string, nodeId externalRef0.Bytes32Hex, epoch externalRef0.EpochID) (*http.Request, error) { var err error var pathParam0 string - pathParam0, err = runtime.StyleParamWithLocation("simple", false, "layer", runtime.ParamLocationPath, layer) + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "node_id", runtime.ParamLocationPath, nodeId) if err != nil { return nil, err } var pathParam1 string - pathParam1, err = runtime.StyleParamWithLocation("simple", false, "node", runtime.ParamLocationPath, node) + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "epoch", runtime.ParamLocationPath, epoch) if err != nil { return nil, err } @@ -659,7 +661,7 @@ func NewGetProposalLayerNodeRequest(server string, layer externalRef0.LayerID, n return nil, err } - operationPath := fmt.Sprintf("/proposal/%s/%s", pathParam0, pathParam1) + operationPath := fmt.Sprintf("/weights/miner/%s/%s", pathParam0, pathParam1) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -677,13 +679,13 @@ func NewGetProposalLayerNodeRequest(server string, layer externalRef0.LayerID, n return req, nil } -// NewPostPublishProtocolRequestWithBody generates requests for PostPublishProtocol with any type of body -func NewPostPublishProtocolRequestWithBody(server string, protocol PostPublishProtocolParamsProtocol, contentType string, body io.Reader) (*http.Request, error) { +// NewGetWeightsTotalEpochRequest generates requests for GetWeightsTotalEpoch +func NewGetWeightsTotalEpochRequest(server string, epoch externalRef0.EpochID) (*http.Request, error) { var err error var pathParam0 string - pathParam0, err = runtime.StyleParamWithLocation("simple", false, "protocol", runtime.ParamLocationPath, protocol) + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "epoch", runtime.ParamLocationPath, epoch) if err != nil { return nil, err } @@ -693,7 +695,7 @@ func NewPostPublishProtocolRequestWithBody(server string, protocol PostPublishPr return nil, err } - operationPath := fmt.Sprintf("/publish/%s", pathParam0) + operationPath := fmt.Sprintf("/weights/total/%s", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -703,13 +705,11 @@ func NewPostPublishProtocolRequestWithBody(server string, protocol PostPublishPr return nil, err } - req, err := http.NewRequest("POST", queryURL.String(), body) + req, err := http.NewRequest("GET", queryURL.String(), nil) if err != nil { return nil, err } - req.Header.Add("Content-Type", contentType) - return req, nil } @@ -770,26 +770,26 @@ type ClientWithResponsesInterface interface { PostActivationPublishWithResponse(ctx context.Context, body PostActivationPublishJSONRequestBody, reqEditors ...RequestEditorFn) (*PostActivationPublishResponse, error) + // GetBeaconEpochWithResponse request + GetBeaconEpochWithResponse(ctx context.Context, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*GetBeaconEpochResponse, error) + // GetEligibilitySlotsNodeEpochWithResponse request GetEligibilitySlotsNodeEpochWithResponse(ctx context.Context, node externalRef0.Bytes32Hex, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*GetEligibilitySlotsNodeEpochResponse, error) - // GetHareBeaconEpochWithResponse request - GetHareBeaconEpochWithResponse(ctx context.Context, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*GetHareBeaconEpochResponse, error) - // GetHareRoundTemplateLayerIterRoundWithResponse request GetHareRoundTemplateLayerIterRoundWithResponse(ctx context.Context, layer externalRef0.LayerID, iter externalRef0.HareIter, round externalRef0.HareRound, reqEditors ...RequestEditorFn) (*GetHareRoundTemplateLayerIterRoundResponse, error) - // GetHareTotalWeightEpochWithResponse request - GetHareTotalWeightEpochWithResponse(ctx context.Context, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*GetHareTotalWeightEpochResponse, error) - - // GetHareWeightNodeIdEpochWithResponse request - GetHareWeightNodeIdEpochWithResponse(ctx context.Context, nodeId externalRef0.Bytes32Hex, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*GetHareWeightNodeIdEpochResponse, error) - // GetProposalLayerNodeWithResponse request GetProposalLayerNodeWithResponse(ctx context.Context, layer externalRef0.LayerID, node externalRef0.Bytes32Hex, reqEditors ...RequestEditorFn) (*GetProposalLayerNodeResponse, error) // PostPublishProtocolWithBodyWithResponse request with any body PostPublishProtocolWithBodyWithResponse(ctx context.Context, protocol PostPublishProtocolParamsProtocol, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostPublishProtocolResponse, error) + + // GetWeightsMinerNodeIdEpochWithResponse request + GetWeightsMinerNodeIdEpochWithResponse(ctx context.Context, nodeId externalRef0.Bytes32Hex, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*GetWeightsMinerNodeIdEpochResponse, error) + + // GetWeightsTotalEpochWithResponse request + GetWeightsTotalEpochWithResponse(ctx context.Context, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*GetWeightsTotalEpochResponse, error) } type GetActivationAtxAtxIdResponse struct { @@ -881,17 +881,16 @@ func (r PostActivationPublishResponse) StatusCode() int { return 0 } -type GetEligibilitySlotsNodeEpochResponse struct { +type GetBeaconEpochResponse struct { Body []byte HTTPResponse *http.Response JSON200 *struct { - Nonce uint64 `json:"nonce"` - Slots uint32 `json:"slots"` + Beacon externalRef0.Beacon `json:"beacon"` } } // Status returns HTTPResponse.Status -func (r GetEligibilitySlotsNodeEpochResponse) Status() string { +func (r GetBeaconEpochResponse) Status() string { if r.HTTPResponse != nil { return r.HTTPResponse.Status } @@ -899,23 +898,24 @@ func (r GetEligibilitySlotsNodeEpochResponse) Status() string { } // StatusCode returns HTTPResponse.StatusCode -func (r GetEligibilitySlotsNodeEpochResponse) StatusCode() int { +func (r GetBeaconEpochResponse) StatusCode() int { if r.HTTPResponse != nil { return r.HTTPResponse.StatusCode } return 0 } -type GetHareBeaconEpochResponse struct { +type GetEligibilitySlotsNodeEpochResponse struct { Body []byte HTTPResponse *http.Response JSON200 *struct { - Beacon externalRef0.Beacon `json:"beacon"` + Nonce uint64 `json:"nonce"` + Slots uint32 `json:"slots"` } } // Status returns HTTPResponse.Status -func (r GetHareBeaconEpochResponse) Status() string { +func (r GetEligibilitySlotsNodeEpochResponse) Status() string { if r.HTTPResponse != nil { return r.HTTPResponse.Status } @@ -923,7 +923,7 @@ func (r GetHareBeaconEpochResponse) Status() string { } // StatusCode returns HTTPResponse.StatusCode -func (r GetHareBeaconEpochResponse) StatusCode() int { +func (r GetEligibilitySlotsNodeEpochResponse) StatusCode() int { if r.HTTPResponse != nil { return r.HTTPResponse.StatusCode } @@ -952,16 +952,14 @@ func (r GetHareRoundTemplateLayerIterRoundResponse) StatusCode() int { return 0 } -type GetHareTotalWeightEpochResponse struct { +type GetProposalLayerNodeResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *struct { - Weight uint64 `json:"weight"` - } + JSON200 *externalRef0.PartialProposal } // Status returns HTTPResponse.Status -func (r GetHareTotalWeightEpochResponse) Status() string { +func (r GetProposalLayerNodeResponse) Status() string { if r.HTTPResponse != nil { return r.HTTPResponse.Status } @@ -969,23 +967,20 @@ func (r GetHareTotalWeightEpochResponse) Status() string { } // StatusCode returns HTTPResponse.StatusCode -func (r GetHareTotalWeightEpochResponse) StatusCode() int { +func (r GetProposalLayerNodeResponse) StatusCode() int { if r.HTTPResponse != nil { return r.HTTPResponse.StatusCode } return 0 } -type GetHareWeightNodeIdEpochResponse struct { +type PostPublishProtocolResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *struct { - Weight uint64 `json:"weight"` - } } // Status returns HTTPResponse.Status -func (r GetHareWeightNodeIdEpochResponse) Status() string { +func (r PostPublishProtocolResponse) Status() string { if r.HTTPResponse != nil { return r.HTTPResponse.Status } @@ -993,21 +988,23 @@ func (r GetHareWeightNodeIdEpochResponse) Status() string { } // StatusCode returns HTTPResponse.StatusCode -func (r GetHareWeightNodeIdEpochResponse) StatusCode() int { +func (r PostPublishProtocolResponse) StatusCode() int { if r.HTTPResponse != nil { return r.HTTPResponse.StatusCode } return 0 } -type GetProposalLayerNodeResponse struct { +type GetWeightsMinerNodeIdEpochResponse struct { Body []byte HTTPResponse *http.Response - JSON200 *externalRef0.PartialProposal + JSON200 *struct { + Weight uint64 `json:"weight"` + } } // Status returns HTTPResponse.Status -func (r GetProposalLayerNodeResponse) Status() string { +func (r GetWeightsMinerNodeIdEpochResponse) Status() string { if r.HTTPResponse != nil { return r.HTTPResponse.Status } @@ -1015,20 +1012,23 @@ func (r GetProposalLayerNodeResponse) Status() string { } // StatusCode returns HTTPResponse.StatusCode -func (r GetProposalLayerNodeResponse) StatusCode() int { +func (r GetWeightsMinerNodeIdEpochResponse) StatusCode() int { if r.HTTPResponse != nil { return r.HTTPResponse.StatusCode } return 0 } -type PostPublishProtocolResponse struct { +type GetWeightsTotalEpochResponse struct { Body []byte HTTPResponse *http.Response + JSON200 *struct { + Weight uint64 `json:"weight"` + } } // Status returns HTTPResponse.Status -func (r PostPublishProtocolResponse) Status() string { +func (r GetWeightsTotalEpochResponse) Status() string { if r.HTTPResponse != nil { return r.HTTPResponse.Status } @@ -1036,7 +1036,7 @@ func (r PostPublishProtocolResponse) Status() string { } // StatusCode returns HTTPResponse.StatusCode -func (r PostPublishProtocolResponse) StatusCode() int { +func (r GetWeightsTotalEpochResponse) StatusCode() int { if r.HTTPResponse != nil { return r.HTTPResponse.StatusCode } @@ -1087,22 +1087,22 @@ func (c *ClientWithResponses) PostActivationPublishWithResponse(ctx context.Cont return ParsePostActivationPublishResponse(rsp) } -// GetEligibilitySlotsNodeEpochWithResponse request returning *GetEligibilitySlotsNodeEpochResponse -func (c *ClientWithResponses) GetEligibilitySlotsNodeEpochWithResponse(ctx context.Context, node externalRef0.Bytes32Hex, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*GetEligibilitySlotsNodeEpochResponse, error) { - rsp, err := c.GetEligibilitySlotsNodeEpoch(ctx, node, epoch, reqEditors...) +// GetBeaconEpochWithResponse request returning *GetBeaconEpochResponse +func (c *ClientWithResponses) GetBeaconEpochWithResponse(ctx context.Context, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*GetBeaconEpochResponse, error) { + rsp, err := c.GetBeaconEpoch(ctx, epoch, reqEditors...) if err != nil { return nil, err } - return ParseGetEligibilitySlotsNodeEpochResponse(rsp) + return ParseGetBeaconEpochResponse(rsp) } -// GetHareBeaconEpochWithResponse request returning *GetHareBeaconEpochResponse -func (c *ClientWithResponses) GetHareBeaconEpochWithResponse(ctx context.Context, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*GetHareBeaconEpochResponse, error) { - rsp, err := c.GetHareBeaconEpoch(ctx, epoch, reqEditors...) +// GetEligibilitySlotsNodeEpochWithResponse request returning *GetEligibilitySlotsNodeEpochResponse +func (c *ClientWithResponses) GetEligibilitySlotsNodeEpochWithResponse(ctx context.Context, node externalRef0.Bytes32Hex, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*GetEligibilitySlotsNodeEpochResponse, error) { + rsp, err := c.GetEligibilitySlotsNodeEpoch(ctx, node, epoch, reqEditors...) if err != nil { return nil, err } - return ParseGetHareBeaconEpochResponse(rsp) + return ParseGetEligibilitySlotsNodeEpochResponse(rsp) } // GetHareRoundTemplateLayerIterRoundWithResponse request returning *GetHareRoundTemplateLayerIterRoundResponse @@ -1114,40 +1114,40 @@ func (c *ClientWithResponses) GetHareRoundTemplateLayerIterRoundWithResponse(ctx return ParseGetHareRoundTemplateLayerIterRoundResponse(rsp) } -// GetHareTotalWeightEpochWithResponse request returning *GetHareTotalWeightEpochResponse -func (c *ClientWithResponses) GetHareTotalWeightEpochWithResponse(ctx context.Context, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*GetHareTotalWeightEpochResponse, error) { - rsp, err := c.GetHareTotalWeightEpoch(ctx, epoch, reqEditors...) +// GetProposalLayerNodeWithResponse request returning *GetProposalLayerNodeResponse +func (c *ClientWithResponses) GetProposalLayerNodeWithResponse(ctx context.Context, layer externalRef0.LayerID, node externalRef0.Bytes32Hex, reqEditors ...RequestEditorFn) (*GetProposalLayerNodeResponse, error) { + rsp, err := c.GetProposalLayerNode(ctx, layer, node, reqEditors...) if err != nil { return nil, err } - return ParseGetHareTotalWeightEpochResponse(rsp) + return ParseGetProposalLayerNodeResponse(rsp) } -// GetHareWeightNodeIdEpochWithResponse request returning *GetHareWeightNodeIdEpochResponse -func (c *ClientWithResponses) GetHareWeightNodeIdEpochWithResponse(ctx context.Context, nodeId externalRef0.Bytes32Hex, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*GetHareWeightNodeIdEpochResponse, error) { - rsp, err := c.GetHareWeightNodeIdEpoch(ctx, nodeId, epoch, reqEditors...) +// PostPublishProtocolWithBodyWithResponse request with arbitrary body returning *PostPublishProtocolResponse +func (c *ClientWithResponses) PostPublishProtocolWithBodyWithResponse(ctx context.Context, protocol PostPublishProtocolParamsProtocol, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostPublishProtocolResponse, error) { + rsp, err := c.PostPublishProtocolWithBody(ctx, protocol, contentType, body, reqEditors...) if err != nil { return nil, err } - return ParseGetHareWeightNodeIdEpochResponse(rsp) + return ParsePostPublishProtocolResponse(rsp) } -// GetProposalLayerNodeWithResponse request returning *GetProposalLayerNodeResponse -func (c *ClientWithResponses) GetProposalLayerNodeWithResponse(ctx context.Context, layer externalRef0.LayerID, node externalRef0.Bytes32Hex, reqEditors ...RequestEditorFn) (*GetProposalLayerNodeResponse, error) { - rsp, err := c.GetProposalLayerNode(ctx, layer, node, reqEditors...) +// GetWeightsMinerNodeIdEpochWithResponse request returning *GetWeightsMinerNodeIdEpochResponse +func (c *ClientWithResponses) GetWeightsMinerNodeIdEpochWithResponse(ctx context.Context, nodeId externalRef0.Bytes32Hex, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*GetWeightsMinerNodeIdEpochResponse, error) { + rsp, err := c.GetWeightsMinerNodeIdEpoch(ctx, nodeId, epoch, reqEditors...) if err != nil { return nil, err } - return ParseGetProposalLayerNodeResponse(rsp) + return ParseGetWeightsMinerNodeIdEpochResponse(rsp) } -// PostPublishProtocolWithBodyWithResponse request with arbitrary body returning *PostPublishProtocolResponse -func (c *ClientWithResponses) PostPublishProtocolWithBodyWithResponse(ctx context.Context, protocol PostPublishProtocolParamsProtocol, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostPublishProtocolResponse, error) { - rsp, err := c.PostPublishProtocolWithBody(ctx, protocol, contentType, body, reqEditors...) +// GetWeightsTotalEpochWithResponse request returning *GetWeightsTotalEpochResponse +func (c *ClientWithResponses) GetWeightsTotalEpochWithResponse(ctx context.Context, epoch externalRef0.EpochID, reqEditors ...RequestEditorFn) (*GetWeightsTotalEpochResponse, error) { + rsp, err := c.GetWeightsTotalEpoch(ctx, epoch, reqEditors...) if err != nil { return nil, err } - return ParsePostPublishProtocolResponse(rsp) + return ParseGetWeightsTotalEpochResponse(rsp) } // ParseGetActivationAtxAtxIdResponse parses an HTTP response from a GetActivationAtxAtxIdWithResponse call @@ -1246,15 +1246,15 @@ func ParsePostActivationPublishResponse(rsp *http.Response) (*PostActivationPubl return response, nil } -// ParseGetEligibilitySlotsNodeEpochResponse parses an HTTP response from a GetEligibilitySlotsNodeEpochWithResponse call -func ParseGetEligibilitySlotsNodeEpochResponse(rsp *http.Response) (*GetEligibilitySlotsNodeEpochResponse, error) { +// ParseGetBeaconEpochResponse parses an HTTP response from a GetBeaconEpochWithResponse call +func ParseGetBeaconEpochResponse(rsp *http.Response) (*GetBeaconEpochResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &GetEligibilitySlotsNodeEpochResponse{ + response := &GetBeaconEpochResponse{ Body: bodyBytes, HTTPResponse: rsp, } @@ -1262,8 +1262,7 @@ func ParseGetEligibilitySlotsNodeEpochResponse(rsp *http.Response) (*GetEligibil switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: var dest struct { - Nonce uint64 `json:"nonce"` - Slots uint32 `json:"slots"` + Beacon externalRef0.Beacon `json:"beacon"` } if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err @@ -1275,15 +1274,15 @@ func ParseGetEligibilitySlotsNodeEpochResponse(rsp *http.Response) (*GetEligibil return response, nil } -// ParseGetHareBeaconEpochResponse parses an HTTP response from a GetHareBeaconEpochWithResponse call -func ParseGetHareBeaconEpochResponse(rsp *http.Response) (*GetHareBeaconEpochResponse, error) { +// ParseGetEligibilitySlotsNodeEpochResponse parses an HTTP response from a GetEligibilitySlotsNodeEpochWithResponse call +func ParseGetEligibilitySlotsNodeEpochResponse(rsp *http.Response) (*GetEligibilitySlotsNodeEpochResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &GetHareBeaconEpochResponse{ + response := &GetEligibilitySlotsNodeEpochResponse{ Body: bodyBytes, HTTPResponse: rsp, } @@ -1291,7 +1290,8 @@ func ParseGetHareBeaconEpochResponse(rsp *http.Response) (*GetHareBeaconEpochRes switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: var dest struct { - Beacon externalRef0.Beacon `json:"beacon"` + Nonce uint64 `json:"nonce"` + Slots uint32 `json:"slots"` } if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err @@ -1329,24 +1329,22 @@ func ParseGetHareRoundTemplateLayerIterRoundResponse(rsp *http.Response) (*GetHa return response, nil } -// ParseGetHareTotalWeightEpochResponse parses an HTTP response from a GetHareTotalWeightEpochWithResponse call -func ParseGetHareTotalWeightEpochResponse(rsp *http.Response) (*GetHareTotalWeightEpochResponse, error) { +// ParseGetProposalLayerNodeResponse parses an HTTP response from a GetProposalLayerNodeWithResponse call +func ParseGetProposalLayerNodeResponse(rsp *http.Response) (*GetProposalLayerNodeResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &GetHareTotalWeightEpochResponse{ + response := &GetProposalLayerNodeResponse{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest struct { - Weight uint64 `json:"weight"` - } + var dest externalRef0.PartialProposal if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -1357,50 +1355,40 @@ func ParseGetHareTotalWeightEpochResponse(rsp *http.Response) (*GetHareTotalWeig return response, nil } -// ParseGetHareWeightNodeIdEpochResponse parses an HTTP response from a GetHareWeightNodeIdEpochWithResponse call -func ParseGetHareWeightNodeIdEpochResponse(rsp *http.Response) (*GetHareWeightNodeIdEpochResponse, error) { +// ParsePostPublishProtocolResponse parses an HTTP response from a PostPublishProtocolWithResponse call +func ParsePostPublishProtocolResponse(rsp *http.Response) (*PostPublishProtocolResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &GetHareWeightNodeIdEpochResponse{ + response := &PostPublishProtocolResponse{ Body: bodyBytes, HTTPResponse: rsp, } - switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest struct { - Weight uint64 `json:"weight"` - } - if err := json.Unmarshal(bodyBytes, &dest); err != nil { - return nil, err - } - response.JSON200 = &dest - - } - return response, nil } -// ParseGetProposalLayerNodeResponse parses an HTTP response from a GetProposalLayerNodeWithResponse call -func ParseGetProposalLayerNodeResponse(rsp *http.Response) (*GetProposalLayerNodeResponse, error) { +// ParseGetWeightsMinerNodeIdEpochResponse parses an HTTP response from a GetWeightsMinerNodeIdEpochWithResponse call +func ParseGetWeightsMinerNodeIdEpochResponse(rsp *http.Response) (*GetWeightsMinerNodeIdEpochResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &GetProposalLayerNodeResponse{ + response := &GetWeightsMinerNodeIdEpochResponse{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest externalRef0.PartialProposal + var dest struct { + Weight uint64 `json:"weight"` + } if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -1411,18 +1399,30 @@ func ParseGetProposalLayerNodeResponse(rsp *http.Response) (*GetProposalLayerNod return response, nil } -// ParsePostPublishProtocolResponse parses an HTTP response from a PostPublishProtocolWithResponse call -func ParsePostPublishProtocolResponse(rsp *http.Response) (*PostPublishProtocolResponse, error) { +// ParseGetWeightsTotalEpochResponse parses an HTTP response from a GetWeightsTotalEpochWithResponse call +func ParseGetWeightsTotalEpochResponse(rsp *http.Response) (*GetWeightsTotalEpochResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &PostPublishProtocolResponse{ + response := &GetWeightsTotalEpochResponse{ Body: bodyBytes, HTTPResponse: rsp, } + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest struct { + Weight uint64 `json:"weight"` + } + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + return response, nil } diff --git a/api/node/client/client.go b/api/node/client/client.go index 8e7dba084d..ccb4bcc37f 100644 --- a/api/node/client/client.go +++ b/api/node/client/client.go @@ -187,7 +187,7 @@ func (s *NodeService) HareRoundTemplate( } func (s *NodeService) TotalWeight(ctx context.Context, epoch types.EpochID) (uint64, error) { - resp, err := s.client.GetHareTotalWeightEpochWithResponse(ctx, epoch.Uint32()) + resp, err := s.client.GetWeightsTotalEpochWithResponse(ctx, epoch.Uint32()) if err != nil { return 0, fmt.Errorf("get total weight: %w", err) } @@ -200,7 +200,7 @@ func (s *NodeService) TotalWeight(ctx context.Context, epoch types.EpochID) (uin } func (s *NodeService) MinerWeight(ctx context.Context, epoch types.EpochID, node types.NodeID) (uint64, error) { - resp, err := s.client.GetHareWeightNodeIdEpochWithResponse(ctx, hex.EncodeToString(node.Bytes()), epoch.Uint32()) + resp, err := s.client.GetWeightsMinerNodeIdEpochWithResponse(ctx, hex.EncodeToString(node.Bytes()), epoch.Uint32()) if err != nil { return 0, fmt.Errorf("get miner weight: %w", err) } @@ -213,7 +213,7 @@ func (s *NodeService) MinerWeight(ctx context.Context, epoch types.EpochID, node } func (s *NodeService) Beacon(ctx context.Context, epoch types.EpochID) (types.Beacon, error) { - resp, err := s.client.GetHareBeaconEpochWithResponse(ctx, epoch.Uint32()) + resp, err := s.client.GetBeaconEpochWithResponse(ctx, epoch.Uint32()) if err != nil { return types.Beacon{}, fmt.Errorf("get hare beacon: %w", err) } diff --git a/api/node/client/client_e2e_test.go b/api/node/client/client_e2e_test.go index 3c063607c7..f25b569e0f 100644 --- a/api/node/client/client_e2e_test.go +++ b/api/node/client/client_e2e_test.go @@ -28,6 +28,7 @@ type mocks struct { beacons *server.MockbeaconService poetDb *server.MockpoetDB hare *server.Mockhare + weights *server.Mockweights publisher *pubsubMocks.MockPublisher proposals *server.MockproposalBuilder } @@ -41,6 +42,7 @@ func setupE2E(t *testing.T) (*client.NodeService, *mocks) { beacons: server.NewMockbeaconService(ctrl), poetDb: server.NewMockpoetDB(ctrl), hare: server.NewMockhare(ctrl), + weights: server.NewMockweights(ctrl), publisher: pubsubMocks.NewMockPublisher(ctrl), proposals: server.NewMockproposalBuilder(ctrl), } @@ -50,6 +52,7 @@ func setupE2E(t *testing.T) (*client.NodeService, *mocks) { m.publisher, m.poetDb, m.hare, + m.weights, m.proposals, log.Named("server")) @@ -204,15 +207,16 @@ func Test_Hare(t *testing.T) { svc, mock := setupE2E(t) t.Run("total weight", func(t *testing.T) { val := uint64(11) - mock.hare.EXPECT().TotalWeight(gomock.Any(), types.EpochID(112)).Return(val, nil) + mock.weights.EXPECT().TotalWeight(gomock.Any(), types.EpochID(112)).Return(val, nil) v, err := svc.TotalWeight(context.Background(), 112) require.NoError(t, err) require.Equal(t, v, val) }) t.Run("miner weight", func(t *testing.T) { val := uint64(101) - mock.hare.EXPECT().MinerWeight(gomock.Any(), gomock.Any(), types.EpochID(113)).Return(val, nil) - v, err := svc.MinerWeight(context.Background(), 113, types.NodeID{}) + nodeID := types.RandomNodeID() + mock.weights.EXPECT().MinerWeight(gomock.Any(), types.EpochID(113), nodeID).Return(val, nil) + v, err := svc.MinerWeight(context.Background(), 113, nodeID) require.NoError(t, err) require.Equal(t, v, val) }) diff --git a/api/node/node_service.yaml b/api/node/node_service.yaml index 3cfb9127ef..60b7c7f296 100644 --- a/api/node/node_service.yaml +++ b/api/node/node_service.yaml @@ -167,11 +167,11 @@ paths: $ref: "models/components.yaml#/components/schemas/HareRoundTemplate" "204": description: did not find a message to retrieve - /hare/total_weight/{epoch}: + /weights/total/{epoch}: get: summary: Get the total weight for epoch tags: - - "hare" + - "weights" parameters: - in: path name: epoch @@ -191,13 +191,11 @@ paths: format: uint64 required: - weight - "204": - description: did not find a message to retrieve - /hare/weight/{node_id}/{epoch}: + /weights/miner/{node_id}/{epoch}: get: summary: Get the miner weight in epoch tags: - - "hare" + - "weights" parameters: - in: path name: node_id @@ -222,19 +220,17 @@ paths: format: uint64 required: - weight - "204": - description: did not find a message to retrieve "400": description: Bad request content: plain/text: schema: type: string - /hare/beacon/{epoch}: + /beacon/{epoch}: get: summary: Get the beacon value for an epoch tags: - - "hare" + - "beacon" parameters: - in: path name: epoch diff --git a/api/node/server/mocks.go b/api/node/server/mocks.go index 199d3079e7..68342a7331 100644 --- a/api/node/server/mocks.go +++ b/api/node/server/mocks.go @@ -167,85 +167,109 @@ func (m *Mockhare) EXPECT() *MockhareMockRecorder { return m.recorder } -// MinerWeight mocks base method. -func (m *Mockhare) MinerWeight(ctx context.Context, node types.NodeID, epoch types.EpochID) (uint64, error) { +// RoundTemplate mocks base method. +func (m *Mockhare) RoundTemplate(layer types.LayerID, round hare3.IterRound) *hare3.Body { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "MinerWeight", ctx, node, epoch) - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret := m.ctrl.Call(m, "RoundTemplate", layer, round) + ret0, _ := ret[0].(*hare3.Body) + return ret0 } -// MinerWeight indicates an expected call of MinerWeight. -func (mr *MockhareMockRecorder) MinerWeight(ctx, node, epoch any) *MockhareMinerWeightCall { +// RoundTemplate indicates an expected call of RoundTemplate. +func (mr *MockhareMockRecorder) RoundTemplate(layer, round any) *MockhareRoundTemplateCall { mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MinerWeight", reflect.TypeOf((*Mockhare)(nil).MinerWeight), ctx, node, epoch) - return &MockhareMinerWeightCall{Call: call} + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RoundTemplate", reflect.TypeOf((*Mockhare)(nil).RoundTemplate), layer, round) + return &MockhareRoundTemplateCall{Call: call} } -// MockhareMinerWeightCall wrap *gomock.Call -type MockhareMinerWeightCall struct { +// MockhareRoundTemplateCall wrap *gomock.Call +type MockhareRoundTemplateCall struct { *gomock.Call } // Return rewrite *gomock.Call.Return -func (c *MockhareMinerWeightCall) Return(arg0 uint64, arg1 error) *MockhareMinerWeightCall { - c.Call = c.Call.Return(arg0, arg1) +func (c *MockhareRoundTemplateCall) Return(arg0 *hare3.Body) *MockhareRoundTemplateCall { + c.Call = c.Call.Return(arg0) return c } // Do rewrite *gomock.Call.Do -func (c *MockhareMinerWeightCall) Do(f func(context.Context, types.NodeID, types.EpochID) (uint64, error)) *MockhareMinerWeightCall { +func (c *MockhareRoundTemplateCall) Do(f func(types.LayerID, hare3.IterRound) *hare3.Body) *MockhareRoundTemplateCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockhareMinerWeightCall) DoAndReturn(f func(context.Context, types.NodeID, types.EpochID) (uint64, error)) *MockhareMinerWeightCall { +func (c *MockhareRoundTemplateCall) DoAndReturn(f func(types.LayerID, hare3.IterRound) *hare3.Body) *MockhareRoundTemplateCall { c.Call = c.Call.DoAndReturn(f) return c } -// RoundTemplate mocks base method. -func (m *Mockhare) RoundTemplate(layer types.LayerID, round hare3.IterRound) *hare3.Body { +// Mockweights is a mock of weights interface. +type Mockweights struct { + ctrl *gomock.Controller + recorder *MockweightsMockRecorder + isgomock struct{} +} + +// MockweightsMockRecorder is the mock recorder for Mockweights. +type MockweightsMockRecorder struct { + mock *Mockweights +} + +// NewMockweights creates a new mock instance. +func NewMockweights(ctrl *gomock.Controller) *Mockweights { + mock := &Mockweights{ctrl: ctrl} + mock.recorder = &MockweightsMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *Mockweights) EXPECT() *MockweightsMockRecorder { + return m.recorder +} + +// MinerWeight mocks base method. +func (m *Mockweights) MinerWeight(ctx context.Context, epoch types.EpochID, node types.NodeID) (uint64, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RoundTemplate", layer, round) - ret0, _ := ret[0].(*hare3.Body) - return ret0 + ret := m.ctrl.Call(m, "MinerWeight", ctx, epoch, node) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 } -// RoundTemplate indicates an expected call of RoundTemplate. -func (mr *MockhareMockRecorder) RoundTemplate(layer, round any) *MockhareRoundTemplateCall { +// MinerWeight indicates an expected call of MinerWeight. +func (mr *MockweightsMockRecorder) MinerWeight(ctx, epoch, node any) *MockweightsMinerWeightCall { mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RoundTemplate", reflect.TypeOf((*Mockhare)(nil).RoundTemplate), layer, round) - return &MockhareRoundTemplateCall{Call: call} + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MinerWeight", reflect.TypeOf((*Mockweights)(nil).MinerWeight), ctx, epoch, node) + return &MockweightsMinerWeightCall{Call: call} } -// MockhareRoundTemplateCall wrap *gomock.Call -type MockhareRoundTemplateCall struct { +// MockweightsMinerWeightCall wrap *gomock.Call +type MockweightsMinerWeightCall struct { *gomock.Call } // Return rewrite *gomock.Call.Return -func (c *MockhareRoundTemplateCall) Return(arg0 *hare3.Body) *MockhareRoundTemplateCall { - c.Call = c.Call.Return(arg0) +func (c *MockweightsMinerWeightCall) Return(arg0 uint64, arg1 error) *MockweightsMinerWeightCall { + c.Call = c.Call.Return(arg0, arg1) return c } // Do rewrite *gomock.Call.Do -func (c *MockhareRoundTemplateCall) Do(f func(types.LayerID, hare3.IterRound) *hare3.Body) *MockhareRoundTemplateCall { +func (c *MockweightsMinerWeightCall) Do(f func(context.Context, types.EpochID, types.NodeID) (uint64, error)) *MockweightsMinerWeightCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockhareRoundTemplateCall) DoAndReturn(f func(types.LayerID, hare3.IterRound) *hare3.Body) *MockhareRoundTemplateCall { +func (c *MockweightsMinerWeightCall) DoAndReturn(f func(context.Context, types.EpochID, types.NodeID) (uint64, error)) *MockweightsMinerWeightCall { c.Call = c.Call.DoAndReturn(f) return c } // TotalWeight mocks base method. -func (m *Mockhare) TotalWeight(ctx context.Context, epoch types.EpochID) (uint64, error) { +func (m *Mockweights) TotalWeight(ctx context.Context, epoch types.EpochID) (uint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "TotalWeight", ctx, epoch) ret0, _ := ret[0].(uint64) @@ -254,31 +278,31 @@ func (m *Mockhare) TotalWeight(ctx context.Context, epoch types.EpochID) (uint64 } // TotalWeight indicates an expected call of TotalWeight. -func (mr *MockhareMockRecorder) TotalWeight(ctx, epoch any) *MockhareTotalWeightCall { +func (mr *MockweightsMockRecorder) TotalWeight(ctx, epoch any) *MockweightsTotalWeightCall { mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TotalWeight", reflect.TypeOf((*Mockhare)(nil).TotalWeight), ctx, epoch) - return &MockhareTotalWeightCall{Call: call} + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TotalWeight", reflect.TypeOf((*Mockweights)(nil).TotalWeight), ctx, epoch) + return &MockweightsTotalWeightCall{Call: call} } -// MockhareTotalWeightCall wrap *gomock.Call -type MockhareTotalWeightCall struct { +// MockweightsTotalWeightCall wrap *gomock.Call +type MockweightsTotalWeightCall struct { *gomock.Call } // Return rewrite *gomock.Call.Return -func (c *MockhareTotalWeightCall) Return(arg0 uint64, arg1 error) *MockhareTotalWeightCall { +func (c *MockweightsTotalWeightCall) Return(arg0 uint64, arg1 error) *MockweightsTotalWeightCall { c.Call = c.Call.Return(arg0, arg1) return c } // Do rewrite *gomock.Call.Do -func (c *MockhareTotalWeightCall) Do(f func(context.Context, types.EpochID) (uint64, error)) *MockhareTotalWeightCall { +func (c *MockweightsTotalWeightCall) Do(f func(context.Context, types.EpochID) (uint64, error)) *MockweightsTotalWeightCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockhareTotalWeightCall) DoAndReturn(f func(context.Context, types.EpochID) (uint64, error)) *MockhareTotalWeightCall { +func (c *MockweightsTotalWeightCall) DoAndReturn(f func(context.Context, types.EpochID) (uint64, error)) *MockweightsTotalWeightCall { c.Call = c.Call.DoAndReturn(f) return c } diff --git a/api/node/server/server.gen.go b/api/node/server/server.gen.go index e7cb2a9ac5..ec42639029 100644 --- a/api/node/server/server.gen.go +++ b/api/node/server/server.gen.go @@ -57,27 +57,27 @@ type ServerInterface interface { // Publish an ATX along with its poet merkle proof // (POST /activation/publish) PostActivationPublish(w http.ResponseWriter, r *http.Request) + // Get the beacon value for an epoch + // (GET /beacon/{epoch}) + GetBeaconEpoch(w http.ResponseWriter, r *http.Request, epoch externalRef0.EpochID) // Get eligibility slots for a given node id in given epoch // (GET /eligibility/slots/{node}/{epoch}) GetEligibilitySlotsNodeEpoch(w http.ResponseWriter, r *http.Request, node externalRef0.Bytes32Hex, epoch externalRef0.EpochID) - // Get the beacon value for an epoch - // (GET /hare/beacon/{epoch}) - GetHareBeaconEpoch(w http.ResponseWriter, r *http.Request, epoch externalRef0.EpochID) // Get a hare message to sign // (GET /hare/round_template/{layer}/{iter}/{round}) GetHareRoundTemplateLayerIterRound(w http.ResponseWriter, r *http.Request, layer externalRef0.LayerID, iter externalRef0.HareIter, round externalRef0.HareRound) - // Get the total weight for epoch - // (GET /hare/total_weight/{epoch}) - GetHareTotalWeightEpoch(w http.ResponseWriter, r *http.Request, epoch externalRef0.EpochID) - // Get the miner weight in epoch - // (GET /hare/weight/{node_id}/{epoch}) - GetHareWeightNodeIdEpoch(w http.ResponseWriter, r *http.Request, nodeId externalRef0.Bytes32Hex, epoch externalRef0.EpochID) // Get a partial proposal for a given node in a layer // (GET /proposal/{layer}/{node}) GetProposalLayerNode(w http.ResponseWriter, r *http.Request, layer externalRef0.LayerID, node externalRef0.Bytes32Hex) // Publish a blob in the given p2p protocol // (POST /publish/{protocol}) PostPublishProtocol(w http.ResponseWriter, r *http.Request, protocol PostPublishProtocolParamsProtocol) + // Get the miner weight in epoch + // (GET /weights/miner/{node_id}/{epoch}) + GetWeightsMinerNodeIdEpoch(w http.ResponseWriter, r *http.Request, nodeId externalRef0.Bytes32Hex, epoch externalRef0.EpochID) + // Get the total weight for epoch + // (GET /weights/total/{epoch}) + GetWeightsTotalEpoch(w http.ResponseWriter, r *http.Request, epoch externalRef0.EpochID) } // ServerInterfaceWrapper converts contexts to parameters. @@ -178,20 +178,11 @@ func (siw *ServerInterfaceWrapper) PostActivationPublish(w http.ResponseWriter, handler.ServeHTTP(w, r) } -// GetEligibilitySlotsNodeEpoch operation middleware -func (siw *ServerInterfaceWrapper) GetEligibilitySlotsNodeEpoch(w http.ResponseWriter, r *http.Request) { +// GetBeaconEpoch operation middleware +func (siw *ServerInterfaceWrapper) GetBeaconEpoch(w http.ResponseWriter, r *http.Request) { var err error - // ------------- Path parameter "node" ------------- - var node externalRef0.Bytes32Hex - - err = runtime.BindStyledParameterWithOptions("simple", "node", r.PathValue("node"), &node, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) - if err != nil { - siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "node", Err: err}) - return - } - // ------------- Path parameter "epoch" ------------- var epoch externalRef0.EpochID @@ -202,7 +193,7 @@ func (siw *ServerInterfaceWrapper) GetEligibilitySlotsNodeEpoch(w http.ResponseW } handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.GetEligibilitySlotsNodeEpoch(w, r, node, epoch) + siw.Handler.GetBeaconEpoch(w, r, epoch) })) for _, middleware := range siw.HandlerMiddlewares { @@ -212,11 +203,20 @@ func (siw *ServerInterfaceWrapper) GetEligibilitySlotsNodeEpoch(w http.ResponseW handler.ServeHTTP(w, r) } -// GetHareBeaconEpoch operation middleware -func (siw *ServerInterfaceWrapper) GetHareBeaconEpoch(w http.ResponseWriter, r *http.Request) { +// GetEligibilitySlotsNodeEpoch operation middleware +func (siw *ServerInterfaceWrapper) GetEligibilitySlotsNodeEpoch(w http.ResponseWriter, r *http.Request) { var err error + // ------------- Path parameter "node" ------------- + var node externalRef0.Bytes32Hex + + err = runtime.BindStyledParameterWithOptions("simple", "node", r.PathValue("node"), &node, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "node", Err: err}) + return + } + // ------------- Path parameter "epoch" ------------- var epoch externalRef0.EpochID @@ -227,7 +227,7 @@ func (siw *ServerInterfaceWrapper) GetHareBeaconEpoch(w http.ResponseWriter, r * } handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.GetHareBeaconEpoch(w, r, epoch) + siw.Handler.GetEligibilitySlotsNodeEpoch(w, r, node, epoch) })) for _, middleware := range siw.HandlerMiddlewares { @@ -280,22 +280,31 @@ func (siw *ServerInterfaceWrapper) GetHareRoundTemplateLayerIterRound(w http.Res handler.ServeHTTP(w, r) } -// GetHareTotalWeightEpoch operation middleware -func (siw *ServerInterfaceWrapper) GetHareTotalWeightEpoch(w http.ResponseWriter, r *http.Request) { +// GetProposalLayerNode operation middleware +func (siw *ServerInterfaceWrapper) GetProposalLayerNode(w http.ResponseWriter, r *http.Request) { var err error - // ------------- Path parameter "epoch" ------------- - var epoch externalRef0.EpochID + // ------------- Path parameter "layer" ------------- + var layer externalRef0.LayerID - err = runtime.BindStyledParameterWithOptions("simple", "epoch", r.PathValue("epoch"), &epoch, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "layer", r.PathValue("layer"), &layer, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) if err != nil { - siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "epoch", Err: err}) + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "layer", Err: err}) + return + } + + // ------------- Path parameter "node" ------------- + var node externalRef0.Bytes32Hex + + err = runtime.BindStyledParameterWithOptions("simple", "node", r.PathValue("node"), &node, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + if err != nil { + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "node", Err: err}) return } handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.GetHareTotalWeightEpoch(w, r, epoch) + siw.Handler.GetProposalLayerNode(w, r, layer, node) })) for _, middleware := range siw.HandlerMiddlewares { @@ -305,31 +314,22 @@ func (siw *ServerInterfaceWrapper) GetHareTotalWeightEpoch(w http.ResponseWriter handler.ServeHTTP(w, r) } -// GetHareWeightNodeIdEpoch operation middleware -func (siw *ServerInterfaceWrapper) GetHareWeightNodeIdEpoch(w http.ResponseWriter, r *http.Request) { +// PostPublishProtocol operation middleware +func (siw *ServerInterfaceWrapper) PostPublishProtocol(w http.ResponseWriter, r *http.Request) { var err error - // ------------- Path parameter "node_id" ------------- - var nodeId externalRef0.Bytes32Hex - - err = runtime.BindStyledParameterWithOptions("simple", "node_id", r.PathValue("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) - if err != nil { - siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "node_id", Err: err}) - return - } - - // ------------- Path parameter "epoch" ------------- - var epoch externalRef0.EpochID + // ------------- Path parameter "protocol" ------------- + var protocol PostPublishProtocolParamsProtocol - err = runtime.BindStyledParameterWithOptions("simple", "epoch", r.PathValue("epoch"), &epoch, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "protocol", r.PathValue("protocol"), &protocol, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) if err != nil { - siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "epoch", Err: err}) + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "protocol", Err: err}) return } handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.GetHareWeightNodeIdEpoch(w, r, nodeId, epoch) + siw.Handler.PostPublishProtocol(w, r, protocol) })) for _, middleware := range siw.HandlerMiddlewares { @@ -339,31 +339,31 @@ func (siw *ServerInterfaceWrapper) GetHareWeightNodeIdEpoch(w http.ResponseWrite handler.ServeHTTP(w, r) } -// GetProposalLayerNode operation middleware -func (siw *ServerInterfaceWrapper) GetProposalLayerNode(w http.ResponseWriter, r *http.Request) { +// GetWeightsMinerNodeIdEpoch operation middleware +func (siw *ServerInterfaceWrapper) GetWeightsMinerNodeIdEpoch(w http.ResponseWriter, r *http.Request) { var err error - // ------------- Path parameter "layer" ------------- - var layer externalRef0.LayerID + // ------------- Path parameter "node_id" ------------- + var nodeId externalRef0.Bytes32Hex - err = runtime.BindStyledParameterWithOptions("simple", "layer", r.PathValue("layer"), &layer, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "node_id", r.PathValue("node_id"), &nodeId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) if err != nil { - siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "layer", Err: err}) + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "node_id", Err: err}) return } - // ------------- Path parameter "node" ------------- - var node externalRef0.Bytes32Hex + // ------------- Path parameter "epoch" ------------- + var epoch externalRef0.EpochID - err = runtime.BindStyledParameterWithOptions("simple", "node", r.PathValue("node"), &node, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "epoch", r.PathValue("epoch"), &epoch, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) if err != nil { - siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "node", Err: err}) + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "epoch", Err: err}) return } handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.GetProposalLayerNode(w, r, layer, node) + siw.Handler.GetWeightsMinerNodeIdEpoch(w, r, nodeId, epoch) })) for _, middleware := range siw.HandlerMiddlewares { @@ -373,22 +373,22 @@ func (siw *ServerInterfaceWrapper) GetProposalLayerNode(w http.ResponseWriter, r handler.ServeHTTP(w, r) } -// PostPublishProtocol operation middleware -func (siw *ServerInterfaceWrapper) PostPublishProtocol(w http.ResponseWriter, r *http.Request) { +// GetWeightsTotalEpoch operation middleware +func (siw *ServerInterfaceWrapper) GetWeightsTotalEpoch(w http.ResponseWriter, r *http.Request) { var err error - // ------------- Path parameter "protocol" ------------- - var protocol PostPublishProtocolParamsProtocol + // ------------- Path parameter "epoch" ------------- + var epoch externalRef0.EpochID - err = runtime.BindStyledParameterWithOptions("simple", "protocol", r.PathValue("protocol"), &protocol, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) + err = runtime.BindStyledParameterWithOptions("simple", "epoch", r.PathValue("epoch"), &epoch, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true}) if err != nil { - siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "protocol", Err: err}) + siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "epoch", Err: err}) return } handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - siw.Handler.PostPublishProtocol(w, r, protocol) + siw.Handler.GetWeightsTotalEpoch(w, r, epoch) })) for _, middleware := range siw.HandlerMiddlewares { @@ -522,13 +522,13 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H m.HandleFunc("GET "+options.BaseURL+"/activation/last_atx/{node_id}", wrapper.GetActivationLastAtxNodeId) m.HandleFunc("GET "+options.BaseURL+"/activation/positioning_atx/{publish_epoch}", wrapper.GetActivationPositioningAtxPublishEpoch) m.HandleFunc("POST "+options.BaseURL+"/activation/publish", wrapper.PostActivationPublish) + m.HandleFunc("GET "+options.BaseURL+"/beacon/{epoch}", wrapper.GetBeaconEpoch) m.HandleFunc("GET "+options.BaseURL+"/eligibility/slots/{node}/{epoch}", wrapper.GetEligibilitySlotsNodeEpoch) - m.HandleFunc("GET "+options.BaseURL+"/hare/beacon/{epoch}", wrapper.GetHareBeaconEpoch) m.HandleFunc("GET "+options.BaseURL+"/hare/round_template/{layer}/{iter}/{round}", wrapper.GetHareRoundTemplateLayerIterRound) - m.HandleFunc("GET "+options.BaseURL+"/hare/total_weight/{epoch}", wrapper.GetHareTotalWeightEpoch) - m.HandleFunc("GET "+options.BaseURL+"/hare/weight/{node_id}/{epoch}", wrapper.GetHareWeightNodeIdEpoch) m.HandleFunc("GET "+options.BaseURL+"/proposal/{layer}/{node}", wrapper.GetProposalLayerNode) m.HandleFunc("POST "+options.BaseURL+"/publish/{protocol}", wrapper.PostPublishProtocol) + m.HandleFunc("GET "+options.BaseURL+"/weights/miner/{node_id}/{epoch}", wrapper.GetWeightsMinerNodeIdEpoch) + m.HandleFunc("GET "+options.BaseURL+"/weights/total/{epoch}", wrapper.GetWeightsTotalEpoch) return m } @@ -675,6 +675,33 @@ func (response PostActivationPublish400PlaintextResponse) VisitPostActivationPub return err } +type GetBeaconEpochRequestObject struct { + Epoch externalRef0.EpochID `json:"epoch"` +} + +type GetBeaconEpochResponseObject interface { + VisitGetBeaconEpochResponse(w http.ResponseWriter) error +} + +type GetBeaconEpoch200JSONResponse struct { + Beacon externalRef0.Beacon `json:"beacon"` +} + +func (response GetBeaconEpoch200JSONResponse) VisitGetBeaconEpochResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +type GetBeaconEpoch204Response struct { +} + +func (response GetBeaconEpoch204Response) VisitGetBeaconEpochResponse(w http.ResponseWriter) error { + w.WriteHeader(204) + return nil +} + type GetEligibilitySlotsNodeEpochRequestObject struct { Node externalRef0.Bytes32Hex `json:"node"` Epoch externalRef0.EpochID `json:"epoch"` @@ -723,33 +750,6 @@ func (response GetEligibilitySlotsNodeEpoch500Response) VisitGetEligibilitySlots return nil } -type GetHareBeaconEpochRequestObject struct { - Epoch externalRef0.EpochID `json:"epoch"` -} - -type GetHareBeaconEpochResponseObject interface { - VisitGetHareBeaconEpochResponse(w http.ResponseWriter) error -} - -type GetHareBeaconEpoch200JSONResponse struct { - Beacon externalRef0.Beacon `json:"beacon"` -} - -func (response GetHareBeaconEpoch200JSONResponse) VisitGetHareBeaconEpochResponse(w http.ResponseWriter) error { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(200) - - return json.NewEncoder(w).Encode(response) -} - -type GetHareBeaconEpoch204Response struct { -} - -func (response GetHareBeaconEpoch204Response) VisitGetHareBeaconEpochResponse(w http.ResponseWriter) error { - w.WriteHeader(204) - return nil -} - type GetHareRoundTemplateLayerIterRoundRequestObject struct { Layer externalRef0.LayerID `json:"layer"` Iter externalRef0.HareIter `json:"iter"` @@ -777,67 +777,38 @@ func (response GetHareRoundTemplateLayerIterRound204Response) VisitGetHareRoundT return nil } -type GetHareTotalWeightEpochRequestObject struct { - Epoch externalRef0.EpochID `json:"epoch"` -} - -type GetHareTotalWeightEpochResponseObject interface { - VisitGetHareTotalWeightEpochResponse(w http.ResponseWriter) error -} - -type GetHareTotalWeightEpoch200JSONResponse struct { - Weight uint64 `json:"weight"` -} - -func (response GetHareTotalWeightEpoch200JSONResponse) VisitGetHareTotalWeightEpochResponse(w http.ResponseWriter) error { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(200) - - return json.NewEncoder(w).Encode(response) -} - -type GetHareTotalWeightEpoch204Response struct { -} - -func (response GetHareTotalWeightEpoch204Response) VisitGetHareTotalWeightEpochResponse(w http.ResponseWriter) error { - w.WriteHeader(204) - return nil -} - -type GetHareWeightNodeIdEpochRequestObject struct { - NodeId externalRef0.Bytes32Hex `json:"node_id"` - Epoch externalRef0.EpochID `json:"epoch"` +type GetProposalLayerNodeRequestObject struct { + Layer externalRef0.LayerID `json:"layer"` + Node externalRef0.Bytes32Hex `json:"node"` } -type GetHareWeightNodeIdEpochResponseObject interface { - VisitGetHareWeightNodeIdEpochResponse(w http.ResponseWriter) error +type GetProposalLayerNodeResponseObject interface { + VisitGetProposalLayerNodeResponse(w http.ResponseWriter) error } -type GetHareWeightNodeIdEpoch200JSONResponse struct { - Weight uint64 `json:"weight"` -} +type GetProposalLayerNode200JSONResponse externalRef0.PartialProposal -func (response GetHareWeightNodeIdEpoch200JSONResponse) VisitGetHareWeightNodeIdEpochResponse(w http.ResponseWriter) error { +func (response GetProposalLayerNode200JSONResponse) VisitGetProposalLayerNodeResponse(w http.ResponseWriter) error { w.Header().Set("Content-Type", "application/json") w.WriteHeader(200) return json.NewEncoder(w).Encode(response) } -type GetHareWeightNodeIdEpoch204Response struct { +type GetProposalLayerNode204Response struct { } -func (response GetHareWeightNodeIdEpoch204Response) VisitGetHareWeightNodeIdEpochResponse(w http.ResponseWriter) error { +func (response GetProposalLayerNode204Response) VisitGetProposalLayerNodeResponse(w http.ResponseWriter) error { w.WriteHeader(204) return nil } -type GetHareWeightNodeIdEpoch400PlaintextResponse struct { +type GetProposalLayerNode400PlaintextResponse struct { Body io.Reader ContentLength int64 } -func (response GetHareWeightNodeIdEpoch400PlaintextResponse) VisitGetHareWeightNodeIdEpochResponse(w http.ResponseWriter) error { +func (response GetProposalLayerNode400PlaintextResponse) VisitGetProposalLayerNodeResponse(w http.ResponseWriter) error { w.Header().Set("Content-Type", "plain/text") if response.ContentLength != 0 { w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength)) @@ -851,38 +822,57 @@ func (response GetHareWeightNodeIdEpoch400PlaintextResponse) VisitGetHareWeightN return err } -type GetProposalLayerNodeRequestObject struct { - Layer externalRef0.LayerID `json:"layer"` - Node externalRef0.Bytes32Hex `json:"node"` +type GetProposalLayerNode500Response struct { } -type GetProposalLayerNodeResponseObject interface { - VisitGetProposalLayerNodeResponse(w http.ResponseWriter) error +func (response GetProposalLayerNode500Response) VisitGetProposalLayerNodeResponse(w http.ResponseWriter) error { + w.WriteHeader(500) + return nil } -type GetProposalLayerNode200JSONResponse externalRef0.PartialProposal +type PostPublishProtocolRequestObject struct { + Protocol PostPublishProtocolParamsProtocol `json:"protocol"` + Body io.Reader +} -func (response GetProposalLayerNode200JSONResponse) VisitGetProposalLayerNodeResponse(w http.ResponseWriter) error { - w.Header().Set("Content-Type", "application/json") +type PostPublishProtocolResponseObject interface { + VisitPostPublishProtocolResponse(w http.ResponseWriter) error +} + +type PostPublishProtocol200Response struct { +} + +func (response PostPublishProtocol200Response) VisitPostPublishProtocolResponse(w http.ResponseWriter) error { w.WriteHeader(200) + return nil +} - return json.NewEncoder(w).Encode(response) +type GetWeightsMinerNodeIdEpochRequestObject struct { + NodeId externalRef0.Bytes32Hex `json:"node_id"` + Epoch externalRef0.EpochID `json:"epoch"` } -type GetProposalLayerNode204Response struct { +type GetWeightsMinerNodeIdEpochResponseObject interface { + VisitGetWeightsMinerNodeIdEpochResponse(w http.ResponseWriter) error } -func (response GetProposalLayerNode204Response) VisitGetProposalLayerNodeResponse(w http.ResponseWriter) error { - w.WriteHeader(204) - return nil +type GetWeightsMinerNodeIdEpoch200JSONResponse struct { + Weight uint64 `json:"weight"` } -type GetProposalLayerNode400PlaintextResponse struct { +func (response GetWeightsMinerNodeIdEpoch200JSONResponse) VisitGetWeightsMinerNodeIdEpochResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(200) + + return json.NewEncoder(w).Encode(response) +} + +type GetWeightsMinerNodeIdEpoch400PlaintextResponse struct { Body io.Reader ContentLength int64 } -func (response GetProposalLayerNode400PlaintextResponse) VisitGetProposalLayerNodeResponse(w http.ResponseWriter) error { +func (response GetWeightsMinerNodeIdEpoch400PlaintextResponse) VisitGetWeightsMinerNodeIdEpochResponse(w http.ResponseWriter) error { w.Header().Set("Content-Type", "plain/text") if response.ContentLength != 0 { w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength)) @@ -896,29 +886,23 @@ func (response GetProposalLayerNode400PlaintextResponse) VisitGetProposalLayerNo return err } -type GetProposalLayerNode500Response struct { -} - -func (response GetProposalLayerNode500Response) VisitGetProposalLayerNodeResponse(w http.ResponseWriter) error { - w.WriteHeader(500) - return nil -} - -type PostPublishProtocolRequestObject struct { - Protocol PostPublishProtocolParamsProtocol `json:"protocol"` - Body io.Reader +type GetWeightsTotalEpochRequestObject struct { + Epoch externalRef0.EpochID `json:"epoch"` } -type PostPublishProtocolResponseObject interface { - VisitPostPublishProtocolResponse(w http.ResponseWriter) error +type GetWeightsTotalEpochResponseObject interface { + VisitGetWeightsTotalEpochResponse(w http.ResponseWriter) error } -type PostPublishProtocol200Response struct { +type GetWeightsTotalEpoch200JSONResponse struct { + Weight uint64 `json:"weight"` } -func (response PostPublishProtocol200Response) VisitPostPublishProtocolResponse(w http.ResponseWriter) error { +func (response GetWeightsTotalEpoch200JSONResponse) VisitGetWeightsTotalEpochResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json") w.WriteHeader(200) - return nil + + return json.NewEncoder(w).Encode(response) } // StrictServerInterface represents all server handlers. @@ -935,27 +919,27 @@ type StrictServerInterface interface { // Publish an ATX along with its poet merkle proof // (POST /activation/publish) PostActivationPublish(ctx context.Context, request PostActivationPublishRequestObject) (PostActivationPublishResponseObject, error) + // Get the beacon value for an epoch + // (GET /beacon/{epoch}) + GetBeaconEpoch(ctx context.Context, request GetBeaconEpochRequestObject) (GetBeaconEpochResponseObject, error) // Get eligibility slots for a given node id in given epoch // (GET /eligibility/slots/{node}/{epoch}) GetEligibilitySlotsNodeEpoch(ctx context.Context, request GetEligibilitySlotsNodeEpochRequestObject) (GetEligibilitySlotsNodeEpochResponseObject, error) - // Get the beacon value for an epoch - // (GET /hare/beacon/{epoch}) - GetHareBeaconEpoch(ctx context.Context, request GetHareBeaconEpochRequestObject) (GetHareBeaconEpochResponseObject, error) // Get a hare message to sign // (GET /hare/round_template/{layer}/{iter}/{round}) GetHareRoundTemplateLayerIterRound(ctx context.Context, request GetHareRoundTemplateLayerIterRoundRequestObject) (GetHareRoundTemplateLayerIterRoundResponseObject, error) - // Get the total weight for epoch - // (GET /hare/total_weight/{epoch}) - GetHareTotalWeightEpoch(ctx context.Context, request GetHareTotalWeightEpochRequestObject) (GetHareTotalWeightEpochResponseObject, error) - // Get the miner weight in epoch - // (GET /hare/weight/{node_id}/{epoch}) - GetHareWeightNodeIdEpoch(ctx context.Context, request GetHareWeightNodeIdEpochRequestObject) (GetHareWeightNodeIdEpochResponseObject, error) // Get a partial proposal for a given node in a layer // (GET /proposal/{layer}/{node}) GetProposalLayerNode(ctx context.Context, request GetProposalLayerNodeRequestObject) (GetProposalLayerNodeResponseObject, error) // Publish a blob in the given p2p protocol // (POST /publish/{protocol}) PostPublishProtocol(ctx context.Context, request PostPublishProtocolRequestObject) (PostPublishProtocolResponseObject, error) + // Get the miner weight in epoch + // (GET /weights/miner/{node_id}/{epoch}) + GetWeightsMinerNodeIdEpoch(ctx context.Context, request GetWeightsMinerNodeIdEpochRequestObject) (GetWeightsMinerNodeIdEpochResponseObject, error) + // Get the total weight for epoch + // (GET /weights/total/{epoch}) + GetWeightsTotalEpoch(ctx context.Context, request GetWeightsTotalEpochRequestObject) (GetWeightsTotalEpochResponseObject, error) } type StrictHandlerFunc = strictnethttp.StrictHTTPHandlerFunc @@ -1096,26 +1080,25 @@ func (sh *strictHandler) PostActivationPublish(w http.ResponseWriter, r *http.Re } } -// GetEligibilitySlotsNodeEpoch operation middleware -func (sh *strictHandler) GetEligibilitySlotsNodeEpoch(w http.ResponseWriter, r *http.Request, node externalRef0.Bytes32Hex, epoch externalRef0.EpochID) { - var request GetEligibilitySlotsNodeEpochRequestObject +// GetBeaconEpoch operation middleware +func (sh *strictHandler) GetBeaconEpoch(w http.ResponseWriter, r *http.Request, epoch externalRef0.EpochID) { + var request GetBeaconEpochRequestObject - request.Node = node request.Epoch = epoch handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { - return sh.ssi.GetEligibilitySlotsNodeEpoch(ctx, request.(GetEligibilitySlotsNodeEpochRequestObject)) + return sh.ssi.GetBeaconEpoch(ctx, request.(GetBeaconEpochRequestObject)) } for _, middleware := range sh.middlewares { - handler = middleware(handler, "GetEligibilitySlotsNodeEpoch") + handler = middleware(handler, "GetBeaconEpoch") } response, err := handler(r.Context(), w, r, request) if err != nil { sh.options.ResponseErrorHandlerFunc(w, r, err) - } else if validResponse, ok := response.(GetEligibilitySlotsNodeEpochResponseObject); ok { - if err := validResponse.VisitGetEligibilitySlotsNodeEpochResponse(w); err != nil { + } else if validResponse, ok := response.(GetBeaconEpochResponseObject); ok { + if err := validResponse.VisitGetBeaconEpochResponse(w); err != nil { sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { @@ -1123,25 +1106,26 @@ func (sh *strictHandler) GetEligibilitySlotsNodeEpoch(w http.ResponseWriter, r * } } -// GetHareBeaconEpoch operation middleware -func (sh *strictHandler) GetHareBeaconEpoch(w http.ResponseWriter, r *http.Request, epoch externalRef0.EpochID) { - var request GetHareBeaconEpochRequestObject +// GetEligibilitySlotsNodeEpoch operation middleware +func (sh *strictHandler) GetEligibilitySlotsNodeEpoch(w http.ResponseWriter, r *http.Request, node externalRef0.Bytes32Hex, epoch externalRef0.EpochID) { + var request GetEligibilitySlotsNodeEpochRequestObject + request.Node = node request.Epoch = epoch handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { - return sh.ssi.GetHareBeaconEpoch(ctx, request.(GetHareBeaconEpochRequestObject)) + return sh.ssi.GetEligibilitySlotsNodeEpoch(ctx, request.(GetEligibilitySlotsNodeEpochRequestObject)) } for _, middleware := range sh.middlewares { - handler = middleware(handler, "GetHareBeaconEpoch") + handler = middleware(handler, "GetEligibilitySlotsNodeEpoch") } response, err := handler(r.Context(), w, r, request) if err != nil { sh.options.ResponseErrorHandlerFunc(w, r, err) - } else if validResponse, ok := response.(GetHareBeaconEpochResponseObject); ok { - if err := validResponse.VisitGetHareBeaconEpochResponse(w); err != nil { + } else if validResponse, ok := response.(GetEligibilitySlotsNodeEpochResponseObject); ok { + if err := validResponse.VisitGetEligibilitySlotsNodeEpochResponse(w); err != nil { sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { @@ -1177,25 +1161,26 @@ func (sh *strictHandler) GetHareRoundTemplateLayerIterRound(w http.ResponseWrite } } -// GetHareTotalWeightEpoch operation middleware -func (sh *strictHandler) GetHareTotalWeightEpoch(w http.ResponseWriter, r *http.Request, epoch externalRef0.EpochID) { - var request GetHareTotalWeightEpochRequestObject +// GetProposalLayerNode operation middleware +func (sh *strictHandler) GetProposalLayerNode(w http.ResponseWriter, r *http.Request, layer externalRef0.LayerID, node externalRef0.Bytes32Hex) { + var request GetProposalLayerNodeRequestObject - request.Epoch = epoch + request.Layer = layer + request.Node = node handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { - return sh.ssi.GetHareTotalWeightEpoch(ctx, request.(GetHareTotalWeightEpochRequestObject)) + return sh.ssi.GetProposalLayerNode(ctx, request.(GetProposalLayerNodeRequestObject)) } for _, middleware := range sh.middlewares { - handler = middleware(handler, "GetHareTotalWeightEpoch") + handler = middleware(handler, "GetProposalLayerNode") } response, err := handler(r.Context(), w, r, request) if err != nil { sh.options.ResponseErrorHandlerFunc(w, r, err) - } else if validResponse, ok := response.(GetHareTotalWeightEpochResponseObject); ok { - if err := validResponse.VisitGetHareTotalWeightEpochResponse(w); err != nil { + } else if validResponse, ok := response.(GetProposalLayerNodeResponseObject); ok { + if err := validResponse.VisitGetProposalLayerNodeResponse(w); err != nil { sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { @@ -1203,26 +1188,27 @@ func (sh *strictHandler) GetHareTotalWeightEpoch(w http.ResponseWriter, r *http. } } -// GetHareWeightNodeIdEpoch operation middleware -func (sh *strictHandler) GetHareWeightNodeIdEpoch(w http.ResponseWriter, r *http.Request, nodeId externalRef0.Bytes32Hex, epoch externalRef0.EpochID) { - var request GetHareWeightNodeIdEpochRequestObject +// PostPublishProtocol operation middleware +func (sh *strictHandler) PostPublishProtocol(w http.ResponseWriter, r *http.Request, protocol PostPublishProtocolParamsProtocol) { + var request PostPublishProtocolRequestObject - request.NodeId = nodeId - request.Epoch = epoch + request.Protocol = protocol + + request.Body = r.Body handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { - return sh.ssi.GetHareWeightNodeIdEpoch(ctx, request.(GetHareWeightNodeIdEpochRequestObject)) + return sh.ssi.PostPublishProtocol(ctx, request.(PostPublishProtocolRequestObject)) } for _, middleware := range sh.middlewares { - handler = middleware(handler, "GetHareWeightNodeIdEpoch") + handler = middleware(handler, "PostPublishProtocol") } response, err := handler(r.Context(), w, r, request) if err != nil { sh.options.ResponseErrorHandlerFunc(w, r, err) - } else if validResponse, ok := response.(GetHareWeightNodeIdEpochResponseObject); ok { - if err := validResponse.VisitGetHareWeightNodeIdEpochResponse(w); err != nil { + } else if validResponse, ok := response.(PostPublishProtocolResponseObject); ok { + if err := validResponse.VisitPostPublishProtocolResponse(w); err != nil { sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { @@ -1230,26 +1216,26 @@ func (sh *strictHandler) GetHareWeightNodeIdEpoch(w http.ResponseWriter, r *http } } -// GetProposalLayerNode operation middleware -func (sh *strictHandler) GetProposalLayerNode(w http.ResponseWriter, r *http.Request, layer externalRef0.LayerID, node externalRef0.Bytes32Hex) { - var request GetProposalLayerNodeRequestObject +// GetWeightsMinerNodeIdEpoch operation middleware +func (sh *strictHandler) GetWeightsMinerNodeIdEpoch(w http.ResponseWriter, r *http.Request, nodeId externalRef0.Bytes32Hex, epoch externalRef0.EpochID) { + var request GetWeightsMinerNodeIdEpochRequestObject - request.Layer = layer - request.Node = node + request.NodeId = nodeId + request.Epoch = epoch handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { - return sh.ssi.GetProposalLayerNode(ctx, request.(GetProposalLayerNodeRequestObject)) + return sh.ssi.GetWeightsMinerNodeIdEpoch(ctx, request.(GetWeightsMinerNodeIdEpochRequestObject)) } for _, middleware := range sh.middlewares { - handler = middleware(handler, "GetProposalLayerNode") + handler = middleware(handler, "GetWeightsMinerNodeIdEpoch") } response, err := handler(r.Context(), w, r, request) if err != nil { sh.options.ResponseErrorHandlerFunc(w, r, err) - } else if validResponse, ok := response.(GetProposalLayerNodeResponseObject); ok { - if err := validResponse.VisitGetProposalLayerNodeResponse(w); err != nil { + } else if validResponse, ok := response.(GetWeightsMinerNodeIdEpochResponseObject); ok { + if err := validResponse.VisitGetWeightsMinerNodeIdEpochResponse(w); err != nil { sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { @@ -1257,27 +1243,25 @@ func (sh *strictHandler) GetProposalLayerNode(w http.ResponseWriter, r *http.Req } } -// PostPublishProtocol operation middleware -func (sh *strictHandler) PostPublishProtocol(w http.ResponseWriter, r *http.Request, protocol PostPublishProtocolParamsProtocol) { - var request PostPublishProtocolRequestObject - - request.Protocol = protocol +// GetWeightsTotalEpoch operation middleware +func (sh *strictHandler) GetWeightsTotalEpoch(w http.ResponseWriter, r *http.Request, epoch externalRef0.EpochID) { + var request GetWeightsTotalEpochRequestObject - request.Body = r.Body + request.Epoch = epoch handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { - return sh.ssi.PostPublishProtocol(ctx, request.(PostPublishProtocolRequestObject)) + return sh.ssi.GetWeightsTotalEpoch(ctx, request.(GetWeightsTotalEpochRequestObject)) } for _, middleware := range sh.middlewares { - handler = middleware(handler, "PostPublishProtocol") + handler = middleware(handler, "GetWeightsTotalEpoch") } response, err := handler(r.Context(), w, r, request) if err != nil { sh.options.ResponseErrorHandlerFunc(w, r, err) - } else if validResponse, ok := response.(PostPublishProtocolResponseObject); ok { - if err := validResponse.VisitPostPublishProtocolResponse(w); err != nil { + } else if validResponse, ok := response.(GetWeightsTotalEpochResponseObject); ok { + if err := validResponse.VisitGetWeightsTotalEpochResponse(w); err != nil { sh.options.ResponseErrorHandlerFunc(w, r, err) } } else if response != nil { diff --git a/api/node/server/server.go b/api/node/server/server.go index dfaab396a5..906b470738 100644 --- a/api/node/server/server.go +++ b/api/node/server/server.go @@ -33,8 +33,11 @@ type beaconService interface { type hare interface { RoundTemplate(layer types.LayerID, round hare3.IterRound) *hare3.Body +} + +type weights interface { TotalWeight(ctx context.Context, epoch types.EpochID) (uint64, error) - MinerWeight(ctx context.Context, node types.NodeID, epoch types.EpochID) (uint64, error) + MinerWeight(ctx context.Context, epoch types.EpochID, node types.NodeID) (uint64, error) } type proposalBuilder interface { @@ -49,6 +52,7 @@ type Server struct { publisher pubsub.Publisher poetDB poetDB hare hare + weights weights proposals proposalBuilder logger *zap.Logger } @@ -61,6 +65,7 @@ func NewServer( publisher pubsub.Publisher, poetDB poetDB, hare hare, + weights weights, proposals proposalBuilder, logger *zap.Logger, ) *Server { @@ -70,6 +75,7 @@ func NewServer( publisher: publisher, poetDB: poetDB, hare: hare, + weights: weights, proposals: proposals, logger: logger, } @@ -272,45 +278,47 @@ func (s *Server) GetHareRoundTemplateLayerIterRound(ctx context.Context, return resp, nil } -func (s *Server) GetHareTotalWeightEpoch(ctx context.Context, - req GetHareTotalWeightEpochRequestObject, -) (GetHareTotalWeightEpochResponseObject, error) { - weight, err := s.hare.TotalWeight(ctx, types.EpochID(req.Epoch)) +func (s *Server) GetWeightsTotalEpoch( + ctx context.Context, + req GetWeightsTotalEpochRequestObject, +) (GetWeightsTotalEpochResponseObject, error) { + weight, err := s.weights.TotalWeight(ctx, types.EpochID(req.Epoch)) if err != nil { return nil, err } - return &GetHareTotalWeightEpoch200JSONResponse{Weight: weight}, nil + return &GetWeightsTotalEpoch200JSONResponse{Weight: weight}, nil } -func (s *Server) GetHareWeightNodeIdEpoch(ctx context.Context, - request GetHareWeightNodeIdEpochRequestObject, -) (GetHareWeightNodeIdEpochResponseObject, error) { +func (s *Server) GetWeightsMinerNodeIdEpoch(ctx context.Context, + request GetWeightsMinerNodeIdEpochRequestObject, +) (GetWeightsMinerNodeIdEpochResponseObject, error) { id, err := models.ParseNodeIDHex(request.NodeId) if err != nil { msg := err.Error() - return GetHareWeightNodeIdEpoch400PlaintextResponse{ + return GetWeightsMinerNodeIdEpoch400PlaintextResponse{ Body: bytes.NewBuffer([]byte(msg)), ContentLength: int64(len(msg)), }, nil } - weight, err := s.hare.MinerWeight(ctx, id, types.EpochID(request.Epoch)) + weight, err := s.weights.MinerWeight(ctx, types.EpochID(request.Epoch), id) if err != nil { if errors.Is(err, eligibility.ErrNotActive) { - return &GetHareWeightNodeIdEpoch200JSONResponse{Weight: 0}, nil + return &GetWeightsMinerNodeIdEpoch200JSONResponse{Weight: 0}, nil } return nil, fmt.Errorf("miner weight: %w", err) } - return &GetHareWeightNodeIdEpoch200JSONResponse{Weight: weight}, nil + return &GetWeightsMinerNodeIdEpoch200JSONResponse{Weight: weight}, nil } -func (s *Server) GetHareBeaconEpoch(ctx context.Context, - request GetHareBeaconEpochRequestObject, -) (GetHareBeaconEpochResponseObject, error) { +func (s *Server) GetBeaconEpoch( + ctx context.Context, + request GetBeaconEpochRequestObject, +) (GetBeaconEpochResponseObject, error) { beacon, err := s.beacons.Beacon(ctx, types.EpochID(request.Epoch)) if err != nil { return nil, err } - return &GetHareBeaconEpoch200JSONResponse{Beacon: beacon[:]}, nil + return &GetBeaconEpoch200JSONResponse{Beacon: beacon[:]}, nil } func (s *Server) GetProposalLayerNode(ctx context.Context, request GetProposalLayerNodeRequestObject) ( diff --git a/hare3/eligibility/active_set.go b/hare3/eligibility/active_set.go new file mode 100644 index 0000000000..38553eba45 --- /dev/null +++ b/hare3/eligibility/active_set.go @@ -0,0 +1,244 @@ +package eligibility + +import ( + "context" + "errors" + "fmt" + "sync" + + lru "github.com/hashicorp/golang-lru/v2" + "go.uber.org/zap" + "golang.org/x/exp/maps" + + "github.com/spacemeshos/go-spacemesh/atxsdata" + "github.com/spacemeshos/go-spacemesh/common/types" + "github.com/spacemeshos/go-spacemesh/log" + "github.com/spacemeshos/go-spacemesh/miner" + "github.com/spacemeshos/go-spacemesh/sql" + "github.com/spacemeshos/go-spacemesh/sql/activesets" + "github.com/spacemeshos/go-spacemesh/sql/ballots" + "github.com/spacemeshos/go-spacemesh/system" +) + +const activesCacheSize = 5 // we don't expect to handle more than two layers concurrently + +type identityWeight struct { + atx types.ATXID + weight uint64 +} +type cachedActiveSet struct { + set map[types.NodeID]identityWeight + total uint64 +} + +func (c *cachedActiveSet) atxs() []types.ATXID { + atxs := make([]types.ATXID, 0, len(c.set)) + for _, id := range c.set { + atxs = append(atxs, id.atx) + } + return atxs +} + +type ActiveSetCache struct { + mu sync.Mutex + cache *lru.Cache[types.EpochID, *cachedActiveSet] + fallback map[types.EpochID][]types.ATXID + sync system.SyncStateProvider + // NOTE(dshulyak) on switch from synced to not synced reset the cache + // to cope with https://github.com/spacemeshos/go-spacemesh/issues/4552 + // until graded oracle is implemented + synced bool + + beacons BeaconProvider + db sql.Executor + atxsdata *atxsdata.Data + log *zap.Logger +} + +func NewActiveSetCache( + beacons BeaconProvider, + db sql.Executor, + atxsdata *atxsdata.Data, + log *zap.Logger, +) (*ActiveSetCache, error) { + cache, err := lru.New[types.EpochID, *cachedActiveSet](activesCacheSize) + if err != nil { + return nil, fmt.Errorf("create lru cache for active set: %w", err) + } + return &ActiveSetCache{ + cache: cache, + fallback: make(map[types.EpochID][]types.ATXID), + beacons: beacons, + db: db, + atxsdata: atxsdata, + log: log, + }, nil +} + +func (o *ActiveSetCache) SetSync(sync system.SyncStateProvider) { + o.sync = sync +} + +func (o *ActiveSetCache) resetCacheOnSynced(ctx context.Context) { + synced := o.synced + o.synced = o.sync.IsSynced(ctx) + if !synced && o.synced { + o.cache.Purge() + } +} + +// Returns a set of all active node IDs in the specified epoch. +func (o *ActiveSetCache) actives(ctx context.Context, targetEpoch types.EpochID) (*cachedActiveSet, error) { + if !targetEpoch.FirstLayer().After(types.GetEffectiveGenesis()) { + return nil, errEmptyActiveSet + } + o.log.Debug("hare oracle getting active set", + log.ZContext(ctx), + zap.Uint32("target_epoch", targetEpoch.Uint32()), + ) + + o.mu.Lock() + defer o.mu.Unlock() + o.resetCacheOnSynced(ctx) + if value, exists := o.cache.Get(targetEpoch); exists { + return value, nil + } + activeSet, err := o.computeActiveSet(ctx, targetEpoch) + if err != nil { + return nil, err + } + if len(activeSet) == 0 { + return nil, errEmptyActiveSet + } + activeWeights, err := o.computeActiveWeights(targetEpoch, activeSet) + if err != nil { + return nil, err + } + + aset := &cachedActiveSet{set: activeWeights} + for _, aweight := range activeWeights { + aset.total += aweight.weight + } + o.log.Debug("got hare active set", log.ZContext(ctx), zap.Int("count", len(activeWeights))) + o.cache.Add(targetEpoch, aset) + return aset, nil +} + +func (o *ActiveSetCache) ActiveSet(ctx context.Context, targetEpoch types.EpochID) ([]types.ATXID, error) { + aset, err := o.actives(ctx, targetEpoch) + if err != nil { + return nil, err + } + return aset.atxs(), nil +} + +func (o *ActiveSetCache) computeActiveSet(ctx context.Context, targetEpoch types.EpochID) ([]types.ATXID, error) { + activeSet, ok := o.fallback[targetEpoch] + if ok { + o.log.Debug("using fallback active set", + log.ZContext(ctx), + zap.Uint32("target_epoch", targetEpoch.Uint32()), + zap.Int("size", len(activeSet)), + ) + return activeSet, nil + } + + activeSet, err := miner.ActiveSetFromEpochFirstBlock(o.db, targetEpoch) + if err != nil && !errors.Is(err, sql.ErrNotFound) { + return nil, err + } + if len(activeSet) == 0 { + return o.activeSetFromRefBallots(ctx, targetEpoch) + } + return activeSet, nil +} + +func (o *ActiveSetCache) computeActiveWeights( + targetEpoch types.EpochID, + activeSet []types.ATXID, +) (map[types.NodeID]identityWeight, error) { + identities := make(map[types.NodeID]identityWeight, len(activeSet)) + for _, id := range activeSet { + atx := o.atxsdata.Get(targetEpoch, id) + if atx == nil { + return nil, fmt.Errorf("oracle: missing atx in atxsdata %s/%s", targetEpoch, id.ShortString()) + } + identities[atx.Node] = identityWeight{atx: id, weight: atx.Weight} + } + return identities, nil +} + +func (o *ActiveSetCache) activeSetFromRefBallots(ctx context.Context, epoch types.EpochID) ([]types.ATXID, error) { + beacon, err := o.beacons.Beacon(ctx, epoch) + if err != nil { + return nil, fmt.Errorf("get beacon: %w", err) + } + ballotsrst, err := ballots.AllFirstInEpoch(o.db, epoch) + if err != nil { + return nil, fmt.Errorf("first in epoch %d: %w", epoch, err) + } + activeMap := make(map[types.ATXID]struct{}, len(ballotsrst)) + for _, ballot := range ballotsrst { + if ballot.EpochData == nil { + o.log.Error("invalid data. first ballot doesn't have epoch data", zap.Inline(ballot)) + continue + } + if ballot.EpochData.Beacon != beacon { + o.log.Debug("beacon mismatch", zap.Stringer("local", beacon), zap.Object("ballot", ballot)) + continue + } + actives, err := activesets.Get(o.db, ballot.EpochData.ActiveSetHash) + if err != nil { + o.log.Error("failed to get active set", + zap.String("actives hash", ballot.EpochData.ActiveSetHash.ShortString()), + zap.String("ballot ", ballot.ID().String()), + zap.Error(err), + ) + continue + } + for _, id := range actives.Set { + activeMap[id] = struct{}{} + } + } + o.log.Warn("using tortoise active set", + zap.Int("actives size", len(activeMap)), + zap.Uint32("epoch", epoch.Uint32()), + zap.Stringer("beacon", beacon), + ) + return maps.Keys(activeMap), nil +} + +func (o *ActiveSetCache) UpdateActiveSet(epoch types.EpochID, activeSet []types.ATXID) { + o.log.Debug("received activeset update", + zap.Uint32("epoch", epoch.Uint32()), + zap.Int("size", len(activeSet)), + ) + o.mu.Lock() + defer o.mu.Unlock() + if _, ok := o.fallback[epoch]; ok { + o.log.Debug("fallback active set already exists", zap.Uint32("epoch", epoch.Uint32())) + return + } + o.fallback[epoch] = activeSet +} + +func (o *ActiveSetCache) TotalWeight(ctx context.Context, epoch types.EpochID) (uint64, error) { + actives, err := o.actives(ctx, epoch) + if err != nil { + return 0, err + } + return actives.total, nil +} + +func (o *ActiveSetCache) MinerWeight(ctx context.Context, epoch types.EpochID, id types.NodeID) (uint64, error) { + actives, err := o.actives(ctx, epoch) + if err != nil { + return 0, err + } + + w, ok := actives.set[id] + if !ok { + return 0, fmt.Errorf("%w: %v", ErrNotActive, id) + } + return w.weight, nil +} diff --git a/hare3/eligibility/active_set_test.go b/hare3/eligibility/active_set_test.go new file mode 100644 index 0000000000..15c3135668 --- /dev/null +++ b/hare3/eligibility/active_set_test.go @@ -0,0 +1,45 @@ +package eligibility + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + gomock "go.uber.org/mock/gomock" + "go.uber.org/zap/zaptest" + + "github.com/spacemeshos/go-spacemesh/atxsdata" + "github.com/spacemeshos/go-spacemesh/sql/statesql" + "github.com/spacemeshos/go-spacemesh/system/mocks" +) + +func TestResetCache(t *testing.T) { + db := statesql.InMemoryTest(t) + + ctrl := gomock.NewController(t) + mBeacon := NewMockBeaconProvider(ctrl) + mSyncer := mocks.NewMockSyncStateProvider(ctrl) + + cache, err := NewActiveSetCache(mBeacon, db, atxsdata.New(), zaptest.NewLogger(t)) + require.NoError(t, err) + cache.SetSync(mSyncer) + cache.cache.Add(1, nil) + + mSyncer.EXPECT().IsSynced(gomock.Any()).Return(false) + cache.resetCacheOnSynced(context.Background()) + require.True(t, cache.cache.Contains(1)) + + mSyncer.EXPECT().IsSynced(gomock.Any()).Return(false) + cache.resetCacheOnSynced(context.Background()) + require.True(t, cache.cache.Contains(1)) + + mSyncer.EXPECT().IsSynced(gomock.Any()).Return(true) + cache.resetCacheOnSynced(context.Background()) + require.Equal(t, 0, cache.cache.Len()) + + cache.cache.Add(1, nil) + + mSyncer.EXPECT().IsSynced(gomock.Any()).Return(true) + cache.resetCacheOnSynced(context.Background()) + require.True(t, cache.cache.Contains(1)) +} diff --git a/hare3/eligibility/cached_weights.go b/hare3/eligibility/cached_weights.go new file mode 100644 index 0000000000..c9ffa059dc --- /dev/null +++ b/hare3/eligibility/cached_weights.go @@ -0,0 +1,76 @@ +package eligibility + +import ( + "context" + "sync" + + lru "github.com/hashicorp/golang-lru/v2" + "golang.org/x/sync/singleflight" + + "github.com/spacemeshos/go-spacemesh/common/types" +) + +type cachedWeights struct { + mu sync.Mutex + minerWeights map[types.EpochID]map[types.NodeID]uint64 + + sf singleflight.Group + epochWeights *lru.Cache[types.EpochID, uint64] + + weightsSvc weights +} + +func NewCachedWeights(weightsSvc weights) *cachedWeights { + epochWeightsCache, err := lru.New[types.EpochID, uint64](2) + if err != nil { + panic("failed to create epoch weights cache") + } + return &cachedWeights{ + minerWeights: make(map[types.EpochID]map[types.NodeID]uint64, 2), + epochWeights: epochWeightsCache, + weightsSvc: weightsSvc, + } +} + +func (c *cachedWeights) MinerWeight(ctx context.Context, epoch types.EpochID, node types.NodeID) (uint64, error) { + c.mu.Lock() + if cache, ok := c.minerWeights[epoch]; ok { + if w, ok := cache[node]; ok { + c.mu.Unlock() + return w, nil + } + } + c.mu.Unlock() + + w, err := c.weightsSvc.MinerWeight(ctx, epoch, node) + if err != nil { + return 0, err + } + + c.mu.Lock() + defer c.mu.Unlock() + if cache, ok := c.minerWeights[epoch]; ok { + cache[node] = w + } else { + c.minerWeights[epoch] = make(map[types.NodeID]uint64, 100) + c.minerWeights[epoch][node] = w + + // evict old epoch as it's not needed anymore + delete(c.minerWeights, epoch-2) + } + return w, nil +} + +func (c *cachedWeights) TotalWeight(ctx context.Context, epoch types.EpochID) (uint64, error) { + res, err, _ := c.sf.Do(epoch.String(), func() (any, error) { + if w, ok := c.epochWeights.Get(epoch); ok { + return w, nil + } + w, err := c.weightsSvc.TotalWeight(ctx, epoch) + if err == nil { + c.epochWeights.Add(epoch, w) + } + return w, err + }) + return res.(uint64), err +} diff --git a/hare3/eligibility/cached_weights_test.go b/hare3/eligibility/cached_weights_test.go new file mode 100644 index 0000000000..264b4f6d04 --- /dev/null +++ b/hare3/eligibility/cached_weights_test.go @@ -0,0 +1,232 @@ +package eligibility + +import ( + "context" + "encoding/binary" + "errors" + "fmt" + "testing" + + "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" + "golang.org/x/sync/errgroup" + + "github.com/spacemeshos/go-spacemesh/common/types" +) + +func TestMinerWeight(t *testing.T) { + t.Run("caches successful responses", func(t *testing.T) { + ctrl := gomock.NewController(t) + mock := NewMockweights(ctrl) + cache := NewCachedWeights(mock) + + nodeID := types.NodeID{1, 2, 3} + expectedWeight := uint64(100) + + mock.EXPECT(). + MinerWeight(gomock.Any(), types.EpochID(1), nodeID). + Return(expectedWeight, nil). + Times(1) + + // First call should hit the service + got, err := cache.MinerWeight(context.Background(), 1, nodeID) + require.NoError(t, err) + require.Equal(t, expectedWeight, got) + + // Second call should use cache + got, err = cache.MinerWeight(context.Background(), 1, nodeID) + require.NoError(t, err) + require.Equal(t, expectedWeight, got) + }) + + t.Run("doesn't cache errors", func(t *testing.T) { + ctrl := gomock.NewController(t) + mock := NewMockweights(ctrl) + cache := NewCachedWeights(mock) + + nodeID := types.NodeID{1, 2, 3} + expectedErr := errors.New("weight not found") + + mock.EXPECT(). + MinerWeight(gomock.Any(), types.EpochID(1), nodeID). + Return(uint64(0), expectedErr). + Times(2) + + // First call should fail + _, err := cache.MinerWeight(context.Background(), 1, nodeID) + require.Error(t, err) + require.ErrorIs(t, err, expectedErr) + + // Second call should try again + _, err = cache.MinerWeight(context.Background(), 1, nodeID) + require.Error(t, err) + require.ErrorIs(t, err, expectedErr) + }) + + t.Run("handles parallel requests correctly", func(t *testing.T) { + ctrl := gomock.NewController(t) + mock := NewMockweights(ctrl) + cache := NewCachedWeights(mock) + + const numNodes = 1000 + + epochs := []types.EpochID{1, 2} + nodes := make([]types.NodeID, numNodes) + for i := range nodes { + binary.LittleEndian.PutUint64(nodes[i][:], uint64(i)) + } + + var eg errgroup.Group + + // Launch parallel requests for all combinations + for _, epoch := range epochs { + for i, node := range nodes { + expectedWeight := uint64(epoch)*numNodes + uint64(i) + mock.EXPECT().MinerWeight(gomock.Any(), epoch, node).Return(expectedWeight, nil) + eg.Go(func() error { + w, _ := cache.MinerWeight(context.Background(), epoch, node) + if w != expectedWeight { + return fmt.Errorf( + "wrong weight for epoch %d node %v: got %d, want %d ", + epoch, + node, + w, + expectedWeight, + ) + } + return nil + }) + } + } + require.NoError(t, eg.Wait()) + + // Verify all values are properly cached + for _, epoch := range epochs { + for i, node := range nodes { + expectedWeight := uint64(epoch)*numNodes + uint64(i) + w, err := cache.MinerWeight(context.Background(), epoch, node) + require.NoError(t, err) + require.Equal(t, expectedWeight, w) + } + } + }) + t.Run("evicts old epochs", func(t *testing.T) { + ctrl := gomock.NewController(t) + mock := NewMockweights(ctrl) + cache := NewCachedWeights(mock) + + nodeID := types.NodeID{1, 2, 3} + weight := uint64(100) + + // Set up initial cache for epoch 1 + mock.EXPECT().MinerWeight(gomock.Any(), types.EpochID(1), nodeID).Return(weight, nil) + _, err := cache.MinerWeight(context.Background(), 1, nodeID) + require.NoError(t, err) + + // Access epoch 3 which should trigger eviction of epoch 1 + mock.EXPECT().MinerWeight(gomock.Any(), types.EpochID(3), nodeID).Return(weight, nil) + _, err = cache.MinerWeight(context.Background(), 3, nodeID) + require.NoError(t, err) + + // Epoch 1 should be evicted, requiring a new service call + mock.EXPECT().MinerWeight(gomock.Any(), types.EpochID(1), nodeID).Return(weight, nil) + _, err = cache.MinerWeight(context.Background(), 1, nodeID) + require.NoError(t, err) + }) +} + +func TestTotalWeight(t *testing.T) { + t.Run("caches successful responses", func(t *testing.T) { + ctrl := gomock.NewController(t) + mock := NewMockweights(ctrl) + cache := NewCachedWeights(mock) + + expectedWeight := uint64(1000) + + mock.EXPECT().TotalWeight(gomock.Any(), types.EpochID(1)).Return(expectedWeight, nil) + + // First call should hit the service + got, err := cache.TotalWeight(context.Background(), 1) + require.NoError(t, err) + require.Equal(t, expectedWeight, got) + + // Second call should use cache + got, err = cache.TotalWeight(context.Background(), 1) + require.NoError(t, err) + require.Equal(t, expectedWeight, got) + }) + + t.Run("doesn't cache errors", func(t *testing.T) { + ctrl := gomock.NewController(t) + mock := NewMockweights(ctrl) + cache := NewCachedWeights(mock) + + expectedErr := errors.New("total weight not found") + + mock.EXPECT(). + TotalWeight(gomock.Any(), types.EpochID(1)). + Return(uint64(0), expectedErr). + Times(2) + + // First call should fail + _, err := cache.TotalWeight(context.Background(), 1) + require.Error(t, err) + require.ErrorIs(t, err, expectedErr) + + // Second call should try again + _, err = cache.TotalWeight(context.Background(), 1) + require.Error(t, err) + require.ErrorIs(t, err, expectedErr) + }) + + t.Run("uses singleflight for concurrent requests", func(t *testing.T) { + ctrl := gomock.NewController(t) + mock := NewMockweights(ctrl) + cache := NewCachedWeights(mock) + + expectedWeight := uint64(1000) + mock.EXPECT().TotalWeight(gomock.Any(), types.EpochID(1)).Return(expectedWeight, nil) + + var eg errgroup.Group + for range 100 { + eg.Go(func() error { + got, err := cache.TotalWeight(context.Background(), 1) + if err != nil { + return err + } + if got != expectedWeight { + return fmt.Errorf("got wrong weight, want: %d, got: %d", expectedWeight, got) + } + return nil + }) + } + require.NoError(t, eg.Wait()) + }) + + t.Run("respects LRU cache size", func(t *testing.T) { + ctrl := gomock.NewController(t) + mock := NewMockweights(ctrl) + cache := NewCachedWeights(mock) + + weight := uint64(1000) + + // Fill cache with epochs 1 and 2 + mock.EXPECT().TotalWeight(gomock.Any(), types.EpochID(1)).Return(weight, nil) + mock.EXPECT().TotalWeight(gomock.Any(), types.EpochID(2)).Return(weight, nil) + + _, err := cache.TotalWeight(context.Background(), 1) + require.NoError(t, err) + _, err = cache.TotalWeight(context.Background(), 2) + require.NoError(t, err) + + // Add epoch 3, should evict epoch 1 + mock.EXPECT().TotalWeight(gomock.Any(), types.EpochID(3)).Return(weight, nil) + _, err = cache.TotalWeight(context.Background(), 3) + require.NoError(t, err) + + // Epoch 1 should require new service call + mock.EXPECT().TotalWeight(gomock.Any(), types.EpochID(1)).Return(weight, nil) + _, err = cache.TotalWeight(context.Background(), 1) + require.NoError(t, err) + }) +} diff --git a/hare3/eligibility/interface.go b/hare3/eligibility/interface.go index af8908a006..f332d578d8 100644 --- a/hare3/eligibility/interface.go +++ b/hare3/eligibility/interface.go @@ -8,11 +8,6 @@ import ( //go:generate mockgen -typed -package=eligibility -destination=./mocks.go -source=./interface.go -type activeSetCache interface { - Add(key types.EpochID, value *cachedActiveSet) (evicted bool) - Get(key types.EpochID) (value *cachedActiveSet, ok bool) -} - type vrfVerifier interface { Verify(nodeID types.NodeID, msg []byte, sig types.VrfSignature) bool } @@ -26,3 +21,8 @@ type Rolacle interface { type BeaconProvider interface { Beacon(context.Context, types.EpochID) (types.Beacon, error) } + +type weights interface { + MinerWeight(ctx context.Context, epoch types.EpochID, node types.NodeID) (uint64, error) + TotalWeight(ctx context.Context, epoch types.EpochID) (uint64, error) +} diff --git a/hare3/eligibility/mocks.go b/hare3/eligibility/mocks.go index 0f13501f05..62058a4842 100644 --- a/hare3/eligibility/mocks.go +++ b/hare3/eligibility/mocks.go @@ -17,107 +17,6 @@ import ( gomock "go.uber.org/mock/gomock" ) -// MockactiveSetCache is a mock of activeSetCache interface. -type MockactiveSetCache struct { - ctrl *gomock.Controller - recorder *MockactiveSetCacheMockRecorder - isgomock struct{} -} - -// MockactiveSetCacheMockRecorder is the mock recorder for MockactiveSetCache. -type MockactiveSetCacheMockRecorder struct { - mock *MockactiveSetCache -} - -// NewMockactiveSetCache creates a new mock instance. -func NewMockactiveSetCache(ctrl *gomock.Controller) *MockactiveSetCache { - mock := &MockactiveSetCache{ctrl: ctrl} - mock.recorder = &MockactiveSetCacheMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockactiveSetCache) EXPECT() *MockactiveSetCacheMockRecorder { - return m.recorder -} - -// Add mocks base method. -func (m *MockactiveSetCache) Add(key types.EpochID, value *cachedActiveSet) bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Add", key, value) - ret0, _ := ret[0].(bool) - return ret0 -} - -// Add indicates an expected call of Add. -func (mr *MockactiveSetCacheMockRecorder) Add(key, value any) *MockactiveSetCacheAddCall { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Add", reflect.TypeOf((*MockactiveSetCache)(nil).Add), key, value) - return &MockactiveSetCacheAddCall{Call: call} -} - -// MockactiveSetCacheAddCall wrap *gomock.Call -type MockactiveSetCacheAddCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *MockactiveSetCacheAddCall) Return(evicted bool) *MockactiveSetCacheAddCall { - c.Call = c.Call.Return(evicted) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *MockactiveSetCacheAddCall) Do(f func(types.EpochID, *cachedActiveSet) bool) *MockactiveSetCacheAddCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockactiveSetCacheAddCall) DoAndReturn(f func(types.EpochID, *cachedActiveSet) bool) *MockactiveSetCacheAddCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - -// Get mocks base method. -func (m *MockactiveSetCache) Get(key types.EpochID) (*cachedActiveSet, bool) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Get", key) - ret0, _ := ret[0].(*cachedActiveSet) - ret1, _ := ret[1].(bool) - return ret0, ret1 -} - -// Get indicates an expected call of Get. -func (mr *MockactiveSetCacheMockRecorder) Get(key any) *MockactiveSetCacheGetCall { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockactiveSetCache)(nil).Get), key) - return &MockactiveSetCacheGetCall{Call: call} -} - -// MockactiveSetCacheGetCall wrap *gomock.Call -type MockactiveSetCacheGetCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *MockactiveSetCacheGetCall) Return(value *cachedActiveSet, ok bool) *MockactiveSetCacheGetCall { - c.Call = c.Call.Return(value, ok) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *MockactiveSetCacheGetCall) Do(f func(types.EpochID) (*cachedActiveSet, bool)) *MockactiveSetCacheGetCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockactiveSetCacheGetCall) DoAndReturn(f func(types.EpochID) (*cachedActiveSet, bool)) *MockactiveSetCacheGetCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - // MockvrfVerifier is a mock of vrfVerifier interface. type MockvrfVerifier struct { ctrl *gomock.Controller @@ -344,3 +243,105 @@ func (c *MockBeaconProviderBeaconCall) DoAndReturn(f func(context.Context, types c.Call = c.Call.DoAndReturn(f) return c } + +// Mockweights is a mock of weights interface. +type Mockweights struct { + ctrl *gomock.Controller + recorder *MockweightsMockRecorder + isgomock struct{} +} + +// MockweightsMockRecorder is the mock recorder for Mockweights. +type MockweightsMockRecorder struct { + mock *Mockweights +} + +// NewMockweights creates a new mock instance. +func NewMockweights(ctrl *gomock.Controller) *Mockweights { + mock := &Mockweights{ctrl: ctrl} + mock.recorder = &MockweightsMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *Mockweights) EXPECT() *MockweightsMockRecorder { + return m.recorder +} + +// MinerWeight mocks base method. +func (m *Mockweights) MinerWeight(ctx context.Context, epoch types.EpochID, node types.NodeID) (uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "MinerWeight", ctx, epoch, node) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// MinerWeight indicates an expected call of MinerWeight. +func (mr *MockweightsMockRecorder) MinerWeight(ctx, epoch, node any) *MockweightsMinerWeightCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MinerWeight", reflect.TypeOf((*Mockweights)(nil).MinerWeight), ctx, epoch, node) + return &MockweightsMinerWeightCall{Call: call} +} + +// MockweightsMinerWeightCall wrap *gomock.Call +type MockweightsMinerWeightCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockweightsMinerWeightCall) Return(arg0 uint64, arg1 error) *MockweightsMinerWeightCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockweightsMinerWeightCall) Do(f func(context.Context, types.EpochID, types.NodeID) (uint64, error)) *MockweightsMinerWeightCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockweightsMinerWeightCall) DoAndReturn(f func(context.Context, types.EpochID, types.NodeID) (uint64, error)) *MockweightsMinerWeightCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// TotalWeight mocks base method. +func (m *Mockweights) TotalWeight(ctx context.Context, epoch types.EpochID) (uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "TotalWeight", ctx, epoch) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// TotalWeight indicates an expected call of TotalWeight. +func (mr *MockweightsMockRecorder) TotalWeight(ctx, epoch any) *MockweightsTotalWeightCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TotalWeight", reflect.TypeOf((*Mockweights)(nil).TotalWeight), ctx, epoch) + return &MockweightsTotalWeightCall{Call: call} +} + +// MockweightsTotalWeightCall wrap *gomock.Call +type MockweightsTotalWeightCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockweightsTotalWeightCall) Return(arg0 uint64, arg1 error) *MockweightsTotalWeightCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockweightsTotalWeightCall) Do(f func(context.Context, types.EpochID) (uint64, error)) *MockweightsTotalWeightCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockweightsTotalWeightCall) DoAndReturn(f func(context.Context, types.EpochID) (uint64, error)) *MockweightsTotalWeightCall { + c.Call = c.Call.DoAndReturn(f) + return c +} diff --git a/hare3/eligibility/oracle.go b/hare3/eligibility/oracle.go index 2f2d0ac849..c1aaca3a9a 100644 --- a/hare3/eligibility/oracle.go +++ b/hare3/eligibility/oracle.go @@ -5,24 +5,15 @@ import ( "errors" "fmt" "math" - "sync" - lru "github.com/hashicorp/golang-lru/v2" "github.com/spacemeshos/fixed" "go.uber.org/zap" "go.uber.org/zap/zapcore" - "golang.org/x/exp/maps" - "github.com/spacemeshos/go-spacemesh/atxsdata" "github.com/spacemeshos/go-spacemesh/codec" "github.com/spacemeshos/go-spacemesh/common/types" "github.com/spacemeshos/go-spacemesh/log" - "github.com/spacemeshos/go-spacemesh/miner" "github.com/spacemeshos/go-spacemesh/signing" - "github.com/spacemeshos/go-spacemesh/sql" - "github.com/spacemeshos/go-spacemesh/sql/activesets" - "github.com/spacemeshos/go-spacemesh/sql/ballots" - "github.com/spacemeshos/go-spacemesh/system" ) const ( @@ -31,8 +22,7 @@ const ( ) const ( - activesCacheSize = 5 // we don't expect to handle more than two layers concurrently - maxSupportedN = (math.MaxInt32 / 2) + 1 // higher values result in an overflow when calculating CDF + maxSupportedN = (math.MaxInt32 / 2) + 1 // higher values result in an overflow when calculating CDF ) var ( @@ -42,24 +32,6 @@ var ( ErrNotActive = errors.New("oracle: miner is not active in epoch") ) -type identityWeight struct { - atx types.ATXID - weight uint64 -} - -type cachedActiveSet struct { - set map[types.NodeID]identityWeight - total uint64 -} - -func (c *cachedActiveSet) atxs() []types.ATXID { - atxs := make([]types.ATXID, 0, len(c.set)) - for _, id := range c.set { - atxs = append(atxs, id.atx) - } - return atxs -} - // Config is the configuration of the oracle package. type Config struct { // ConfidenceParam specifies how many layers into the epoch hare uses active set generated in the previous epoch. @@ -83,38 +55,15 @@ func DefaultConfig() Config { // Oracle is the hare eligibility oracle. type Oracle struct { - mu sync.Mutex - activesCache activeSetCache - fallback map[types.EpochID][]types.ATXID - sync system.SyncStateProvider - // NOTE(dshulyak) on switch from synced to not synced reset the cache - // to cope with https://github.com/spacemeshos/go-spacemesh/issues/4552 - // until graded oracle is implemented - synced bool - - beacons BeaconProvider - atxsdata *atxsdata.Data - db sql.Executor - vrfVerifier vrfVerifier - cfg Config - minerWeightFn func(context.Context, types.EpochID, types.NodeID) (uint64, error) - totalWeightFn func(context.Context, types.EpochID) (uint64, error) - log *zap.Logger -} + weights weights -type Opt func(*Oracle) - -func WithMinerWeightFunc(f func(context.Context, types.EpochID, types.NodeID) (uint64, error)) Opt { - return func(o *Oracle) { - o.minerWeightFn = f - } + beacons BeaconProvider + vrfVerifier vrfVerifier + cfg Config + log *zap.Logger } -func WithTotalWeightFunc(f func(context.Context, types.EpochID) (uint64, error)) Opt { - return func(o *Oracle) { - o.totalWeightFn = f - } -} +type Opt func(*Oracle) func WithConfig(config Config) Opt { return func(o *Oracle) { @@ -130,29 +79,19 @@ func WithLogger(logger *zap.Logger) Opt { // New returns a new eligibility oracle instance. func New( + weights weights, beacons BeaconProvider, - db sql.Executor, - atxsdata *atxsdata.Data, vrfVerifier vrfVerifier, layersPerEpoch uint32, opts ...Opt, ) (*Oracle, error) { - activesCache, err := lru.New[types.EpochID, *cachedActiveSet](activesCacheSize) - if err != nil { - return nil, fmt.Errorf("create lru cache for active set: %w", err) - } oracle := &Oracle{ - beacons: beacons, - db: db, - atxsdata: atxsdata, - vrfVerifier: vrfVerifier, - activesCache: activesCache, - fallback: map[types.EpochID][]types.ATXID{}, - cfg: DefaultConfig(), - log: zap.NewNop(), + beacons: beacons, + vrfVerifier: vrfVerifier, + weights: weights, + cfg: DefaultConfig(), + log: zap.NewNop(), } - oracle.minerWeightFn = oracle.minerWeight - oracle.totalWeightFn = oracle.totalWeight for _, opt := range opts { opt(oracle) } @@ -178,24 +117,6 @@ type VrfMessage struct { Layer types.LayerID } -func (o *Oracle) SetSync(sync system.SyncStateProvider) { - o.mu.Lock() - defer o.mu.Unlock() - o.sync = sync -} - -func (o *Oracle) resetCacheOnSynced(ctx context.Context) { - synced := o.synced - o.synced = o.sync.IsSynced(ctx) - if !synced && o.synced { - ac, err := lru.New[types.EpochID, *cachedActiveSet](activesCacheSize) - if err != nil { - o.log.Fatal("failed to create lru cache for active set", zap.Error(err)) - } - o.activesCache = ac - } -} - // buildVRFMessage builds the VRF message used as input for hare eligibility validation. func (o *Oracle) buildVRFMessage(ctx context.Context, layer types.LayerID, round uint32) ([]byte, error) { beacon, err := o.beacons.Beacon(ctx, layer.GetEpoch()) @@ -205,27 +126,6 @@ func (o *Oracle) buildVRFMessage(ctx context.Context, layer types.LayerID, round return codec.MustEncode(&VrfMessage{Type: types.EligibilityHare, Beacon: beacon, Round: round, Layer: layer}), nil } -func (o *Oracle) totalWeight(ctx context.Context, epoch types.EpochID) (uint64, error) { - actives, err := o.actives(ctx, epoch) - if err != nil { - return 0, err - } - return actives.total, nil -} - -func (o *Oracle) minerWeight(ctx context.Context, epoch types.EpochID, id types.NodeID) (uint64, error) { - actives, err := o.actives(ctx, epoch) - if err != nil { - return 0, err - } - - w, ok := actives.set[id] - if !ok { - return 0, fmt.Errorf("%w: %v", ErrNotActive, id) - } - return w.weight, nil -} - func calcVrfFrac(vrfSig types.VrfSignature) fixed.Fixed { return fixed.FracFromBytes(vrfSig[:8]) } @@ -254,7 +154,7 @@ func (o *Oracle) prepareEligibilityCheck( // calc hash & check threshold // this is cheap in case the node is not eligible - minerWeight, err := o.minerWeightFn(ctx, o.layerToEpoch(layer), id) + minerWeight, err := o.weights.MinerWeight(ctx, o.layerToEpoch(layer), id) if err != nil { return 0, fixed.Fixed{}, fixed.Fixed{}, true, err } @@ -272,7 +172,7 @@ func (o *Oracle) prepareEligibilityCheck( } // get active set size - totalWeight, err := o.totalWeightFn(ctx, o.layerToEpoch(layer)) + totalWeight, err := o.weights.TotalWeight(ctx, o.layerToEpoch(layer)) if err != nil { logger.Error("failed to get total weight", zap.Error(err)) return 0, fixed.Fixed{}, fixed.Fixed{}, true, err @@ -418,146 +318,3 @@ func (o *Oracle) layerToEpoch(layer types.LayerID) types.EpochID { } return epoch } - -// Returns a set of all active node IDs in the specified epoch. -func (o *Oracle) actives(ctx context.Context, targetEpoch types.EpochID) (*cachedActiveSet, error) { - if !targetEpoch.FirstLayer().After(types.GetEffectiveGenesis()) { - return nil, errEmptyActiveSet - } - o.log.Debug("hare oracle getting active set", - log.ZContext(ctx), - zap.Uint32("target_epoch", targetEpoch.Uint32()), - ) - - o.mu.Lock() - defer o.mu.Unlock() - o.resetCacheOnSynced(ctx) - if value, exists := o.activesCache.Get(targetEpoch); exists { - return value, nil - } - activeSet, err := o.computeActiveSet(ctx, targetEpoch) - if err != nil { - return nil, err - } - if len(activeSet) == 0 { - return nil, errEmptyActiveSet - } - activeWeights, err := o.computeActiveWeights(targetEpoch, activeSet) - if err != nil { - return nil, err - } - - aset := &cachedActiveSet{set: activeWeights} - for _, aweight := range activeWeights { - aset.total += aweight.weight - } - o.log.Debug("got hare active set", log.ZContext(ctx), zap.Int("count", len(activeWeights))) - o.activesCache.Add(targetEpoch, aset) - return aset, nil -} - -func (o *Oracle) ActiveSet(ctx context.Context, targetEpoch types.EpochID) ([]types.ATXID, error) { - aset, err := o.actives(ctx, targetEpoch) - if err != nil { - return nil, err - } - return aset.atxs(), nil -} - -func (o *Oracle) computeActiveSet(ctx context.Context, targetEpoch types.EpochID) ([]types.ATXID, error) { - activeSet, ok := o.fallback[targetEpoch] - if ok { - o.log.Debug("using fallback active set", - log.ZContext(ctx), - zap.Uint32("target_epoch", targetEpoch.Uint32()), - zap.Int("size", len(activeSet)), - ) - return activeSet, nil - } - - activeSet, err := miner.ActiveSetFromEpochFirstBlock(o.db, targetEpoch) - if err != nil && !errors.Is(err, sql.ErrNotFound) { - return nil, err - } - if len(activeSet) == 0 { - return o.activeSetFromRefBallots(ctx, targetEpoch) - } - return activeSet, nil -} - -func (o *Oracle) computeActiveWeights( - targetEpoch types.EpochID, - activeSet []types.ATXID, -) (map[types.NodeID]identityWeight, error) { - identities := make(map[types.NodeID]identityWeight, len(activeSet)) - for _, id := range activeSet { - atx := o.atxsdata.Get(targetEpoch, id) - if atx == nil { - return nil, fmt.Errorf("oracle: missing atx in atxsdata %s/%s", targetEpoch, id.ShortString()) - } - identities[atx.Node] = identityWeight{atx: id, weight: atx.Weight} - } - return identities, nil -} - -func (o *Oracle) activeSetFromRefBallots(ctx context.Context, epoch types.EpochID) ([]types.ATXID, error) { - beacon, err := o.beacons.Beacon(ctx, epoch) - if err != nil { - return nil, fmt.Errorf("get beacon: %w", err) - } - ballotsrst, err := ballots.AllFirstInEpoch(o.db, epoch) - if err != nil { - return nil, fmt.Errorf("first in epoch %d: %w", epoch, err) - } - activeMap := make(map[types.ATXID]struct{}, len(ballotsrst)) - for _, ballot := range ballotsrst { - if ballot.EpochData == nil { - o.log.Error("invalid data. first ballot doesn't have epoch data", zap.Inline(ballot)) - continue - } - if ballot.EpochData.Beacon != beacon { - o.log.Debug("beacon mismatch", zap.Stringer("local", beacon), zap.Object("ballot", ballot)) - continue - } - actives, err := activesets.Get(o.db, ballot.EpochData.ActiveSetHash) - if err != nil { - o.log.Error("failed to get active set", - zap.String("actives hash", ballot.EpochData.ActiveSetHash.ShortString()), - zap.String("ballot ", ballot.ID().String()), - zap.Error(err), - ) - continue - } - for _, id := range actives.Set { - activeMap[id] = struct{}{} - } - } - o.log.Warn("using tortoise active set", - zap.Int("actives size", len(activeMap)), - zap.Uint32("epoch", epoch.Uint32()), - zap.Stringer("beacon", beacon), - ) - return maps.Keys(activeMap), nil -} - -func (o *Oracle) UpdateActiveSet(epoch types.EpochID, activeSet []types.ATXID) { - o.log.Debug("received activeset update", - zap.Uint32("epoch", epoch.Uint32()), - zap.Int("size", len(activeSet)), - ) - o.mu.Lock() - defer o.mu.Unlock() - if _, ok := o.fallback[epoch]; ok { - o.log.Debug("fallback active set already exists", zap.Uint32("epoch", epoch.Uint32())) - return - } - o.fallback[epoch] = activeSet -} - -func (o *Oracle) TotalWeight(ctx context.Context, epoch types.EpochID) (uint64, error) { - return o.totalWeightFn(ctx, epoch) -} - -func (o *Oracle) MinerWeight(ctx context.Context, node types.NodeID, epoch types.EpochID) (uint64, error) { - return o.minerWeightFn(ctx, epoch, node) -} diff --git a/hare3/eligibility/oracle_test.go b/hare3/eligibility/oracle_test.go index ca80a9bce9..033e3a2bf9 100644 --- a/hare3/eligibility/oracle_test.go +++ b/hare3/eligibility/oracle_test.go @@ -18,6 +18,7 @@ import ( "go.uber.org/mock/gomock" "go.uber.org/zap/zaptest" "golang.org/x/exp/maps" + "golang.org/x/sync/errgroup" "github.com/spacemeshos/go-spacemesh/atxsdata" "github.com/spacemeshos/go-spacemesh/common/types" @@ -46,12 +47,13 @@ func TestMain(m *testing.M) { type testOracle struct { *Oracle - tb testing.TB - db sql.StateDatabase - atxsdata *atxsdata.Data - mBeacon *MockBeaconProvider - mVerifier *MockvrfVerifier - mSyncer *mocks.MockSyncStateProvider + tb testing.TB + db sql.StateDatabase + atxsdata *atxsdata.Data + activeSetCache *ActiveSetCache + mBeacon *MockBeaconProvider + mVerifier *MockvrfVerifier + mSyncer *mocks.MockSyncStateProvider } func defaultOracle(tb testing.TB) *testOracle { @@ -62,27 +64,30 @@ func defaultOracle(tb testing.TB) *testOracle { mBeacon := NewMockBeaconProvider(ctrl) mVerifier := NewMockvrfVerifier(ctrl) mSyncer := mocks.NewMockSyncStateProvider(ctrl) + logger := zaptest.NewLogger(tb) + activeSetCache, err := NewActiveSetCache(mBeacon, db, atxsdata, logger) + require.NoError(tb, err) + activeSetCache.SetSync(mSyncer) o, err := New( + activeSetCache, mBeacon, - db, - atxsdata, mVerifier, defLayersPerEpoch, WithConfig(Config{ConfidenceParam: confidenceParam}), - WithLogger(zaptest.NewLogger(tb)), + WithLogger(logger), ) require.NoError(tb, err) to := &testOracle{ - Oracle: o, - tb: tb, - mBeacon: mBeacon, - mVerifier: mVerifier, - mSyncer: mSyncer, - db: db, - atxsdata: atxsdata, + Oracle: o, + tb: tb, + mBeacon: mBeacon, + mVerifier: mVerifier, + mSyncer: mSyncer, + db: db, + atxsdata: atxsdata, + activeSetCache: activeSetCache, } - to.SetSync(mSyncer) return to } @@ -245,7 +250,7 @@ func TestCalcEligibility(t *testing.T) { activeSet := types.RandomActiveSet(111) miners := o.createActiveSet(types.EpochID(4).FirstLayer(), activeSet) - o.UpdateActiveSet(5, activeSet) + o.activeSetCache.UpdateActiveSet(5, activeSet) o.mBeacon.EXPECT().Beacon(gomock.Any(), lid.GetEpoch()).Return(types.RandomBeacon(), nil) o.mSyncer.EXPECT().IsSynced(context.Background()).Return(false) o.mVerifier.EXPECT().Verify(gomock.Any(), gomock.Any(), gomock.Any()).Return(true) @@ -481,11 +486,10 @@ func TestActiveSet(t *testing.T) { numMiners := 5 o := defaultOracle(t) targetEpoch := types.EpochID(5) - layer := targetEpoch.FirstLayer().Add(o.cfg.ConfidenceParam) o.mSyncer.EXPECT().IsSynced(context.Background()).Return(false).AnyTimes() o.createLayerData(targetEpoch.FirstLayer(), numMiners) - aset, err := o.actives(context.Background(), o.layerToEpoch(layer)) + aset, err := o.activeSetCache.actives(context.Background(), targetEpoch) require.NoError(t, err) require.ElementsMatch( t, @@ -494,7 +498,7 @@ func TestActiveSet(t *testing.T) { "assertion relies on the enumeration of identities", ) - got, err := o.ActiveSet(context.Background(), targetEpoch) + got, err := o.activeSetCache.ActiveSet(context.Background(), targetEpoch) require.NoError(t, err) require.Len(t, got, len(aset.set)) for _, id := range got { @@ -513,14 +517,14 @@ func TestActives(t *testing.T) { first := types.GetEffectiveGenesis().Add(1) bootstrap := types.RandomActiveSet(numMiners) o.createActiveSet(types.EpochID(1).FirstLayer(), bootstrap) - o.UpdateActiveSet(types.GetEffectiveGenesis().GetEpoch()+1, bootstrap) + o.activeSetCache.UpdateActiveSet(types.GetEffectiveGenesis().GetEpoch()+1, bootstrap) for lid := types.LayerID(0); lid.Before(first); lid = lid.Add(1) { - activeSet, err := o.actives(context.Background(), o.layerToEpoch(lid)) + activeSet, err := o.activeSetCache.actives(context.Background(), o.layerToEpoch(lid)) require.ErrorIs(t, err, errEmptyActiveSet) require.Nil(t, activeSet) } - activeSet, err := o.actives(context.Background(), o.layerToEpoch(first)) + activeSet, err := o.activeSetCache.actives(context.Background(), o.layerToEpoch(first)) require.NoError(t, err) require.ElementsMatch( t, @@ -538,7 +542,7 @@ func TestActives(t *testing.T) { o.createLayerData(layer, numMiners) start := layer.Add(o.cfg.ConfidenceParam) - activeSet, err := o.actives(context.Background(), layer.GetEpoch()) + activeSet, err := o.activeSetCache.actives(context.Background(), layer.GetEpoch()) require.NoError(t, err) require.ElementsMatch( t, @@ -549,12 +553,12 @@ func TestActives(t *testing.T) { end := (layer.GetEpoch() + 1).FirstLayer().Add(o.cfg.ConfidenceParam) for lid := start.Add(1); lid.Before(end); lid = lid.Add(1) { - got, err := o.actives(context.Background(), o.layerToEpoch(lid)) + got, err := o.activeSetCache.actives(context.Background(), o.layerToEpoch(lid)) require.NoError(t, err) // cached require.Equal(t, &activeSet, &got) } - got, err := o.actives(context.Background(), end.GetEpoch()) + got, err := o.activeSetCache.actives(context.Background(), end.GetEpoch()) require.ErrorIs(t, err, errEmptyActiveSet) require.Nil(t, got) }) @@ -568,14 +572,14 @@ func TestActives(t *testing.T) { o.createLayerData(layer, numMiners) fallback := types.RandomActiveSet(numMiners + 1) o.createActiveSet(types.EpochID(3).FirstLayer(), fallback) - o.UpdateActiveSet(end.GetEpoch(), fallback) + o.activeSetCache.UpdateActiveSet(end.GetEpoch(), fallback) for lid := layer; lid.Before(end); lid = lid.Add(1) { - got, err := o.actives(context.Background(), o.layerToEpoch(lid)) + got, err := o.activeSetCache.actives(context.Background(), o.layerToEpoch(lid)) require.ErrorIs(t, err, errEmptyActiveSet) require.Nil(t, got) } - activeSet, err := o.actives(context.Background(), end.GetEpoch()) + activeSet, err := o.activeSetCache.actives(context.Background(), end.GetEpoch()) require.NoError(t, err) require.ElementsMatch( t, @@ -598,9 +602,9 @@ func TestActives(t *testing.T) { o.createLayerData(layer, numMiners) fallback := types.RandomActiveSet(numMiners + 1) o.createActiveSet(types.EpochID(3).FirstLayer(), fallback) - o.UpdateActiveSet(layer.GetEpoch(), fallback) + o.activeSetCache.UpdateActiveSet(layer.GetEpoch(), fallback) - activeSet, err := o.actives(context.Background(), o.layerToEpoch(layer)) + activeSet, err := o.activeSetCache.actives(context.Background(), o.layerToEpoch(layer)) require.NoError(t, err) require.ElementsMatch( t, @@ -608,53 +612,34 @@ func TestActives(t *testing.T) { maps.Keys(activeSet.set), "assertion relies on the enumeration of identities", ) - activeSet2, err := o.actives(context.Background(), o.layerToEpoch(layer+1)) + activeSet2, err := o.activeSetCache.actives(context.Background(), o.layerToEpoch(layer+1)) require.NoError(t, err) require.Equal(t, activeSet, activeSet2) }) } func TestActives_ConcurrentCalls(t *testing.T) { - r := require.New(t) o := defaultOracle(t) layer := types.LayerID(100) o.createLayerData(layer.Sub(defLayersPerEpoch), 5) - mc := NewMockactiveSetCache(gomock.NewController(t)) - firstCall := true - mc.EXPECT().Get(layer.GetEpoch() - 1).DoAndReturn( - func(types.EpochID) (*cachedActiveSet, bool) { - if firstCall { - firstCall = false - return nil, false - } - aset := cachedActiveSet{set: createIdentities(5)} - for _, value := range aset.set { - aset.total += value.weight - } - return &aset, true - }).Times(102) - mc.EXPECT().Add(layer.GetEpoch()-1, gomock.Any()) - o.activesCache = mc - o.mSyncer.EXPECT().IsSynced(context.Background()).Return(false).Times(102) - var wg sync.WaitGroup - wg.Add(102) - runFn := func() { - _, err := o.actives(context.Background(), o.layerToEpoch(layer)) - r.NoError(err) - wg.Done() - } // outstanding probability for concurrent access to calc active set size + var eg errgroup.Group for range 100 { - go runFn() + eg.Go(func() error { + _, err := o.activeSetCache.actives(context.Background(), o.layerToEpoch(layer)) + return err + }) } // make sure we wait at least two calls duration - runFn() - runFn() - wg.Wait() + _, err := o.activeSetCache.actives(context.Background(), o.layerToEpoch(layer)) + require.NoError(t, err) + _, err = o.activeSetCache.actives(context.Background(), o.layerToEpoch(layer)) + require.NoError(t, err) + require.NoError(t, eg.Wait()) } func TestMaxSupportedN(t *testing.T) { @@ -891,7 +876,7 @@ func TestActiveSetMatrix(t *testing.T) { oracle.mBeacon.EXPECT().Beacon(gomock.Any(), target).Return(types.EmptyBeacon, sql.ErrNotFound) } oracle.mSyncer.EXPECT().IsSynced(context.Background()).Return(false) - rst, err := oracle.ActiveSet(context.Background(), target) + rst, err := oracle.activeSetCache.ActiveSet(context.Background(), target) switch typed := tc.expect.(type) { case []types.ATXID: @@ -907,32 +892,6 @@ func TestActiveSetMatrix(t *testing.T) { } } -func TestResetCache(t *testing.T) { - oracle := defaultOracle(t) - - prev := oracle.activesCache - prev.Add(1, nil) - - oracle.mSyncer.EXPECT().IsSynced(gomock.Any()).Return(false) - oracle.resetCacheOnSynced(context.Background()) - require.Equal(t, prev, oracle.activesCache) - - oracle.mSyncer.EXPECT().IsSynced(gomock.Any()).Return(false) - oracle.resetCacheOnSynced(context.Background()) - require.Equal(t, prev, oracle.activesCache) - - oracle.mSyncer.EXPECT().IsSynced(gomock.Any()).Return(true) - oracle.resetCacheOnSynced(context.Background()) - require.NotEqual(t, prev, oracle.activesCache) - - prev = oracle.activesCache - prev.Add(1, nil) - - oracle.mSyncer.EXPECT().IsSynced(gomock.Any()).Return(true) - oracle.resetCacheOnSynced(context.Background()) - require.Equal(t, prev, oracle.activesCache) -} - func FuzzVrfMessageConsistency(f *testing.F) { tester.FuzzConsistency[VrfMessage](f) } diff --git a/hare3/hare.go b/hare3/hare.go index 06abd52076..bd6c5c864f 100644 --- a/hare3/hare.go +++ b/hare3/hare.go @@ -692,11 +692,3 @@ func (h *Hare) RoundTemplate(layer types.LayerID, round IterRound) *Body { } return &r.message.Body } - -func (h *Hare) TotalWeight(ctx context.Context, epoch types.EpochID) (uint64, error) { - return h.oracle.oracle.TotalWeight(ctx, epoch) -} - -func (h *Hare) MinerWeight(ctx context.Context, miner types.NodeID, epoch types.EpochID) (uint64, error) { - return h.oracle.oracle.MinerWeight(ctx, miner, epoch) -} diff --git a/hare3/hare_test.go b/hare3/hare_test.go index e70cbc9533..a0dadf3e60 100644 --- a/hare3/hare_test.go +++ b/hare3/hare_test.go @@ -111,16 +111,17 @@ func (t *testNodeClock) AwaitLayer(lid types.LayerID) <-chan struct{} { type node struct { t *tester - i int - clock *clockwork.FakeClock - nclock *testNodeClock - signer *signing.EdSigner - registered []*signing.EdSigner - atx *types.ActivationTx - oracle *eligibility.Oracle - db sql.StateDatabase - atxsdata *atxsdata.Data - proposals *store.Store + i int + clock *clockwork.FakeClock + nclock *testNodeClock + signer *signing.EdSigner + registered []*signing.EdSigner + atx *types.ActivationTx + activeSetCache *eligibility.ActiveSetCache + oracle *eligibility.Oracle + db sql.StateDatabase + atxsdata *atxsdata.Data + proposals *store.Store ctrl *gomock.Controller mpublisher *pmocks.MockPublishSubscriber @@ -193,16 +194,19 @@ func (n *node) withOracle(tb testing.TB) *node { func(_ context.Context, epoch types.EpochID) (types.Beacon, error) { return beacons.Get(n.db, epoch) }).AnyTimes() + activeSetCache, err := eligibility.NewActiveSetCache(beaconget, n.db, n.atxsdata, zaptest.NewLogger(tb)) + require.NoError(tb, err) + activeSetCache.SetSync(n.msyncer) + oracle, err := eligibility.New( + activeSetCache, beaconget, - n.db, - n.atxsdata, signing.NewVRFVerifier(), layersPerEpoch, ) require.NoError(tb, err) - oracle.SetSync(n.msyncer) n.oracle = oracle + n.activeSetCache = activeSetCache return n } @@ -449,7 +453,7 @@ func (cl *lockstepCluster) setup() { } require.NoError(cl.t, n.storeAtx(other.atx)) } - n.oracle.UpdateActiveSet(cl.t.genesis.GetEpoch()+1, active) + n.activeSetCache.UpdateActiveSet(cl.t.genesis.GetEpoch()+1, active) n.mpublisher.EXPECT(). Publish(gomock.Any(), gomock.Any(), gomock.Any()). Do(func(ctx context.Context, _ string, msg []byte) error { @@ -680,7 +684,7 @@ func TestHandler(t *testing.T) { n := cluster.nodes[0] require.NoError(t, beacons.Add(n.db, tst.genesis.GetEpoch()+1, tst.beacon)) require.NoError(t, n.storeAtx(n.atx)) - n.oracle.UpdateActiveSet(tst.genesis.GetEpoch()+1, []types.ATXID{n.atx.ID()}) + n.activeSetCache.UpdateActiveSet(tst.genesis.GetEpoch()+1, []types.ATXID{n.atx.ID()}) n.mpublisher.EXPECT().Publish(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() layer := tst.genesis + 1 n.nclock.StartLayer(layer) diff --git a/hare3/legacy_oracle.go b/hare3/legacy_oracle.go index f2a6f83329..da9ad6c598 100644 --- a/hare3/legacy_oracle.go +++ b/hare3/legacy_oracle.go @@ -14,8 +14,6 @@ import ( type oracle interface { Validate(context.Context, types.LayerID, uint32, int, types.NodeID, types.VrfSignature, uint16) (bool, error) CalcEligibility(context.Context, types.LayerID, uint32, int, types.NodeID, types.VrfSignature) (uint16, error) - TotalWeight(ctx context.Context, epoch types.EpochID) (uint64, error) - MinerWeight(ctx context.Context, node types.NodeID, epoch types.EpochID) (uint64, error) } type legacyOracle struct { diff --git a/node/node.go b/node/node.go index a2f1cf7785..d05322b5f6 100644 --- a/node/node.go +++ b/node/node.go @@ -413,7 +413,7 @@ type App struct { hare4 *hare4.Hare remoteHare *hare3.RemoteHare hareResultsChan chan hare4.ConsensusOutput - hOracle *eligibility.Oracle + activeSetCache *eligibility.ActiveSetCache blockGen *blocks.Generator certifier *blocks.Certifier atxBuilder *activation.Builder @@ -788,10 +788,20 @@ func (app *App) initServices(ctx context.Context) error { app.addLogger(TxHandlerLogger, lg).Zap(), ) - hOracle, err := eligibility.New( + oracleLogger := app.addLogger(HareOracleLogger, lg).Zap() + activeSetCache, err := eligibility.NewActiveSetCache( &beaconGetter{beaconProtocol}, app.db, app.atxsdata, + oracleLogger, + ) + if err != nil { + return fmt.Errorf("create active set cache: %w", err) + } + app.activeSetCache = activeSetCache + hOracle, err := eligibility.New( + activeSetCache, + &beaconGetter{beaconProtocol}, vrfVerifier, app.Config.LayersPerEpoch, eligibility.WithConfig(app.Config.HareEligibility), @@ -902,7 +912,7 @@ func (app *App) initServices(ctx context.Context) error { } // TODO(dshulyak) this needs to be improved, but dependency graph is a bit complicated beaconProtocol.SetSyncState(newSyncer) - hOracle.SetSync(newSyncer) + activeSetCache.SetSync(newSyncer) err = app.Config.HARE3.Validate(time.Duration(app.Config.Tortoise.Zdist) * app.Config.LayerDuration) if err != nil { @@ -1395,7 +1405,6 @@ func (app *App) initServices(ctx context.Context) error { app.poetDb = poetDb app.fetcher = fetcher app.beaconProtocol = beaconProtocol - app.hOracle = hOracle app.certifier = certifier if !app.Config.TIME.Peersync.Disable { app.ptimesync = peersync.New( @@ -1510,7 +1519,7 @@ func (app *App) listenToUpdates(ctx context.Context) { return nil } - app.hOracle.UpdateActiveSet(epoch, set) + app.activeSetCache.UpdateActiveSet(epoch, set) if app.proposalBuilder != nil { app.proposalBuilder.UpdateActiveSet(epoch, set) @@ -1602,7 +1611,7 @@ func (app *App) grpcService(svc grpcserver.Service, lg log.Log) (grpcserver.Serv switch svc { case grpcserver.Debug: - service := grpcserver.NewDebugService(app.db, app.conState, app.host, app.hOracle, app.loggers) + service := grpcserver.NewDebugService(app.db, app.conState, app.host, app.activeSetCache, app.loggers) app.grpcServices[svc] = service return service, nil case grpcserver.GlobalState: @@ -2092,6 +2101,7 @@ func (app *App) startAPIServices(ctx context.Context) error { app.host, app.poetDb, app.hare3, + app.activeSetCache, app.proposalBuilder, logger, ) diff --git a/node/smeshing_service.go b/node/smeshing_service.go index 675ecfee42..09cf093e24 100644 --- a/node/smeshing_service.go +++ b/node/smeshing_service.go @@ -255,16 +255,14 @@ func (app *App) initSmeshingServiceServices(ctx context.Context) error { } beaconProvider := beacon.NewBeaconCache(nodeServiceClient) + cachedWeights := eligibility.NewCachedWeights(nodeServiceClient) hOracle, err := eligibility.New( + cachedWeights, beaconProvider, - app.db, - app.atxsdata, vrfVerifier, app.Config.LayersPerEpoch, eligibility.WithConfig(app.Config.HareEligibility), eligibility.WithLogger(app.addLogger(HareOracleLogger, lg).Zap()), - eligibility.WithTotalWeightFunc(nodeServiceClient.TotalWeight), - eligibility.WithMinerWeightFunc(nodeServiceClient.MinerWeight), ) if err != nil { return fmt.Errorf("create hare oracle: %w", err)