From 271da0fabf5cc4c940f2dae1fb2fcba25b850f07 Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Thu, 17 Oct 2024 15:03:39 -0600 Subject: [PATCH 01/27] wip build proposals --- miner/proposal_builder.go | 206 +++++++++++++++++++++++++++++++++++++- txs/conservative_state.go | 2 +- 2 files changed, 206 insertions(+), 2 deletions(-) diff --git a/miner/proposal_builder.go b/miner/proposal_builder.go index a9a3403502..b5dbf8907e 100644 --- a/miner/proposal_builder.go +++ b/miner/proposal_builder.go @@ -41,7 +41,8 @@ var errAtxNotAvailable = errors.New("atx not available") //go:generate mockgen -typed -package=mocks -destination=./mocks/mocks.go -source=./proposal_builder.go type conservativeState interface { - SelectProposalTXs(types.LayerID, int) []types.TransactionID + SelectProposalTXs(types.LayerID, int, bool) []types.TransactionID + PredictBlock(types.LayerID) []types.TransactionID } type votesEncoder interface { @@ -570,6 +571,209 @@ func (pb *ProposalBuilder) initSignerData(ctx context.Context, ss *signerSession return nil } +func (pb *ProposalBuilder) initSignerDataFor(ctx context.Context, ss *signerSession, lid types.LayerID, nodeID types.NodeID) error { + if ss.session.epoch != lid.GetEpoch() { + ss.session = session{epoch: lid.GetEpoch()} + } + if ss.session.atx == types.EmptyATXID { + atxid, err := pb.atxs.GetIDByEpochAndNodeID(ctx, ss.session.epoch-1, nodeID) + switch { + case errors.Is(err, sql.ErrNotFound): + return errAtxNotAvailable + case err != nil: + return fmt.Errorf("get atx in epoch %v: %w", ss.session.epoch-1, err) + } + atx := pb.atxsdata.Get(ss.session.epoch, atxid) + if atx == nil { + return fmt.Errorf("missing atx in atxsdata %v", atxid) + } + ss.session.atx = atxid + ss.session.atxWeight = atx.Weight + ss.session.nonce = atx.Nonce + } + if ss.session.prev == 0 { + prev, err := ballots.LastInEpoch(pb.db, ss.session.atx, ss.session.epoch) + if err != nil && !errors.Is(err, sql.ErrNotFound) { + return err + } + if err == nil { + ss.session.prev = prev.Layer + } + } + if ss.session.ref == types.EmptyBallotID { + ballot, err := ballots.FirstInEpoch(pb.db, ss.session.atx, ss.session.epoch) + if err != nil && !errors.Is(err, sql.ErrNotFound) { + return fmt.Errorf("get refballot %w", err) + } + if errors.Is(err, sql.ErrNotFound) { + ss.session.beacon = pb.shared.beacon + ss.session.eligibilities.slots = proposals.MustGetNumEligibleSlots( + ss.session.atxWeight, + minweight.Select(lid.GetEpoch(), pb.cfg.minActiveSetWeight), + pb.shared.active.weight, + pb.cfg.layerSize, + pb.cfg.layersPerEpoch, + ) + } else { + if ballot.EpochData == nil { + return fmt.Errorf("atx %d created invalid first ballot", ss.session.atx) + } + ss.session.ref = ballot.ID() + ss.session.beacon = ballot.EpochData.Beacon + ss.session.eligibilities.slots = ballot.EpochData.EligibilityCount + } + } + return nil +} + +func (pb *ProposalBuilder) BuildFor(ctx context.Context, lid types.LayerID, nodeID types.NodeID) error { + if err := pb.initSharedData(lid); err != nil { + return err + } + + // don't accept registration in the middle of computing proposals + // pb.signers.mu.Lock() + // signers := maps.Values(pb.signers.signers) + // pb.signers.mu.Unlock() + signer := &signerSession{} + encodeVotesOnce := sync.OnceValues(func() (*types.Opinion, error) { + pb.tortoise.TallyVotes(ctx, lid) + // TODO(dshulyak) get rid from the EncodeVotesWithCurrent option in a followup + // there are some dependencies in the tests + opinion, err := pb.tortoise.EncodeVotes(ctx, tortoise.EncodeVotesWithCurrent(lid)) + if err != nil { + return nil, fmt.Errorf("encoding votes: %w", err) + } + return opinion, nil + }) + + calcMeshHashOnce := sync.OnceValue(func() types.Hash32 { + meshHash := pb.decideMeshHash(ctx, lid) + return meshHash + }) + + persistActiveSetOnce := sync.OnceValue(func() error { + err := activesets.Add(pb.db, pb.shared.active.id, &types.EpochActiveSet{ + Epoch: pb.shared.epoch, + Set: pb.shared.active.set, + }) + if err != nil && !errors.Is(err, sql.ErrObjectExists) { + return err + } + return nil + }) + + // Two stage pipeline, with the stages running in parallel. + // 1. Initializes signers. Runs limited number of goroutines because the initialization is CPU and DB bound. + // 2. Collects eligible signers' sessions from the stage 1 and creates and publishes proposals. + + // Used to pass eligible singers from stage 1 → 2. + // Buffered with capacity for all signers so that writes don't block. + eligible := make(chan *signerSession, 2) + + // Stage 1 + // Use a semaphore instead of eg.SetLimit so that the stage 2 starts immediately after + // scheduling all signers in the stage 1. Otherwise, stage 2 would wait for all stage 1 + // goroutines to at least start, which is not what we want. We want to start stage 2 as soon as possible. + // limiter := semaphore.NewWeighted(int64(pb.cfg.workersLimit)) + var eg errgroup.Group + // for _, ss := range signers { + eg.Go(func() error { + if err := pb.initSignerDataFor(ctx, signer, lid, nodeID); err != nil { + if errors.Is(err, errAtxNotAvailable) { + pb.logger.Debug("smesher doesn't have atx that targets this epoch", + log.ZContext(ctx), + zap.Uint32("epoch_id", signer.session.epoch.Uint32()), + ) + } else { + return err + } + } + if lid <= signer.session.prev { + return fmt.Errorf("layer %d was already built by signer %s", lid, nodeID.ShortString()) + } + signer.session.prev = lid + proofs := signer.session.eligibilities.slots + if proofs == 0 { + pb.logger.Debug("not eligible for proposal in layer", + log.ZContext(ctx), + zap.Uint32("layer_id", lid.Uint32()), + zap.Uint32("epoch_id", lid.GetEpoch().Uint32()), + ) + return nil + } + pb.logger.Debug("eligible for proposals in layer", + log.ZContext(ctx), + zap.Uint32("layer_id", lid.Uint32()), + zap.Uint32("epoch_id", lid.GetEpoch().Uint32()), + zap.Int("num proposals", int(proofs)), + ) + eligible <- signer // won't block + return nil + }) + //} + + var stage1Err error + go func() { + stage1Err = eg.Wait() + close(eligible) + }() + + // Stage 2 + eg2 := errgroup.Group{} + for ss := range eligible { + opinion, err := encodeVotesOnce() + if err != nil { + return err + } + + meshHash := calcMeshHashOnce() + + eg2.Go(func() error { + // needs to be saved before publishing, as we will query it in handler + if ss.session.ref == types.EmptyBallotID { + if err := persistActiveSetOnce(); err != nil { + return err + } + } + slots := ss.session.eligibilities.slots + + txs := pb.conState.SelectProposalTXs(lid, int(slots)) + + proposal := createPartialProposal( + &ss.session, + pb.shared.beacon, + pb.shared.active.set, + ss.signer, + lid, + txs, + opinion, + meshHash, + ) + if err := pb.publisher.Publish(ctx, pubsub.ProposalProtocol, codec.MustEncode(proposal)); err != nil { + pb.logger.Error("failed to publish proposal", + log.ZContext(ctx), + zap.Uint32("lid", proposal.Layer.Uint32()), + zap.Stringer("id", proposal.ID()), + zap.Error(err), + ) + } else { + pb.logger.Info("proposal created", + log.ZContext(ctx), + zap.Inline(proposal), + zap.Object("latency", &ss.latency), + ) + proposalBuild.Observe(ss.latency.total().Seconds()) + events.EmitProposal(ss.signer.NodeID(), lid, proposal.ID()) + events.ReportProposal(events.ProposalCreated, proposal) + } + return nil + }) + } + + return errors.Join(stage1Err, eg2.Wait()) +} + func (pb *ProposalBuilder) build(ctx context.Context, lid types.LayerID) error { buildStartTime := time.Now() if err := pb.initSharedData(lid); err != nil { diff --git a/txs/conservative_state.go b/txs/conservative_state.go index c252e540f5..6e84f4c9c4 100644 --- a/txs/conservative_state.go +++ b/txs/conservative_state.go @@ -87,7 +87,7 @@ func (cs *ConservativeState) getState(addr types.Address) (uint64, uint64) { } // SelectProposalTXs picks a specific number of random txs for miner to pack in a proposal. -func (cs *ConservativeState) SelectProposalTXs(lid types.LayerID, numEligibility int) []types.TransactionID { +func (cs *ConservativeState) SelectProposalTXs(lid types.LayerID, numEligibility int, shuffle bool) []types.TransactionID { logger := cs.logger.With(zap.Uint32("layer_id", lid.Uint32())) mi := newMempoolIterator(logger, cs.cache, cs.cfg.BlockGasLimit) predictedBlock, byAddrAndNonce := mi.PopAll() From 738938eefc88fa8bbc822342da0993d9aee909bc Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Mon, 21 Oct 2024 12:35:35 -0600 Subject: [PATCH 02/27] wip --- miner/proposal_builder.go | 81 ++++++++++++++++++++++++++------------- txs/conservative_state.go | 15 +++++++- 2 files changed, 68 insertions(+), 28 deletions(-) diff --git a/miner/proposal_builder.go b/miner/proposal_builder.go index b5dbf8907e..145355beef 100644 --- a/miner/proposal_builder.go +++ b/miner/proposal_builder.go @@ -41,8 +41,8 @@ var errAtxNotAvailable = errors.New("atx not available") //go:generate mockgen -typed -package=mocks -destination=./mocks/mocks.go -source=./proposal_builder.go type conservativeState interface { - SelectProposalTXs(types.LayerID, int, bool) []types.TransactionID - PredictBlock(types.LayerID) []types.TransactionID + SelectProposalTXs(types.LayerID, int) []types.TransactionID + PredictBlock(types.LayerID, int) []types.TransactionID } type votesEncoder interface { @@ -626,9 +626,9 @@ func (pb *ProposalBuilder) initSignerDataFor(ctx context.Context, ss *signerSess return nil } -func (pb *ProposalBuilder) BuildFor(ctx context.Context, lid types.LayerID, nodeID types.NodeID) error { +func (pb *ProposalBuilder) BuildFor(ctx context.Context, lid types.LayerID, nodeID types.NodeID) (*types.Proposal, error) { if err := pb.initSharedData(lid); err != nil { - return err + return nil, err } // don't accept registration in the middle of computing proposals @@ -719,12 +719,13 @@ func (pb *ProposalBuilder) BuildFor(ctx context.Context, lid types.LayerID, node close(eligible) }() + var prop *types.Proposal // Stage 2 eg2 := errgroup.Group{} for ss := range eligible { opinion, err := encodeVotesOnce() if err != nil { - return err + return nil, err } meshHash := calcMeshHashOnce() @@ -738,40 +739,28 @@ func (pb *ProposalBuilder) BuildFor(ctx context.Context, lid types.LayerID, node } slots := ss.session.eligibilities.slots - txs := pb.conState.SelectProposalTXs(lid, int(slots)) + txs := pb.conState.PredictBlock(lid, int(slots)) - proposal := createPartialProposal( + prop = createPartialProposal( &ss.session, pb.shared.beacon, pb.shared.active.set, - ss.signer, + nodeID, lid, txs, opinion, meshHash, ) - if err := pb.publisher.Publish(ctx, pubsub.ProposalProtocol, codec.MustEncode(proposal)); err != nil { - pb.logger.Error("failed to publish proposal", - log.ZContext(ctx), - zap.Uint32("lid", proposal.Layer.Uint32()), - zap.Stringer("id", proposal.ID()), - zap.Error(err), - ) - } else { - pb.logger.Info("proposal created", - log.ZContext(ctx), - zap.Inline(proposal), - zap.Object("latency", &ss.latency), - ) - proposalBuild.Observe(ss.latency.total().Seconds()) - events.EmitProposal(ss.signer.NodeID(), lid, proposal.ID()) - events.ReportProposal(events.ProposalCreated, proposal) - } + pb.logger.Info("proposal created", + log.ZContext(ctx), + zap.Inline(prop), + zap.Object("latency", &ss.latency), + ) return nil }) } - - return errors.Join(stage1Err, eg2.Wait()) + err := errors.Join(stage1Err, eg2.Wait()) + return prop, err } func (pb *ProposalBuilder) build(ctx context.Context, lid types.LayerID) error { @@ -948,6 +937,44 @@ func (pb *ProposalBuilder) build(ctx context.Context, lid types.LayerID) error { return errors.Join(stage1Err, eg2.Wait()) } +func createPartialProposal( + session *session, + beacon types.Beacon, + activeset types.ATXIDList, + smesher types.NodeID, + lid types.LayerID, + txs []types.TransactionID, + opinion *types.Opinion, + meshHash types.Hash32, +) *types.Proposal { + p := &types.Proposal{ + InnerProposal: types.InnerProposal{ + Ballot: types.Ballot{ + InnerBallot: types.InnerBallot{ + Layer: lid, + AtxID: session.atx, + OpinionHash: opinion.Hash, + }, + Votes: opinion.Votes, + // EligibilityProofs: eligibility, + }, + TxIDs: txs, + MeshHash: meshHash, + }, + } + if session.ref == types.EmptyBallotID { + p.Ballot.RefBallot = types.EmptyBallotID + p.Ballot.EpochData = &types.EpochData{ + ActiveSetHash: activeset.Hash(), + Beacon: beacon, + } + } else { + p.Ballot.RefBallot = session.ref + } + p.SmesherID = smesher + return p +} + func createProposal( session *session, beacon types.Beacon, diff --git a/txs/conservative_state.go b/txs/conservative_state.go index 6e84f4c9c4..f48471e57b 100644 --- a/txs/conservative_state.go +++ b/txs/conservative_state.go @@ -87,7 +87,7 @@ func (cs *ConservativeState) getState(addr types.Address) (uint64, uint64) { } // SelectProposalTXs picks a specific number of random txs for miner to pack in a proposal. -func (cs *ConservativeState) SelectProposalTXs(lid types.LayerID, numEligibility int, shuffle bool) []types.TransactionID { +func (cs *ConservativeState) SelectProposalTXs(lid types.LayerID, numEligibility int) []types.TransactionID { logger := cs.logger.With(zap.Uint32("layer_id", lid.Uint32())) mi := newMempoolIterator(logger, cs.cache, cs.cfg.BlockGasLimit) predictedBlock, byAddrAndNonce := mi.PopAll() @@ -95,6 +95,19 @@ func (cs *ConservativeState) SelectProposalTXs(lid types.LayerID, numEligibility return getProposalTXs(logger, numTXs, predictedBlock, byAddrAndNonce) } +func (cs *ConservativeState) PredictBlock(lid types.LayerID, numEligibility int) []types.TransactionID { + logger := cs.logger.With(zap.Uint32("layer_id", lid.Uint32())) + mi := newMempoolIterator(logger, cs.cache, cs.cfg.BlockGasLimit) + predictedBlock, _ := mi.PopAll() + numTXs := numEligibility * cs.cfg.NumTXsPerProposal + n := min(numTXs, len(predictedBlock)) + txs := make([]types.TransactionID, 0, n) + for i, tx := range predictedBlock[:n] { + txs[i] = tx.ID + } + return txs +} + func getProposalTXs( logger *zap.Logger, numTXs int, From 7b19bc9463dacd5aaed8fb709821315370f8a054 Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Mon, 21 Oct 2024 13:04:28 -0600 Subject: [PATCH 03/27] api and make gen --- api/node/client/client.gen.go | 105 ++++++++++++++++++++++++++++++++++ api/node/node_service.yaml | 26 +++++++++ api/node/server/mocks.go | 38 ++++++++++++ api/node/server/server.gen.go | 104 +++++++++++++++++++++++++++++++++ miner/mocks/mocks.go | 38 ++++++++++++ miner/proposal_builder.go | 3 - 6 files changed, 311 insertions(+), 3 deletions(-) diff --git a/api/node/client/client.gen.go b/api/node/client/client.gen.go index 5216946db2..63870f0b8c 100644 --- a/api/node/client/client.gen.go +++ b/api/node/client/client.gen.go @@ -130,6 +130,9 @@ type ClientInterface interface { // PostPoetWithBody request with any body PostPoetWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + // GetProposalLayerNode request + GetProposalLayerNode(ctx context.Context, layer externalRef0.LayerID, node externalRef0.NodeID, 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) } @@ -230,6 +233,18 @@ func (c *Client) PostPoetWithBody(ctx context.Context, contentType string, body return c.Client.Do(req) } +func (c *Client) GetProposalLayerNode(ctx context.Context, layer externalRef0.LayerID, node externalRef0.NodeID, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetProposalLayerNodeRequest(c.Server, layer, node) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + 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) if err != nil { @@ -530,6 +545,47 @@ func NewPostPoetRequestWithBody(server string, contentType string, body io.Reade return req, nil } +// NewGetProposalLayerNodeRequest generates requests for GetProposalLayerNode +func NewGetProposalLayerNodeRequest(server string, layer externalRef0.LayerID, node externalRef0.NodeID) (*http.Request, error) { + var err error + + var pathParam0 string + + 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 + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/proposal/%s/%s", pathParam0, pathParam1) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + 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) { var err error @@ -633,6 +689,9 @@ type ClientWithResponsesInterface interface { // PostPoetWithBodyWithResponse request with any body PostPoetWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostPoetResponse, error) + // GetProposalLayerNodeWithResponse request + GetProposalLayerNodeWithResponse(ctx context.Context, layer externalRef0.LayerID, node externalRef0.NodeID, reqEditors ...RequestEditorFn) (*GetProposalLayerNodeResponse, error) + // PostPublishProtocolWithBodyWithResponse request with any body PostPublishProtocolWithBodyWithResponse(ctx context.Context, protocol PostPublishProtocolParamsProtocol, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostPublishProtocolResponse, error) } @@ -810,6 +869,27 @@ func (r PostPoetResponse) StatusCode() int { return 0 } +type GetProposalLayerNodeResponse struct { + Body []byte + HTTPResponse *http.Response +} + +// Status returns HTTPResponse.Status +func (r GetProposalLayerNodeResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetProposalLayerNodeResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type PostPublishProtocolResponse struct { Body []byte HTTPResponse *http.Response @@ -903,6 +983,15 @@ func (c *ClientWithResponses) PostPoetWithBodyWithResponse(ctx context.Context, return ParsePostPoetResponse(rsp) } +// GetProposalLayerNodeWithResponse request returning *GetProposalLayerNodeResponse +func (c *ClientWithResponses) GetProposalLayerNodeWithResponse(ctx context.Context, layer externalRef0.LayerID, node externalRef0.NodeID, reqEditors ...RequestEditorFn) (*GetProposalLayerNodeResponse, error) { + rsp, err := c.GetProposalLayerNode(ctx, layer, node, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetProposalLayerNodeResponse(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...) @@ -1072,6 +1161,22 @@ func ParsePostPoetResponse(rsp *http.Response) (*PostPoetResponse, error) { return response, nil } +// 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 := &GetProposalLayerNodeResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + return response, nil +} + // ParsePostPublishProtocolResponse parses an HTTP response from a PostPublishProtocolWithResponse call func ParsePostPublishProtocolResponse(rsp *http.Response) (*PostPublishProtocolResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) diff --git a/api/node/node_service.yaml b/api/node/node_service.yaml index 97cbc7c079..f618c67cd2 100644 --- a/api/node/node_service.yaml +++ b/api/node/node_service.yaml @@ -223,4 +223,30 @@ paths: format: binary "204": description: did not find a message to retrieve + /proposal/{layer}/{node}: + get: + summary: Get a partial proposal for a given node in a layer + tags: + - "proposals" + parameters: + - in: path + name: layer + required: true + schema: + $ref: "models/components.yaml#/components/schemas/LayerID" + - in: path + name: node + required: true + schema: + $ref: "models/components.yaml#/components/schemas/NodeID" + responses: + "200": + description: successfully created a partial proposal + content: + application/octet-stream: + schema: + type: string + format: binary + "500": + description: could not generate proposal diff --git a/api/node/server/mocks.go b/api/node/server/mocks.go index 11ba872186..d968050499 100644 --- a/api/node/server/mocks.go +++ b/api/node/server/mocks.go @@ -102,6 +102,44 @@ func (m *Mockhare) EXPECT() *MockhareMockRecorder { return m.recorder } +// Beacon mocks base method. +func (m *Mockhare) Beacon(ctx context.Context, epoch types.EpochID) types.Beacon { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Beacon", ctx, epoch) + ret0, _ := ret[0].(types.Beacon) + return ret0 +} + +// Beacon indicates an expected call of Beacon. +func (mr *MockhareMockRecorder) Beacon(ctx, epoch any) *MockhareBeaconCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Beacon", reflect.TypeOf((*Mockhare)(nil).Beacon), ctx, epoch) + return &MockhareBeaconCall{Call: call} +} + +// MockhareBeaconCall wrap *gomock.Call +type MockhareBeaconCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockhareBeaconCall) Return(arg0 types.Beacon) *MockhareBeaconCall { + c.Call = c.Call.Return(arg0) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockhareBeaconCall) Do(f func(context.Context, types.EpochID) types.Beacon) *MockhareBeaconCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockhareBeaconCall) DoAndReturn(f func(context.Context, types.EpochID) types.Beacon) *MockhareBeaconCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + // MinerWeight mocks base method. func (m *Mockhare) MinerWeight(ctx context.Context, node types.NodeID, layer types.LayerID) uint64 { m.ctrl.T.Helper() diff --git a/api/node/server/server.gen.go b/api/node/server/server.gen.go index 8e80c59d1e..d48943aaa3 100644 --- a/api/node/server/server.gen.go +++ b/api/node/server/server.gen.go @@ -60,6 +60,9 @@ type ServerInterface interface { // Store PoET proof // (POST /poet) PostPoet(w http.ResponseWriter, r *http.Request) + // 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.NodeID) // Publish a blob in the given p2p protocol // (POST /publish/{protocol}) PostPublishProtocol(w http.ResponseWriter, r *http.Request, protocol PostPublishProtocolParamsProtocol) @@ -290,6 +293,40 @@ func (siw *ServerInterfaceWrapper) PostPoet(w http.ResponseWriter, r *http.Reque handler.ServeHTTP(w, r) } +// GetProposalLayerNode operation middleware +func (siw *ServerInterfaceWrapper) GetProposalLayerNode(w http.ResponseWriter, r *http.Request) { + + var err error + + // ------------- Path parameter "layer" ------------- + var layer externalRef0.LayerID + + 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: "layer", Err: err}) + return + } + + // ------------- Path parameter "node" ------------- + var node externalRef0.NodeID + + 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.GetProposalLayerNode(w, r, layer, node) + })) + + for _, middleware := range siw.HandlerMiddlewares { + handler = middleware(handler) + } + + handler.ServeHTTP(w, r) +} + // PostPublishProtocol operation middleware func (siw *ServerInterfaceWrapper) PostPublishProtocol(w http.ResponseWriter, r *http.Request) { @@ -443,6 +480,7 @@ func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.H m.HandleFunc("GET "+options.BaseURL+"/hare/total_weight/{layer}", wrapper.GetHareTotalWeightLayer) m.HandleFunc("GET "+options.BaseURL+"/hare/weight/{node_id}/{layer}", wrapper.GetHareWeightNodeIdLayer) m.HandleFunc("POST "+options.BaseURL+"/poet", wrapper.PostPoet) + m.HandleFunc("GET "+options.BaseURL+"/proposal/{layer}/{node}", wrapper.GetProposalLayerNode) m.HandleFunc("POST "+options.BaseURL+"/publish/{protocol}", wrapper.PostPublishProtocol) return m @@ -714,6 +752,42 @@ func (response PostPoet400PlaintextResponse) VisitPostPoetResponse(w http.Respon return err } +type GetProposalLayerNodeRequestObject struct { + Layer externalRef0.LayerID `json:"layer"` + Node externalRef0.NodeID `json:"node"` +} + +type GetProposalLayerNodeResponseObject interface { + VisitGetProposalLayerNodeResponse(w http.ResponseWriter) error +} + +type GetProposalLayerNode200ApplicationoctetStreamResponse struct { + Body io.Reader + ContentLength int64 +} + +func (response GetProposalLayerNode200ApplicationoctetStreamResponse) VisitGetProposalLayerNodeResponse(w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/octet-stream") + if response.ContentLength != 0 { + w.Header().Set("Content-Length", fmt.Sprint(response.ContentLength)) + } + w.WriteHeader(200) + + if closer, ok := response.Body.(io.ReadCloser); ok { + defer closer.Close() + } + _, err := io.Copy(w, response.Body) + 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 @@ -757,6 +831,9 @@ type StrictServerInterface interface { // Store PoET proof // (POST /poet) PostPoet(ctx context.Context, request PostPoetRequestObject) (PostPoetResponseObject, 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) @@ -1002,6 +1079,33 @@ func (sh *strictHandler) PostPoet(w http.ResponseWriter, r *http.Request) { } } +// GetProposalLayerNode operation middleware +func (sh *strictHandler) GetProposalLayerNode(w http.ResponseWriter, r *http.Request, layer externalRef0.LayerID, node externalRef0.NodeID) { + var request GetProposalLayerNodeRequestObject + + request.Layer = layer + request.Node = node + + handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, request interface{}) (interface{}, error) { + return sh.ssi.GetProposalLayerNode(ctx, request.(GetProposalLayerNodeRequestObject)) + } + for _, middleware := range sh.middlewares { + 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.(GetProposalLayerNodeResponseObject); ok { + if err := validResponse.VisitGetProposalLayerNodeResponse(w); err != nil { + sh.options.ResponseErrorHandlerFunc(w, r, err) + } + } else if response != nil { + sh.options.ResponseErrorHandlerFunc(w, r, fmt.Errorf("unexpected response type: %T", response)) + } +} + // PostPublishProtocol operation middleware func (sh *strictHandler) PostPublishProtocol(w http.ResponseWriter, r *http.Request, protocol PostPublishProtocolParamsProtocol) { var request PostPublishProtocolRequestObject diff --git a/miner/mocks/mocks.go b/miner/mocks/mocks.go index c873f06297..0e53009a8b 100644 --- a/miner/mocks/mocks.go +++ b/miner/mocks/mocks.go @@ -42,6 +42,44 @@ func (m *MockconservativeState) EXPECT() *MockconservativeStateMockRecorder { return m.recorder } +// PredictBlock mocks base method. +func (m *MockconservativeState) PredictBlock(arg0 types.LayerID, arg1 int) []types.TransactionID { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PredictBlock", arg0, arg1) + ret0, _ := ret[0].([]types.TransactionID) + return ret0 +} + +// PredictBlock indicates an expected call of PredictBlock. +func (mr *MockconservativeStateMockRecorder) PredictBlock(arg0, arg1 any) *MockconservativeStatePredictBlockCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PredictBlock", reflect.TypeOf((*MockconservativeState)(nil).PredictBlock), arg0, arg1) + return &MockconservativeStatePredictBlockCall{Call: call} +} + +// MockconservativeStatePredictBlockCall wrap *gomock.Call +type MockconservativeStatePredictBlockCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockconservativeStatePredictBlockCall) Return(arg0 []types.TransactionID) *MockconservativeStatePredictBlockCall { + c.Call = c.Call.Return(arg0) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockconservativeStatePredictBlockCall) Do(f func(types.LayerID, int) []types.TransactionID) *MockconservativeStatePredictBlockCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockconservativeStatePredictBlockCall) DoAndReturn(f func(types.LayerID, int) []types.TransactionID) *MockconservativeStatePredictBlockCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + // SelectProposalTXs mocks base method. func (m *MockconservativeState) SelectProposalTXs(arg0 types.LayerID, arg1 int) []types.TransactionID { m.ctrl.T.Helper() diff --git a/miner/proposal_builder.go b/miner/proposal_builder.go index 145355beef..34f37e50ef 100644 --- a/miner/proposal_builder.go +++ b/miner/proposal_builder.go @@ -632,9 +632,6 @@ func (pb *ProposalBuilder) BuildFor(ctx context.Context, lid types.LayerID, node } // don't accept registration in the middle of computing proposals - // pb.signers.mu.Lock() - // signers := maps.Values(pb.signers.signers) - // pb.signers.mu.Unlock() signer := &signerSession{} encodeVotesOnce := sync.OnceValues(func() (*types.Opinion, error) { pb.tortoise.TallyVotes(ctx, lid) From d80b5544cae3ecbb74c5425d2489a41f0a9f6a8f Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Tue, 22 Oct 2024 07:52:22 -0600 Subject: [PATCH 04/27] wip --- api/node/client/client.go | 25 +++ api/node/node_service.yaml | 2 + api/node/server/mocks.go | 62 +++++++ api/node/server/server.gen.go | 8 + api/node/server/server.go | 41 +++++ hare3/eligibility/oracle_scale.go | 65 +------- hare3/types_scale.go | 171 +------------------ hare4/eligibility/oracle_scale.go | 65 +------- hare4/types_scale.go | 219 ++---------------------- miner/proposal_builder.go | 9 +- miner/remote_proposals.go | 266 ++++++++++++++++++++++++++++++ 11 files changed, 435 insertions(+), 498 deletions(-) create mode 100644 miner/remote_proposals.go diff --git a/api/node/client/client.go b/api/node/client/client.go index d2206ac45a..2a609f7b87 100644 --- a/api/node/client/client.go +++ b/api/node/client/client.go @@ -190,3 +190,28 @@ func (s *NodeService) Beacon(ctx context.Context, epoch types.EpochID) (types.Be copy(v[:], bytes) return v, nil } + +func (s *NodeService) Proposal(ctx context.Context, layer types.LayerID, node types.NodeID) (*types.Proposal, error) { + resp, err := s.client.GetProposalLayerNode(ctx, externalRef0.LayerID(layer), node.String()) + if err != nil { + return nil, err + } + switch resp.StatusCode { + case http.StatusOK: + case http.StatusNoContent: + // special case - no error but also no proposal, means + // we're no eligibile this epoch with this node ID + return nil, nil + default: + return nil, fmt.Errorf("unexpected status: %s", resp.Status) + } + bytes, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("read all: %w", err) + } + + prop := types.Proposal{} + codec.MustDecode(bytes, &prop) + + return &prop, nil +} diff --git a/api/node/node_service.yaml b/api/node/node_service.yaml index f618c67cd2..2b1a0a3525 100644 --- a/api/node/node_service.yaml +++ b/api/node/node_service.yaml @@ -247,6 +247,8 @@ paths: schema: type: string format: binary + "204": + description: no eligibilities for this node in this epoch "500": description: could not generate proposal diff --git a/api/node/server/mocks.go b/api/node/server/mocks.go index d968050499..31852dc9ee 100644 --- a/api/node/server/mocks.go +++ b/api/node/server/mocks.go @@ -253,3 +253,65 @@ func (c *MockhareTotalWeightCall) DoAndReturn(f func(context.Context, types.Laye c.Call = c.Call.DoAndReturn(f) return c } + +// MockproposalBuilder is a mock of proposalBuilder interface. +type MockproposalBuilder struct { + ctrl *gomock.Controller + recorder *MockproposalBuilderMockRecorder +} + +// MockproposalBuilderMockRecorder is the mock recorder for MockproposalBuilder. +type MockproposalBuilderMockRecorder struct { + mock *MockproposalBuilder +} + +// NewMockproposalBuilder creates a new mock instance. +func NewMockproposalBuilder(ctrl *gomock.Controller) *MockproposalBuilder { + mock := &MockproposalBuilder{ctrl: ctrl} + mock.recorder = &MockproposalBuilderMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockproposalBuilder) EXPECT() *MockproposalBuilderMockRecorder { + return m.recorder +} + +// BuildFor mocks base method. +func (m *MockproposalBuilder) BuildFor(layer types.LayerID, node types.NodeID) (*types.Proposal, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "BuildFor", layer, node) + ret0, _ := ret[0].(*types.Proposal) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// BuildFor indicates an expected call of BuildFor. +func (mr *MockproposalBuilderMockRecorder) BuildFor(layer, node any) *MockproposalBuilderBuildForCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BuildFor", reflect.TypeOf((*MockproposalBuilder)(nil).BuildFor), layer, node) + return &MockproposalBuilderBuildForCall{Call: call} +} + +// MockproposalBuilderBuildForCall wrap *gomock.Call +type MockproposalBuilderBuildForCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockproposalBuilderBuildForCall) Return(arg0 *types.Proposal, arg1 error) *MockproposalBuilderBuildForCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockproposalBuilderBuildForCall) Do(f func(types.LayerID, types.NodeID) (*types.Proposal, error)) *MockproposalBuilderBuildForCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockproposalBuilderBuildForCall) DoAndReturn(f func(types.LayerID, types.NodeID) (*types.Proposal, error)) *MockproposalBuilderBuildForCall { + 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 d48943aaa3..4fd4fc5df7 100644 --- a/api/node/server/server.gen.go +++ b/api/node/server/server.gen.go @@ -780,6 +780,14 @@ func (response GetProposalLayerNode200ApplicationoctetStreamResponse) VisitGetPr return err } +type GetProposalLayerNode204Response struct { +} + +func (response GetProposalLayerNode204Response) VisitGetProposalLayerNodeResponse(w http.ResponseWriter) error { + w.WriteHeader(204) + return nil +} + type GetProposalLayerNode500Response struct { } diff --git a/api/node/server/server.go b/api/node/server/server.go index 3fc47b6704..d7a18746e4 100644 --- a/api/node/server/server.go +++ b/api/node/server/server.go @@ -35,11 +35,16 @@ type hare interface { Beacon(ctx context.Context, epoch types.EpochID) types.Beacon } +type proposalBuilder interface { + BuildFor(layer types.LayerID, node types.NodeID) (*types.Proposal, types.VRFPostIndex, error) +} + type Server struct { atxService activation.AtxService publisher pubsub.Publisher poetDB poetDB hare hare + proposals proposalBuilder logger *zap.Logger } @@ -50,6 +55,7 @@ func NewServer( publisher pubsub.Publisher, poetDB poetDB, hare hare, + proposals proposalBuilder, logger *zap.Logger, ) *Server { return &Server{ @@ -57,6 +63,7 @@ func NewServer( publisher: publisher, poetDB: poetDB, hare: hare, + proposals: proposals, logger: logger, } } @@ -284,3 +291,37 @@ func (s *Server) GetHareBeaconEpoch(ctx context.Context, request GetHareBeaconEp beacon := s.hare.Beacon(ctx, types.EpochID(request.Epoch)) return &beaconResp{b: beacon}, nil } + +type proposalResp struct { + buf []byte + nonce types.VRFPostIndex +} + +func (p *proposalResp) VisitGetProposalLayerNodeResponse(w http.ResponseWriter) error { + if buf == nil { + w.WriteHeader(204) + return nil + } + w.Header().Add("content-type", "application/octet-stream") + w.Header().Add("x-spacemesh-atx-nonce", fmt.Sprintf("%d", p.nonce)) + w.WriteHeader(200) + _, err := w.Write(p.buf) + return err +} + +func (s *Server) GetProposalLayerNode(ctx context.Context, request GetProposalLayerNodeRequestObject) (GetProposalLayerNodeResponseObject, error) { + hexBuf, err := hex.DecodeString(request.Node) + if err != nil { + return &proposalResp{}, err + } + id := types.BytesToNodeID(hexBuf) + + proposal, nonce, err := s.proposals.BuildFor(types.LayerID(request.Layer), id) + if err != nil { + return &proposalResp{}, err + } + if proposal.Ballot.EpochData.EligibilityCount == 0 { + return &proposalResp{}, nil + } + return &proposalResp{buf: codec.MustEncode(proposal), nonce: nonce}, err +} diff --git a/hare3/eligibility/oracle_scale.go b/hare3/eligibility/oracle_scale.go index 03f43bbfef..b4bc18113e 100644 --- a/hare3/eligibility/oracle_scale.go +++ b/hare3/eligibility/oracle_scale.go @@ -1,76 +1,15 @@ -// Code generated by github.com/spacemeshos/go-scale/scalegen. DO NOT EDIT. - -// nolint package eligibility import ( "github.com/spacemeshos/go-scale" - "github.com/spacemeshos/go-spacemesh/common/types" ) func (t *VrfMessage) EncodeScale(enc *scale.Encoder) (total int, err error) { - { - n, err := scale.EncodeCompact16(enc, uint16(t.Type)) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.EncodeByteArray(enc, t.Beacon[:]) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.EncodeCompact32(enc, uint32(t.Round)) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.EncodeCompact32(enc, uint32(t.Layer)) - if err != nil { - return total, err - } - total += n - } + return total, nil } func (t *VrfMessage) DecodeScale(dec *scale.Decoder) (total int, err error) { - { - field, n, err := scale.DecodeCompact16(dec) - if err != nil { - return total, err - } - total += n - t.Type = types.EligibilityType(field) - } - { - n, err := scale.DecodeByteArray(dec, t.Beacon[:]) - if err != nil { - return total, err - } - total += n - } - { - field, n, err := scale.DecodeCompact32(dec) - if err != nil { - return total, err - } - total += n - t.Round = uint32(field) - } - { - field, n, err := scale.DecodeCompact32(dec) - if err != nil { - return total, err - } - total += n - t.Layer = types.LayerID(field) - } + return total, nil } diff --git a/hare3/types_scale.go b/hare3/types_scale.go index 28e8b64035..710c27e745 100644 --- a/hare3/types_scale.go +++ b/hare3/types_scale.go @@ -1,200 +1,45 @@ -// Code generated by github.com/spacemeshos/go-scale/scalegen. DO NOT EDIT. - -// nolint package hare3 import ( "github.com/spacemeshos/go-scale" - "github.com/spacemeshos/go-spacemesh/common/types" ) func (t *IterRound) EncodeScale(enc *scale.Encoder) (total int, err error) { - { - n, err := scale.EncodeCompact8(enc, uint8(t.Iter)) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.EncodeCompact8(enc, uint8(t.Round)) - if err != nil { - return total, err - } - total += n - } + return total, nil } func (t *IterRound) DecodeScale(dec *scale.Decoder) (total int, err error) { - { - field, n, err := scale.DecodeCompact8(dec) - if err != nil { - return total, err - } - total += n - t.Iter = uint8(field) - } - { - field, n, err := scale.DecodeCompact8(dec) - if err != nil { - return total, err - } - total += n - t.Round = Round(field) - } + return total, nil } func (t *Value) EncodeScale(enc *scale.Encoder) (total int, err error) { - { - n, err := scale.EncodeStructSliceWithLimit(enc, t.Proposals, 2350) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.EncodeOption(enc, t.Reference) - if err != nil { - return total, err - } - total += n - } + return total, nil } func (t *Value) DecodeScale(dec *scale.Decoder) (total int, err error) { - { - field, n, err := scale.DecodeStructSliceWithLimit[types.ProposalID](dec, 2350) - if err != nil { - return total, err - } - total += n - t.Proposals = field - } - { - field, n, err := scale.DecodeOption[types.Hash32](dec) - if err != nil { - return total, err - } - total += n - t.Reference = field - } + return total, nil } func (t *Body) EncodeScale(enc *scale.Encoder) (total int, err error) { - { - n, err := scale.EncodeCompact32(enc, uint32(t.Layer)) - if err != nil { - return total, err - } - total += n - } - { - n, err := t.IterRound.EncodeScale(enc) - if err != nil { - return total, err - } - total += n - } - { - n, err := t.Value.EncodeScale(enc) - if err != nil { - return total, err - } - total += n - } - { - n, err := t.Eligibility.EncodeScale(enc) - if err != nil { - return total, err - } - total += n - } + return total, nil } func (t *Body) DecodeScale(dec *scale.Decoder) (total int, err error) { - { - field, n, err := scale.DecodeCompact32(dec) - if err != nil { - return total, err - } - total += n - t.Layer = types.LayerID(field) - } - { - n, err := t.IterRound.DecodeScale(dec) - if err != nil { - return total, err - } - total += n - } - { - n, err := t.Value.DecodeScale(dec) - if err != nil { - return total, err - } - total += n - } - { - n, err := t.Eligibility.DecodeScale(dec) - if err != nil { - return total, err - } - total += n - } + return total, nil } func (t *Message) EncodeScale(enc *scale.Encoder) (total int, err error) { - { - n, err := t.Body.EncodeScale(enc) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.EncodeByteArray(enc, t.Sender[:]) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.EncodeByteArray(enc, t.Signature[:]) - if err != nil { - return total, err - } - total += n - } + return total, nil } func (t *Message) DecodeScale(dec *scale.Decoder) (total int, err error) { - { - n, err := t.Body.DecodeScale(dec) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.DecodeByteArray(dec, t.Sender[:]) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.DecodeByteArray(dec, t.Signature[:]) - if err != nil { - return total, err - } - total += n - } + return total, nil } diff --git a/hare4/eligibility/oracle_scale.go b/hare4/eligibility/oracle_scale.go index 03f43bbfef..b4bc18113e 100644 --- a/hare4/eligibility/oracle_scale.go +++ b/hare4/eligibility/oracle_scale.go @@ -1,76 +1,15 @@ -// Code generated by github.com/spacemeshos/go-scale/scalegen. DO NOT EDIT. - -// nolint package eligibility import ( "github.com/spacemeshos/go-scale" - "github.com/spacemeshos/go-spacemesh/common/types" ) func (t *VrfMessage) EncodeScale(enc *scale.Encoder) (total int, err error) { - { - n, err := scale.EncodeCompact16(enc, uint16(t.Type)) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.EncodeByteArray(enc, t.Beacon[:]) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.EncodeCompact32(enc, uint32(t.Round)) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.EncodeCompact32(enc, uint32(t.Layer)) - if err != nil { - return total, err - } - total += n - } + return total, nil } func (t *VrfMessage) DecodeScale(dec *scale.Decoder) (total int, err error) { - { - field, n, err := scale.DecodeCompact16(dec) - if err != nil { - return total, err - } - total += n - t.Type = types.EligibilityType(field) - } - { - n, err := scale.DecodeByteArray(dec, t.Beacon[:]) - if err != nil { - return total, err - } - total += n - } - { - field, n, err := scale.DecodeCompact32(dec) - if err != nil { - return total, err - } - total += n - t.Round = uint32(field) - } - { - field, n, err := scale.DecodeCompact32(dec) - if err != nil { - return total, err - } - total += n - t.Layer = types.LayerID(field) - } + return total, nil } diff --git a/hare4/types_scale.go b/hare4/types_scale.go index 2f06ce6ff9..37fb3b6201 100644 --- a/hare4/types_scale.go +++ b/hare4/types_scale.go @@ -1,260 +1,65 @@ -// Code generated by github.com/spacemeshos/go-scale/scalegen. DO NOT EDIT. - -// nolint package hare4 import ( "github.com/spacemeshos/go-scale" - "github.com/spacemeshos/go-spacemesh/common/types" ) func (t *IterRound) EncodeScale(enc *scale.Encoder) (total int, err error) { - { - n, err := scale.EncodeCompact8(enc, uint8(t.Iter)) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.EncodeCompact8(enc, uint8(t.Round)) - if err != nil { - return total, err - } - total += n - } + return total, nil } func (t *IterRound) DecodeScale(dec *scale.Decoder) (total int, err error) { - { - field, n, err := scale.DecodeCompact8(dec) - if err != nil { - return total, err - } - total += n - t.Iter = uint8(field) - } - { - field, n, err := scale.DecodeCompact8(dec) - if err != nil { - return total, err - } - total += n - t.Round = Round(field) - } + return total, nil } func (t *Value) EncodeScale(enc *scale.Encoder) (total int, err error) { - { - n, err := scale.EncodeStructSliceWithLimit(enc, t.Proposals, 2350) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.EncodeOption(enc, t.Reference) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.EncodeStructSliceWithLimit(enc, t.CompactProposals, 2350) - if err != nil { - return total, err - } - total += n - } + return total, nil } func (t *Value) DecodeScale(dec *scale.Decoder) (total int, err error) { - { - field, n, err := scale.DecodeStructSliceWithLimit[types.ProposalID](dec, 2350) - if err != nil { - return total, err - } - total += n - t.Proposals = field - } - { - field, n, err := scale.DecodeOption[types.Hash32](dec) - if err != nil { - return total, err - } - total += n - t.Reference = field - } - { - field, n, err := scale.DecodeStructSliceWithLimit[types.CompactProposalID](dec, 2350) - if err != nil { - return total, err - } - total += n - t.CompactProposals = field - } + return total, nil } func (t *Body) EncodeScale(enc *scale.Encoder) (total int, err error) { - { - n, err := scale.EncodeCompact32(enc, uint32(t.Layer)) - if err != nil { - return total, err - } - total += n - } - { - n, err := t.IterRound.EncodeScale(enc) - if err != nil { - return total, err - } - total += n - } - { - n, err := t.Value.EncodeScale(enc) - if err != nil { - return total, err - } - total += n - } - { - n, err := t.Eligibility.EncodeScale(enc) - if err != nil { - return total, err - } - total += n - } + return total, nil } func (t *Body) DecodeScale(dec *scale.Decoder) (total int, err error) { - { - field, n, err := scale.DecodeCompact32(dec) - if err != nil { - return total, err - } - total += n - t.Layer = types.LayerID(field) - } - { - n, err := t.IterRound.DecodeScale(dec) - if err != nil { - return total, err - } - total += n - } - { - n, err := t.Value.DecodeScale(dec) - if err != nil { - return total, err - } - total += n - } - { - n, err := t.Eligibility.DecodeScale(dec) - if err != nil { - return total, err - } - total += n - } + return total, nil } func (t *Message) EncodeScale(enc *scale.Encoder) (total int, err error) { - { - n, err := t.Body.EncodeScale(enc) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.EncodeByteArray(enc, t.Sender[:]) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.EncodeByteArray(enc, t.Signature[:]) - if err != nil { - return total, err - } - total += n - } + return total, nil } func (t *Message) DecodeScale(dec *scale.Decoder) (total int, err error) { - { - n, err := t.Body.DecodeScale(dec) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.DecodeByteArray(dec, t.Sender[:]) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.DecodeByteArray(dec, t.Signature[:]) - if err != nil { - return total, err - } - total += n - } + return total, nil } func (t *CompactIdRequest) EncodeScale(enc *scale.Encoder) (total int, err error) { - { - n, err := scale.EncodeByteArray(enc, t.MsgId[:]) - if err != nil { - return total, err - } - total += n - } + return total, nil } func (t *CompactIdRequest) DecodeScale(dec *scale.Decoder) (total int, err error) { - { - n, err := scale.DecodeByteArray(dec, t.MsgId[:]) - if err != nil { - return total, err - } - total += n - } + return total, nil } func (t *CompactIdResponse) EncodeScale(enc *scale.Encoder) (total int, err error) { - { - n, err := scale.EncodeStructSliceWithLimit(enc, t.Ids, 2050) - if err != nil { - return total, err - } - total += n - } + return total, nil } func (t *CompactIdResponse) DecodeScale(dec *scale.Decoder) (total int, err error) { - { - field, n, err := scale.DecodeStructSliceWithLimit[types.ProposalID](dec, 2050) - if err != nil { - return total, err - } - total += n - t.Ids = field - } + return total, nil } diff --git a/miner/proposal_builder.go b/miner/proposal_builder.go index 34f37e50ef..3f9921584b 100644 --- a/miner/proposal_builder.go +++ b/miner/proposal_builder.go @@ -962,13 +962,18 @@ func createPartialProposal( if session.ref == types.EmptyBallotID { p.Ballot.RefBallot = types.EmptyBallotID p.Ballot.EpochData = &types.EpochData{ - ActiveSetHash: activeset.Hash(), - Beacon: beacon, + ActiveSetHash: activeset.Hash(), + Beacon: beacon, + EligibilityCount: session.eligibilities.slots, } } else { p.Ballot.RefBallot = session.ref } p.SmesherID = smesher + // p.Ballot.Signature = signer.Sign(signing.BALLOT, p.Ballot.SignedBytes()) + // p.Signature = signer.Sign(signing.PROPOSAL, p.SignedBytes()) + // p.MustInitialize() + return p } diff --git a/miner/remote_proposals.go b/miner/remote_proposals.go new file mode 100644 index 0000000000..33f641d5df --- /dev/null +++ b/miner/remote_proposals.go @@ -0,0 +1,266 @@ +package miner + +import ( + "context" + "fmt" + "runtime" + "sync" + + "github.com/spacemeshos/go-spacemesh/common/types" + "github.com/spacemeshos/go-spacemesh/log" + "github.com/spacemeshos/go-spacemesh/p2p/pubsub" + "github.com/spacemeshos/go-spacemesh/signing" + "go.uber.org/zap" + "golang.org/x/exp/maps" + "golang.org/x/sync/errgroup" +) + +// Opt for configuring ProposalBuilder. +// type Opt func(h *RemoteProposalBuilder) + +//// WithLayerSize defines the average number of proposal per layer. +//func WithLayerSize(size uint32) Opt { +//return func(pb *RemoteProposalBuilder) { +//pb.cfg.layerSize = size +//} +//} + +//// WithWorkersLimit configures paralelization factor for builder operation when working with +//// more than one signer. +//func WithWorkersLimit(limit int) Opt { +//return func(pb *RemoteProposalBuilder) { +//pb.cfg.workersLimit = limit +//} +//} + +//// WithLayerPerEpoch defines the number of layers per epoch. +//func WithLayerPerEpoch(layers uint32) Opt { +//return func(pb *RemoteProposalBuilder) { +//pb.cfg.layersPerEpoch = layers +//} +//} + +//func WithMinimalActiveSetWeight(weight []types.EpochMinimalActiveWeight) Opt { +//return func(pb *RemoteProposalBuilder) { +//pb.cfg.minActiveSetWeight = weight +//} +//} + +//// WithLogger defines the logger. +//func WithLogger(logger *zap.Logger) Opt { +//return func(pb *RemoteProposalBuilder) { +//pb.logger = logger +//} +//} + +//func WithHdist(dist uint32) Opt { +//return func(pb *RemoteProposalBuilder) { +//pb.cfg.hdist = dist +//} +//} + +//func WithNetworkDelay(delay time.Duration) Opt { +//return func(pb *RemoteProposalBuilder) { +//pb.cfg.networkDelay = delay +//} +//} + +//func WithMinGoodAtxPercent(percent int) Opt { +//return func(pb *RemoteProposalBuilder) { +//pb.cfg.goodAtxPercent = percent +//} +//} + +//// WithSigners guarantees that builder will start execution with provided list of signers. +//// Should be after logging. +//func WithSigners(signers ...*signing.EdSigner) Opt { +//return func(pb *RemoteProposalBuilder) { +//for _, signer := range signers { +//pb.Register(signer) +//} +//} +//} + +//// WithActivesetPreparation overwrites configuration for activeset preparation. +//func WithActivesetPreparation(prep ActiveSetPreparation) Opt { +//return func(pb *RemoteProposalBuilder) { +//pb.cfg.activeSet = prep +//} +//} + +//func withAtxSearch(p atxSearch) Opt { +//return func(pb *RemoteProposalBuilder) { +//pb.atxs = p +//} +//} + +type nodeService interface { + Proposal(ctx context.Context, layer types.LayerID, node types.NodeID) (*types.Proposal, error) +} +type RemoteProposalBuilder struct { + logger *zap.Logger + cfg config + + // db sql.Executor + // localdb sql.Executor + // atxsdata *atxsdata.Data + clock layerClock + publisher pubsub.Publisher + nodeSvc nodeService + // conState conservativeState + // tortoise votesEncoder + // syncer system.SyncStateProvider + // activeGen *activeSetGenerator + // atxs atxSearch + + signers struct { + mu sync.Mutex + signers map[types.NodeID]*signerSession + } + shared sharedSession +} + +// New creates a struct of block builder type. +func NewRemoteBuilder( + clock layerClock, + publisher pubsub.Publisher, + svc nodeService, +) *RemoteProposalBuilder { + pb := &RemoteProposalBuilder{ + cfg: config{ + workersLimit: runtime.NumCPU(), + activeSet: DefaultActiveSetPreparation(), + }, + logger: zap.NewNop(), + clock: clock, + publisher: publisher, + nodeSvc: svc, + signers: struct { + mu sync.Mutex + signers map[types.NodeID]*signerSession + }{ + signers: map[types.NodeID]*signerSession{}, + }, + } + return pb +} + +func (pb *RemoteProposalBuilder) Register(sig *signing.EdSigner) { + pb.signers.mu.Lock() + defer pb.signers.mu.Unlock() + _, exist := pb.signers.signers[sig.NodeID()] + if !exist { + pb.logger.Info("registered signing key", log.ZShortStringer("id", sig.NodeID())) + pb.signers.signers[sig.NodeID()] = &signerSession{ + signer: sig, + log: pb.logger.With(zap.String("signer", sig.NodeID().ShortString())), + } + } +} + +// Start the loop that listens to layers and build proposals. +func (pb *RemoteProposalBuilder) Run(ctx context.Context) error { + current := pb.clock.CurrentLayer() + next := current + 1 + pb.logger.Info("started", zap.Inline(&pb.cfg), zap.Uint32("next", next.Uint32())) + var eg errgroup.Group + prepareDisabled := pb.cfg.activeSet.Tries == 0 || pb.cfg.activeSet.RetryInterval == 0 + if prepareDisabled { + pb.logger.Warn("activeset will not be prepared in advance") + } + for { + select { + case <-ctx.Done(): + eg.Wait() + return nil + case <-pb.clock.AwaitLayer(next): + current := pb.clock.CurrentLayer() + if current.Before(next) { + pb.logger.Info("time sync detected, realigning ProposalBuilder", + zap.Uint32("current", current.Uint32()), + zap.Uint32("next", next.Uint32()), + ) + continue + } + next = current.Add(1) + ctx := log.WithNewSessionID(ctx) + + if current <= types.GetEffectiveGenesis() { + continue + } + + if err := pb.build(ctx, current); err != nil { + pb.logger.Warn("failed to build proposal", + log.ZContext(ctx), + zap.Uint32("lid", current.Uint32()), + zap.Error(err), + ) + } + } + } +} + +/* + p := &types.Proposal{ + InnerProposal: types.InnerProposal{ + Ballot: types.Ballot{ + InnerBallot: types.InnerBallot{ + Layer: lid, + AtxID: session.atx, + OpinionHash: opinion.Hash, + }, + Votes: opinion.Votes, + // EligibilityProofs: eligibility, + }, + TxIDs: txs, + MeshHash: meshHash, + }, + } + + if session.ref == types.EmptyBallotID { + p.Ballot.RefBallot = types.EmptyBallotID + p.Ballot.EpochData = &types.EpochData{ + ActiveSetHash: activeset.Hash(), + Beacon: beacon, + EligibilityCount: session.eligibilities.slots, + } + } else { + + p.Ballot.RefBallot = session.ref + } + +p.SmesherID = smesher +// p.Ballot.Signature = signer.Sign(signing.BALLOT, p.Ballot.SignedBytes()) +// p.Signature = signer.Sign(signing.PROPOSAL, p.SignedBytes()) +// p.MustInitialize() + +return p +*/ +func (pb *RemoteProposalBuilder) build(ctx context.Context, layer types.LayerID) error { + pb.signers.mu.Lock() + signers := maps.Values(pb.signers.signers) + pb.signers.mu.Unlock() + + for _, signer := range signers { + proposal, err := pb.nodeSvc.Proposal(ctx, layer, signer.signer.NodeID()) + if err != nil { + return fmt.Errorf("get partial proposal: %w", err) + } + + if proposal == nil { + // this node signer isn't eligible this epoch, continue + continue + } + + proofs := calcEligibilityProofs( + signer.signer.VRFSigner(), + layer.GetEpoch(), + proposal.Ballot.EpochData.Beacon, + ss.session.nonce, // atx nonce + proposal.Ballot.EpochData.EligibilityCount, + pb.cfg.layersPerEpoch, + ) + + } + return nil +} From db8920ab8deb97e3e1dc56353e63fd128581e0bc Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Tue, 22 Oct 2024 07:57:31 -0600 Subject: [PATCH 05/27] makegen --- api/node/server/mocks.go | 15 +- hare3/eligibility/oracle_scale.go | 65 ++++++++- hare3/types_scale.go | 171 +++++++++++++++++++++-- hare4/eligibility/oracle_scale.go | 65 ++++++++- hare4/types_scale.go | 219 ++++++++++++++++++++++++++++-- miner/remote_proposals.go | 4 +- 6 files changed, 507 insertions(+), 32 deletions(-) diff --git a/api/node/server/mocks.go b/api/node/server/mocks.go index 31852dc9ee..352731f7e8 100644 --- a/api/node/server/mocks.go +++ b/api/node/server/mocks.go @@ -278,12 +278,13 @@ func (m *MockproposalBuilder) EXPECT() *MockproposalBuilderMockRecorder { } // BuildFor mocks base method. -func (m *MockproposalBuilder) BuildFor(layer types.LayerID, node types.NodeID) (*types.Proposal, error) { +func (m *MockproposalBuilder) BuildFor(layer types.LayerID, node types.NodeID) (*types.Proposal, types.VRFPostIndex, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "BuildFor", layer, node) ret0, _ := ret[0].(*types.Proposal) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret1, _ := ret[1].(types.VRFPostIndex) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 } // BuildFor indicates an expected call of BuildFor. @@ -299,19 +300,19 @@ type MockproposalBuilderBuildForCall struct { } // Return rewrite *gomock.Call.Return -func (c *MockproposalBuilderBuildForCall) Return(arg0 *types.Proposal, arg1 error) *MockproposalBuilderBuildForCall { - c.Call = c.Call.Return(arg0, arg1) +func (c *MockproposalBuilderBuildForCall) Return(arg0 *types.Proposal, arg1 types.VRFPostIndex, arg2 error) *MockproposalBuilderBuildForCall { + c.Call = c.Call.Return(arg0, arg1, arg2) return c } // Do rewrite *gomock.Call.Do -func (c *MockproposalBuilderBuildForCall) Do(f func(types.LayerID, types.NodeID) (*types.Proposal, error)) *MockproposalBuilderBuildForCall { +func (c *MockproposalBuilderBuildForCall) Do(f func(types.LayerID, types.NodeID) (*types.Proposal, types.VRFPostIndex, error)) *MockproposalBuilderBuildForCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockproposalBuilderBuildForCall) DoAndReturn(f func(types.LayerID, types.NodeID) (*types.Proposal, error)) *MockproposalBuilderBuildForCall { +func (c *MockproposalBuilderBuildForCall) DoAndReturn(f func(types.LayerID, types.NodeID) (*types.Proposal, types.VRFPostIndex, error)) *MockproposalBuilderBuildForCall { c.Call = c.Call.DoAndReturn(f) return c } diff --git a/hare3/eligibility/oracle_scale.go b/hare3/eligibility/oracle_scale.go index b4bc18113e..03f43bbfef 100644 --- a/hare3/eligibility/oracle_scale.go +++ b/hare3/eligibility/oracle_scale.go @@ -1,15 +1,76 @@ +// Code generated by github.com/spacemeshos/go-scale/scalegen. DO NOT EDIT. + +// nolint package eligibility import ( "github.com/spacemeshos/go-scale" + "github.com/spacemeshos/go-spacemesh/common/types" ) func (t *VrfMessage) EncodeScale(enc *scale.Encoder) (total int, err error) { - + { + n, err := scale.EncodeCompact16(enc, uint16(t.Type)) + if err != nil { + return total, err + } + total += n + } + { + n, err := scale.EncodeByteArray(enc, t.Beacon[:]) + if err != nil { + return total, err + } + total += n + } + { + n, err := scale.EncodeCompact32(enc, uint32(t.Round)) + if err != nil { + return total, err + } + total += n + } + { + n, err := scale.EncodeCompact32(enc, uint32(t.Layer)) + if err != nil { + return total, err + } + total += n + } return total, nil } func (t *VrfMessage) DecodeScale(dec *scale.Decoder) (total int, err error) { - + { + field, n, err := scale.DecodeCompact16(dec) + if err != nil { + return total, err + } + total += n + t.Type = types.EligibilityType(field) + } + { + n, err := scale.DecodeByteArray(dec, t.Beacon[:]) + if err != nil { + return total, err + } + total += n + } + { + field, n, err := scale.DecodeCompact32(dec) + if err != nil { + return total, err + } + total += n + t.Round = uint32(field) + } + { + field, n, err := scale.DecodeCompact32(dec) + if err != nil { + return total, err + } + total += n + t.Layer = types.LayerID(field) + } return total, nil } diff --git a/hare3/types_scale.go b/hare3/types_scale.go index 710c27e745..28e8b64035 100644 --- a/hare3/types_scale.go +++ b/hare3/types_scale.go @@ -1,45 +1,200 @@ +// Code generated by github.com/spacemeshos/go-scale/scalegen. DO NOT EDIT. + +// nolint package hare3 import ( "github.com/spacemeshos/go-scale" + "github.com/spacemeshos/go-spacemesh/common/types" ) func (t *IterRound) EncodeScale(enc *scale.Encoder) (total int, err error) { - + { + n, err := scale.EncodeCompact8(enc, uint8(t.Iter)) + if err != nil { + return total, err + } + total += n + } + { + n, err := scale.EncodeCompact8(enc, uint8(t.Round)) + if err != nil { + return total, err + } + total += n + } return total, nil } func (t *IterRound) DecodeScale(dec *scale.Decoder) (total int, err error) { - + { + field, n, err := scale.DecodeCompact8(dec) + if err != nil { + return total, err + } + total += n + t.Iter = uint8(field) + } + { + field, n, err := scale.DecodeCompact8(dec) + if err != nil { + return total, err + } + total += n + t.Round = Round(field) + } return total, nil } func (t *Value) EncodeScale(enc *scale.Encoder) (total int, err error) { - + { + n, err := scale.EncodeStructSliceWithLimit(enc, t.Proposals, 2350) + if err != nil { + return total, err + } + total += n + } + { + n, err := scale.EncodeOption(enc, t.Reference) + if err != nil { + return total, err + } + total += n + } return total, nil } func (t *Value) DecodeScale(dec *scale.Decoder) (total int, err error) { - + { + field, n, err := scale.DecodeStructSliceWithLimit[types.ProposalID](dec, 2350) + if err != nil { + return total, err + } + total += n + t.Proposals = field + } + { + field, n, err := scale.DecodeOption[types.Hash32](dec) + if err != nil { + return total, err + } + total += n + t.Reference = field + } return total, nil } func (t *Body) EncodeScale(enc *scale.Encoder) (total int, err error) { - + { + n, err := scale.EncodeCompact32(enc, uint32(t.Layer)) + if err != nil { + return total, err + } + total += n + } + { + n, err := t.IterRound.EncodeScale(enc) + if err != nil { + return total, err + } + total += n + } + { + n, err := t.Value.EncodeScale(enc) + if err != nil { + return total, err + } + total += n + } + { + n, err := t.Eligibility.EncodeScale(enc) + if err != nil { + return total, err + } + total += n + } return total, nil } func (t *Body) DecodeScale(dec *scale.Decoder) (total int, err error) { - + { + field, n, err := scale.DecodeCompact32(dec) + if err != nil { + return total, err + } + total += n + t.Layer = types.LayerID(field) + } + { + n, err := t.IterRound.DecodeScale(dec) + if err != nil { + return total, err + } + total += n + } + { + n, err := t.Value.DecodeScale(dec) + if err != nil { + return total, err + } + total += n + } + { + n, err := t.Eligibility.DecodeScale(dec) + if err != nil { + return total, err + } + total += n + } return total, nil } func (t *Message) EncodeScale(enc *scale.Encoder) (total int, err error) { - + { + n, err := t.Body.EncodeScale(enc) + if err != nil { + return total, err + } + total += n + } + { + n, err := scale.EncodeByteArray(enc, t.Sender[:]) + if err != nil { + return total, err + } + total += n + } + { + n, err := scale.EncodeByteArray(enc, t.Signature[:]) + if err != nil { + return total, err + } + total += n + } return total, nil } func (t *Message) DecodeScale(dec *scale.Decoder) (total int, err error) { - + { + n, err := t.Body.DecodeScale(dec) + if err != nil { + return total, err + } + total += n + } + { + n, err := scale.DecodeByteArray(dec, t.Sender[:]) + if err != nil { + return total, err + } + total += n + } + { + n, err := scale.DecodeByteArray(dec, t.Signature[:]) + if err != nil { + return total, err + } + total += n + } return total, nil } diff --git a/hare4/eligibility/oracle_scale.go b/hare4/eligibility/oracle_scale.go index b4bc18113e..03f43bbfef 100644 --- a/hare4/eligibility/oracle_scale.go +++ b/hare4/eligibility/oracle_scale.go @@ -1,15 +1,76 @@ +// Code generated by github.com/spacemeshos/go-scale/scalegen. DO NOT EDIT. + +// nolint package eligibility import ( "github.com/spacemeshos/go-scale" + "github.com/spacemeshos/go-spacemesh/common/types" ) func (t *VrfMessage) EncodeScale(enc *scale.Encoder) (total int, err error) { - + { + n, err := scale.EncodeCompact16(enc, uint16(t.Type)) + if err != nil { + return total, err + } + total += n + } + { + n, err := scale.EncodeByteArray(enc, t.Beacon[:]) + if err != nil { + return total, err + } + total += n + } + { + n, err := scale.EncodeCompact32(enc, uint32(t.Round)) + if err != nil { + return total, err + } + total += n + } + { + n, err := scale.EncodeCompact32(enc, uint32(t.Layer)) + if err != nil { + return total, err + } + total += n + } return total, nil } func (t *VrfMessage) DecodeScale(dec *scale.Decoder) (total int, err error) { - + { + field, n, err := scale.DecodeCompact16(dec) + if err != nil { + return total, err + } + total += n + t.Type = types.EligibilityType(field) + } + { + n, err := scale.DecodeByteArray(dec, t.Beacon[:]) + if err != nil { + return total, err + } + total += n + } + { + field, n, err := scale.DecodeCompact32(dec) + if err != nil { + return total, err + } + total += n + t.Round = uint32(field) + } + { + field, n, err := scale.DecodeCompact32(dec) + if err != nil { + return total, err + } + total += n + t.Layer = types.LayerID(field) + } return total, nil } diff --git a/hare4/types_scale.go b/hare4/types_scale.go index 37fb3b6201..2f06ce6ff9 100644 --- a/hare4/types_scale.go +++ b/hare4/types_scale.go @@ -1,65 +1,260 @@ +// Code generated by github.com/spacemeshos/go-scale/scalegen. DO NOT EDIT. + +// nolint package hare4 import ( "github.com/spacemeshos/go-scale" + "github.com/spacemeshos/go-spacemesh/common/types" ) func (t *IterRound) EncodeScale(enc *scale.Encoder) (total int, err error) { - + { + n, err := scale.EncodeCompact8(enc, uint8(t.Iter)) + if err != nil { + return total, err + } + total += n + } + { + n, err := scale.EncodeCompact8(enc, uint8(t.Round)) + if err != nil { + return total, err + } + total += n + } return total, nil } func (t *IterRound) DecodeScale(dec *scale.Decoder) (total int, err error) { - + { + field, n, err := scale.DecodeCompact8(dec) + if err != nil { + return total, err + } + total += n + t.Iter = uint8(field) + } + { + field, n, err := scale.DecodeCompact8(dec) + if err != nil { + return total, err + } + total += n + t.Round = Round(field) + } return total, nil } func (t *Value) EncodeScale(enc *scale.Encoder) (total int, err error) { - + { + n, err := scale.EncodeStructSliceWithLimit(enc, t.Proposals, 2350) + if err != nil { + return total, err + } + total += n + } + { + n, err := scale.EncodeOption(enc, t.Reference) + if err != nil { + return total, err + } + total += n + } + { + n, err := scale.EncodeStructSliceWithLimit(enc, t.CompactProposals, 2350) + if err != nil { + return total, err + } + total += n + } return total, nil } func (t *Value) DecodeScale(dec *scale.Decoder) (total int, err error) { - + { + field, n, err := scale.DecodeStructSliceWithLimit[types.ProposalID](dec, 2350) + if err != nil { + return total, err + } + total += n + t.Proposals = field + } + { + field, n, err := scale.DecodeOption[types.Hash32](dec) + if err != nil { + return total, err + } + total += n + t.Reference = field + } + { + field, n, err := scale.DecodeStructSliceWithLimit[types.CompactProposalID](dec, 2350) + if err != nil { + return total, err + } + total += n + t.CompactProposals = field + } return total, nil } func (t *Body) EncodeScale(enc *scale.Encoder) (total int, err error) { - + { + n, err := scale.EncodeCompact32(enc, uint32(t.Layer)) + if err != nil { + return total, err + } + total += n + } + { + n, err := t.IterRound.EncodeScale(enc) + if err != nil { + return total, err + } + total += n + } + { + n, err := t.Value.EncodeScale(enc) + if err != nil { + return total, err + } + total += n + } + { + n, err := t.Eligibility.EncodeScale(enc) + if err != nil { + return total, err + } + total += n + } return total, nil } func (t *Body) DecodeScale(dec *scale.Decoder) (total int, err error) { - + { + field, n, err := scale.DecodeCompact32(dec) + if err != nil { + return total, err + } + total += n + t.Layer = types.LayerID(field) + } + { + n, err := t.IterRound.DecodeScale(dec) + if err != nil { + return total, err + } + total += n + } + { + n, err := t.Value.DecodeScale(dec) + if err != nil { + return total, err + } + total += n + } + { + n, err := t.Eligibility.DecodeScale(dec) + if err != nil { + return total, err + } + total += n + } return total, nil } func (t *Message) EncodeScale(enc *scale.Encoder) (total int, err error) { - + { + n, err := t.Body.EncodeScale(enc) + if err != nil { + return total, err + } + total += n + } + { + n, err := scale.EncodeByteArray(enc, t.Sender[:]) + if err != nil { + return total, err + } + total += n + } + { + n, err := scale.EncodeByteArray(enc, t.Signature[:]) + if err != nil { + return total, err + } + total += n + } return total, nil } func (t *Message) DecodeScale(dec *scale.Decoder) (total int, err error) { - + { + n, err := t.Body.DecodeScale(dec) + if err != nil { + return total, err + } + total += n + } + { + n, err := scale.DecodeByteArray(dec, t.Sender[:]) + if err != nil { + return total, err + } + total += n + } + { + n, err := scale.DecodeByteArray(dec, t.Signature[:]) + if err != nil { + return total, err + } + total += n + } return total, nil } func (t *CompactIdRequest) EncodeScale(enc *scale.Encoder) (total int, err error) { - + { + n, err := scale.EncodeByteArray(enc, t.MsgId[:]) + if err != nil { + return total, err + } + total += n + } return total, nil } func (t *CompactIdRequest) DecodeScale(dec *scale.Decoder) (total int, err error) { - + { + n, err := scale.DecodeByteArray(dec, t.MsgId[:]) + if err != nil { + return total, err + } + total += n + } return total, nil } func (t *CompactIdResponse) EncodeScale(enc *scale.Encoder) (total int, err error) { - + { + n, err := scale.EncodeStructSliceWithLimit(enc, t.Ids, 2050) + if err != nil { + return total, err + } + total += n + } return total, nil } func (t *CompactIdResponse) DecodeScale(dec *scale.Decoder) (total int, err error) { - + { + field, n, err := scale.DecodeStructSliceWithLimit[types.ProposalID](dec, 2050) + if err != nil { + return total, err + } + total += n + t.Ids = field + } return total, nil } diff --git a/miner/remote_proposals.go b/miner/remote_proposals.go index 33f641d5df..28522901de 100644 --- a/miner/remote_proposals.go +++ b/miner/remote_proposals.go @@ -256,11 +256,13 @@ func (pb *RemoteProposalBuilder) build(ctx context.Context, layer types.LayerID) signer.signer.VRFSigner(), layer.GetEpoch(), proposal.Ballot.EpochData.Beacon, - ss.session.nonce, // atx nonce + 111, // ss.session.nonce, // atx nonce proposal.Ballot.EpochData.EligibilityCount, pb.cfg.layersPerEpoch, ) + fmt.Println(proofs) + } return nil } From 315e4982b0cde6be8a0467d3e72f6943b06c4316 Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Tue, 22 Oct 2024 08:21:52 -0600 Subject: [PATCH 06/27] wip --- api/node/client/client.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/api/node/client/client.go b/api/node/client/client.go index 2a609f7b87..0c939983c9 100644 --- a/api/node/client/client.go +++ b/api/node/client/client.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/hex" + "errors" "fmt" "io" "net/http" @@ -191,27 +192,35 @@ func (s *NodeService) Beacon(ctx context.Context, epoch types.EpochID) (types.Be return v, nil } -func (s *NodeService) Proposal(ctx context.Context, layer types.LayerID, node types.NodeID) (*types.Proposal, error) { +func (s *NodeService) Proposal(ctx context.Context, layer types.LayerID, node types.NodeID) (*types.Proposal, uint64, error) { resp, err := s.client.GetProposalLayerNode(ctx, externalRef0.LayerID(layer), node.String()) if err != nil { - return nil, err + return nil, 0, err } switch resp.StatusCode { case http.StatusOK: case http.StatusNoContent: // special case - no error but also no proposal, means // we're no eligibile this epoch with this node ID - return nil, nil + return nil, 0, nil default: - return nil, fmt.Errorf("unexpected status: %s", resp.Status) + return nil, 0, fmt.Errorf("unexpected status: %s", resp.Status) } bytes, err := io.ReadAll(resp.Body) if err != nil { - return nil, fmt.Errorf("read all: %w", err) + return nil, 0, fmt.Errorf("read all: %w", err) } prop := types.Proposal{} codec.MustDecode(bytes, &prop) - return &prop, nil + atxNonce := resp.Header.Get("x-spacemesh-atx-nonce") + if atxNonce == "" { + return nil, 0, errors.New("atx nonce header not found") + } + nonce, err := strconv.ParseUint(atxNonce, 10, 64) + if err != nil { + return nil, 0, fmt.Errorf("nonce parse: %w", err) + } + return &prop, nonce, nil } From cedb73b05a27c01e36c415e817ccac3737713a79 Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Tue, 22 Oct 2024 11:00:50 -0600 Subject: [PATCH 07/27] wip --- api/node/server/server.go | 6 +- miner/proposal_builder.go | 8 +- miner/remote_proposals.go | 6 +- node/node.go | 158 +++++++++++++++++++++----------------- 4 files changed, 98 insertions(+), 80 deletions(-) diff --git a/api/node/server/server.go b/api/node/server/server.go index d7a18746e4..2ee6cbcfa8 100644 --- a/api/node/server/server.go +++ b/api/node/server/server.go @@ -36,7 +36,7 @@ type hare interface { } type proposalBuilder interface { - BuildFor(layer types.LayerID, node types.NodeID) (*types.Proposal, types.VRFPostIndex, error) + BuildFor(ctx context.Context, layer types.LayerID, node types.NodeID) (*types.Proposal, types.VRFPostIndex, error) } type Server struct { @@ -298,7 +298,7 @@ type proposalResp struct { } func (p *proposalResp) VisitGetProposalLayerNodeResponse(w http.ResponseWriter) error { - if buf == nil { + if p.buf == nil { w.WriteHeader(204) return nil } @@ -316,7 +316,7 @@ func (s *Server) GetProposalLayerNode(ctx context.Context, request GetProposalLa } id := types.BytesToNodeID(hexBuf) - proposal, nonce, err := s.proposals.BuildFor(types.LayerID(request.Layer), id) + proposal, nonce, err := s.proposals.BuildFor(ctx, types.LayerID(request.Layer), id) if err != nil { return &proposalResp{}, err } diff --git a/miner/proposal_builder.go b/miner/proposal_builder.go index 3f9921584b..31d564d331 100644 --- a/miner/proposal_builder.go +++ b/miner/proposal_builder.go @@ -626,9 +626,9 @@ func (pb *ProposalBuilder) initSignerDataFor(ctx context.Context, ss *signerSess return nil } -func (pb *ProposalBuilder) BuildFor(ctx context.Context, lid types.LayerID, nodeID types.NodeID) (*types.Proposal, error) { +func (pb *ProposalBuilder) BuildFor(ctx context.Context, lid types.LayerID, nodeID types.NodeID) (*types.Proposal, types.VRFPostIndex, error) { if err := pb.initSharedData(lid); err != nil { - return nil, err + return nil, 0, err } // don't accept registration in the middle of computing proposals @@ -722,7 +722,7 @@ func (pb *ProposalBuilder) BuildFor(ctx context.Context, lid types.LayerID, node for ss := range eligible { opinion, err := encodeVotesOnce() if err != nil { - return nil, err + return nil, 0, err } meshHash := calcMeshHashOnce() @@ -757,7 +757,7 @@ func (pb *ProposalBuilder) BuildFor(ctx context.Context, lid types.LayerID, node }) } err := errors.Join(stage1Err, eg2.Wait()) - return prop, err + return prop, 0, err } func (pb *ProposalBuilder) build(ctx context.Context, lid types.LayerID) error { diff --git a/miner/remote_proposals.go b/miner/remote_proposals.go index 28522901de..0400e53715 100644 --- a/miner/remote_proposals.go +++ b/miner/remote_proposals.go @@ -95,7 +95,7 @@ import ( //} type nodeService interface { - Proposal(ctx context.Context, layer types.LayerID, node types.NodeID) (*types.Proposal, error) + Proposal(ctx context.Context, layer types.LayerID, node types.NodeID) (*types.Proposal, uint64, error) } type RemoteProposalBuilder struct { logger *zap.Logger @@ -242,7 +242,7 @@ func (pb *RemoteProposalBuilder) build(ctx context.Context, layer types.LayerID) pb.signers.mu.Unlock() for _, signer := range signers { - proposal, err := pb.nodeSvc.Proposal(ctx, layer, signer.signer.NodeID()) + proposal, nonce, err := pb.nodeSvc.Proposal(ctx, layer, signer.signer.NodeID()) if err != nil { return fmt.Errorf("get partial proposal: %w", err) } @@ -256,7 +256,7 @@ func (pb *RemoteProposalBuilder) build(ctx context.Context, layer types.LayerID) signer.signer.VRFSigner(), layer.GetEpoch(), proposal.Ballot.EpochData.Beacon, - 111, // ss.session.nonce, // atx nonce + types.VRFPostIndex(nonce), // ss.session.nonce, // atx nonce proposal.Ballot.EpochData.EligibilityCount, pb.cfg.layersPerEpoch, ) diff --git a/node/node.go b/node/node.go index 0d01697363..a931e33236 100644 --- a/node/node.go +++ b/node/node.go @@ -373,54 +373,55 @@ func New(opts ...Option) *App { // App is the cli app singleton. type App struct { *cobra.Command - fileLock *flock.Flock - signers []*signing.EdSigner - Config *config.Config - db sql.StateDatabase - cachedDB *datastore.CachedDB - dbMetrics *dbmetrics.DBMetricsCollector - localDB sql.LocalDatabase - grpcPublicServer *grpcserver.Server - grpcPrivateServer *grpcserver.Server - grpcPostServer *grpcserver.Server - grpcTLSServer *grpcserver.Server - jsonAPIServer *grpcserver.JSONHTTPServer - nodeServiceServer *http.Server - grpcServices map[grpcserver.Service]grpcserver.ServiceAPI - pprofService *http.Server - profilerService *pyroscope.Profiler - syncer *syncer.Syncer - proposalListener *proposals.Handler - proposalBuilder *miner.ProposalBuilder - mesh *mesh.Mesh - atxsdata *atxsdata.Data - clock *timesync.NodeClock - hare3 *hare3.Hare - hare4 *hare4.Hare - remoteHare *hare3.RemoteHare - hareResultsChan chan hare4.ConsensusOutput - hOracle *eligibility.Oracle - blockGen *blocks.Generator - certifier *blocks.Certifier - atxBuilder *activation.Builder - nipostBuilder *activation.NIPostBuilder - atxHandler *activation.Handler - txHandler *txs.TxHandler - validator *activation.Validator - edVerifier *signing.EdVerifier - beaconProtocol *beacon.ProtocolDriver - log log.Log - syncLogger log.Log - svm *vm.VM - conState *txs.ConservativeState - fetcher *fetch.Fetch - ptimesync *peersync.Sync - tortoise *tortoise.Tortoise - updater *bootstrap.Updater - poetDb *activation.PoetDb - postVerifier activation.PostVerifier - postSupervisor *activation.PostSupervisor - errCh chan error + fileLock *flock.Flock + signers []*signing.EdSigner + Config *config.Config + db sql.StateDatabase + cachedDB *datastore.CachedDB + dbMetrics *dbmetrics.DBMetricsCollector + localDB sql.LocalDatabase + grpcPublicServer *grpcserver.Server + grpcPrivateServer *grpcserver.Server + grpcPostServer *grpcserver.Server + grpcTLSServer *grpcserver.Server + jsonAPIServer *grpcserver.JSONHTTPServer + nodeServiceServer *http.Server + grpcServices map[grpcserver.Service]grpcserver.ServiceAPI + pprofService *http.Server + profilerService *pyroscope.Profiler + syncer *syncer.Syncer + proposalListener *proposals.Handler + proposalBuilder *miner.ProposalBuilder + remoteProposalBuilder *miner.RemoteProposalBuilder + mesh *mesh.Mesh + atxsdata *atxsdata.Data + clock *timesync.NodeClock + hare3 *hare3.Hare + hare4 *hare4.Hare + remoteHare *hare3.RemoteHare + hareResultsChan chan hare4.ConsensusOutput + hOracle *eligibility.Oracle + blockGen *blocks.Generator + certifier *blocks.Certifier + atxBuilder *activation.Builder + nipostBuilder *activation.NIPostBuilder + atxHandler *activation.Handler + txHandler *txs.TxHandler + validator *activation.Validator + edVerifier *signing.EdVerifier + beaconProtocol *beacon.ProtocolDriver + log log.Log + syncLogger log.Log + svm *vm.VM + conState *txs.ConservativeState + fetcher *fetch.Fetch + ptimesync *peersync.Sync + tortoise *tortoise.Tortoise + updater *bootstrap.Updater + poetDb *activation.PoetDb + postVerifier activation.PostVerifier + postSupervisor *activation.PostSupervisor + errCh chan error host *p2p.Host @@ -1029,26 +1030,34 @@ func (app *App) initServices(ctx context.Context) error { if app.Config.MinerGoodAtxsPercent > 0 { minerGoodAtxPct = app.Config.MinerGoodAtxsPercent } - proposalBuilder := miner.New( - app.clock, - app.db, - app.localDB, - app.atxsdata, - app.host, - trtl, - newSyncer, - app.conState, - miner.WithLayerSize(layerSize), - miner.WithLayerPerEpoch(layersPerEpoch), - miner.WithMinimalActiveSetWeight(app.Config.Tortoise.MinimalActiveSetWeight), - miner.WithHdist(app.Config.Tortoise.Hdist), - miner.WithNetworkDelay(app.Config.ATXGradeDelay), - miner.WithMinGoodAtxPercent(minerGoodAtxPct), - miner.WithLogger(app.addLogger(ProposalBuilderLogger, lg).Zap()), - miner.WithActivesetPreparation(app.Config.ActiveSet), - ) - for _, sig := range app.signers { - proposalBuilder.Register(sig) + var proposalBuilder *miner.ProposalBuilder + var remoteProposalBuilder *miner.RemoteProposalBuilder + if nodeServiceClient != nil { + remoteProposalBuilder = miner.NewRemoteBuilder(app.clock, nodeServiceClient, nodeServiceClient) + app.remoteProposalBuilder = remoteProposalBuilder + } else { + proposalBuilder = miner.New( + app.clock, + app.db, + app.localDB, + app.atxsdata, + app.host, + trtl, + newSyncer, + app.conState, + miner.WithLayerSize(layerSize), + miner.WithLayerPerEpoch(layersPerEpoch), + miner.WithMinimalActiveSetWeight(app.Config.Tortoise.MinimalActiveSetWeight), + miner.WithHdist(app.Config.Tortoise.Hdist), + miner.WithNetworkDelay(app.Config.ATXGradeDelay), + miner.WithMinGoodAtxPercent(minerGoodAtxPct), + miner.WithLogger(app.addLogger(ProposalBuilderLogger, lg).Zap()), + miner.WithActivesetPreparation(app.Config.ActiveSet), + ) + for _, sig := range app.signers { + proposalBuilder.Register(sig) + } + app.proposalBuilder = proposalBuilder } postSetupMgr, err := activation.NewPostSetupManager( @@ -1487,7 +1496,16 @@ func (app *App) startServices(ctx context.Context) error { app.blockGen.Start(ctx) app.certifier.Start(ctx) app.eg.Go(func() error { - return app.proposalBuilder.Run(ctx) + if app.proposalBuilder != nil { + return app.proposalBuilder.Run(ctx) + } + return nil + }) + app.eg.Go(func() error { + if app.remoteProposalBuilder != nil { + return app.remoteProposalBuilder.Run(ctx) + } + return nil }) if app.Config.SMESHING.CoinbaseAccount != "" { @@ -1896,7 +1914,7 @@ func (app *App) startAPIServices(ctx context.Context) error { golden := types.ATXID(app.Config.Genesis.GoldenATX()) logger := app.log.Zap().Named("atx-service") actSvc := activation.NewDBAtxService(app.db, golden, app.atxsdata, app.validator, logger) - server := nodeserver.NewServer(actSvc, app.host, app.poetDb, app.hare3, logger) + server := nodeserver.NewServer(actSvc, app.host, app.poetDb, app.hare3, app.proposalBuilder, logger) app.nodeServiceServer = &http.Server{ Handler: server.IntoHandler(http.NewServeMux()), From add533a030ce5f05eea8c5054064210c72f55ccd Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Tue, 22 Oct 2024 13:57:45 -0600 Subject: [PATCH 08/27] wip --- api/node/client/client.go | 2 ++ miner/remote_proposals.go | 57 +++++++++++++-------------------------- node/node.go | 1 + 3 files changed, 22 insertions(+), 38 deletions(-) diff --git a/api/node/client/client.go b/api/node/client/client.go index 0c939983c9..356f4d3bd1 100644 --- a/api/node/client/client.go +++ b/api/node/client/client.go @@ -216,10 +216,12 @@ func (s *NodeService) Proposal(ctx context.Context, layer types.LayerID, node ty atxNonce := resp.Header.Get("x-spacemesh-atx-nonce") if atxNonce == "" { + panic("no nonce") return nil, 0, errors.New("atx nonce header not found") } nonce, err := strconv.ParseUint(atxNonce, 10, 64) if err != nil { + panic("bad atx integer parse") return nil, 0, fmt.Errorf("nonce parse: %w", err) } return &prop, nonce, nil diff --git a/miner/remote_proposals.go b/miner/remote_proposals.go index 0400e53715..e69e261192 100644 --- a/miner/remote_proposals.go +++ b/miner/remote_proposals.go @@ -6,6 +6,7 @@ import ( "runtime" "sync" + "github.com/spacemeshos/go-spacemesh/codec" "github.com/spacemeshos/go-spacemesh/common/types" "github.com/spacemeshos/go-spacemesh/log" "github.com/spacemeshos/go-spacemesh/p2p/pubsub" @@ -200,42 +201,6 @@ func (pb *RemoteProposalBuilder) Run(ctx context.Context) error { } } -/* - p := &types.Proposal{ - InnerProposal: types.InnerProposal{ - Ballot: types.Ballot{ - InnerBallot: types.InnerBallot{ - Layer: lid, - AtxID: session.atx, - OpinionHash: opinion.Hash, - }, - Votes: opinion.Votes, - // EligibilityProofs: eligibility, - }, - TxIDs: txs, - MeshHash: meshHash, - }, - } - - if session.ref == types.EmptyBallotID { - p.Ballot.RefBallot = types.EmptyBallotID - p.Ballot.EpochData = &types.EpochData{ - ActiveSetHash: activeset.Hash(), - Beacon: beacon, - EligibilityCount: session.eligibilities.slots, - } - } else { - - p.Ballot.RefBallot = session.ref - } - -p.SmesherID = smesher -// p.Ballot.Signature = signer.Sign(signing.BALLOT, p.Ballot.SignedBytes()) -// p.Signature = signer.Sign(signing.PROPOSAL, p.SignedBytes()) -// p.MustInitialize() - -return p -*/ func (pb *RemoteProposalBuilder) build(ctx context.Context, layer types.LayerID) error { pb.signers.mu.Lock() signers := maps.Values(pb.signers.signers) @@ -256,13 +221,29 @@ func (pb *RemoteProposalBuilder) build(ctx context.Context, layer types.LayerID) signer.signer.VRFSigner(), layer.GetEpoch(), proposal.Ballot.EpochData.Beacon, - types.VRFPostIndex(nonce), // ss.session.nonce, // atx nonce + types.VRFPostIndex(nonce), proposal.Ballot.EpochData.EligibilityCount, pb.cfg.layersPerEpoch, ) - fmt.Println(proofs) + eligibilities, ok := proofs[layer] + if !ok { + // not eligible in this layer, continue + continue + } + proposal.EligibilityProofs = eligibilities + proposal.Ballot.Signature = signer.signer.Sign(signing.BALLOT, proposal.Ballot.SignedBytes()) + proposal.Signature = signer.signer.Sign(signing.PROPOSAL, proposal.SignedBytes()) + proposal.MustInitialize() + if err := pb.publisher.Publish(ctx, pubsub.ProposalProtocol, codec.MustEncode(proposal)); err != nil { + pb.logger.Error("failed to publish proposal", + log.ZContext(ctx), + zap.Uint32("lid", proposal.Layer.Uint32()), + zap.Stringer("id", proposal.ID()), + zap.Error(err), + ) + } } return nil } diff --git a/node/node.go b/node/node.go index a931e33236..6857bf336a 100644 --- a/node/node.go +++ b/node/node.go @@ -1503,6 +1503,7 @@ func (app *App) startServices(ctx context.Context) error { }) app.eg.Go(func() error { if app.remoteProposalBuilder != nil { + fmt.Println("starting remote proposal building") return app.remoteProposalBuilder.Run(ctx) } return nil From d9d55574bd6bbadff38e54f5d84fca4693416e2d Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Tue, 22 Oct 2024 14:32:16 -0600 Subject: [PATCH 09/27] wip --- miner/remote_proposals.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/miner/remote_proposals.go b/miner/remote_proposals.go index e69e261192..b58656274f 100644 --- a/miner/remote_proposals.go +++ b/miner/remote_proposals.go @@ -189,7 +189,7 @@ func (pb *RemoteProposalBuilder) Run(ctx context.Context) error { if current <= types.GetEffectiveGenesis() { continue } - + fmt.Println("remote proposal builder going to build. layer", current.Uint32()) if err := pb.build(ctx, current); err != nil { pb.logger.Warn("failed to build proposal", log.ZContext(ctx), @@ -205,15 +205,16 @@ func (pb *RemoteProposalBuilder) build(ctx context.Context, layer types.LayerID) pb.signers.mu.Lock() signers := maps.Values(pb.signers.signers) pb.signers.mu.Unlock() - + fmt.Println("remote proposal builder got some signers", signers) for _, signer := range signers { proposal, nonce, err := pb.nodeSvc.Proposal(ctx, layer, signer.signer.NodeID()) if err != nil { - return fmt.Errorf("get partial proposal: %w", err) + pb.logger.Error("get partial proposal", zap.Error(err)) } if proposal == nil { // this node signer isn't eligible this epoch, continue + pb.logger.Info("node not eligible on this layer. will try next") continue } @@ -229,6 +230,7 @@ func (pb *RemoteProposalBuilder) build(ctx context.Context, layer types.LayerID) eligibilities, ok := proofs[layer] if !ok { // not eligible in this layer, continue + pb.logger.Info("node not eligible in this layer, will try later") continue } @@ -236,6 +238,7 @@ func (pb *RemoteProposalBuilder) build(ctx context.Context, layer types.LayerID) proposal.Ballot.Signature = signer.signer.Sign(signing.BALLOT, proposal.Ballot.SignedBytes()) proposal.Signature = signer.signer.Sign(signing.PROPOSAL, proposal.SignedBytes()) proposal.MustInitialize() + pb.logger.Info("did all the proposal stuff nicely, publishing", zap.Inline(proposal)) if err := pb.publisher.Publish(ctx, pubsub.ProposalProtocol, codec.MustEncode(proposal)); err != nil { pb.logger.Error("failed to publish proposal", log.ZContext(ctx), @@ -244,6 +247,7 @@ func (pb *RemoteProposalBuilder) build(ctx context.Context, layer types.LayerID) zap.Error(err), ) } + pb.logger.Info("proposal published successfully") } return nil } From fb1da1df891b1418e0bde0db186c3c6759b6c575 Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Tue, 22 Oct 2024 14:41:17 -0600 Subject: [PATCH 10/27] signers --- node/node.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/node/node.go b/node/node.go index 6857bf336a..2d9e04fc8f 100644 --- a/node/node.go +++ b/node/node.go @@ -1034,6 +1034,10 @@ func (app *App) initServices(ctx context.Context) error { var remoteProposalBuilder *miner.RemoteProposalBuilder if nodeServiceClient != nil { remoteProposalBuilder = miner.NewRemoteBuilder(app.clock, nodeServiceClient, nodeServiceClient) + for _, sig := range app.signers { + remoteProposalBuilder.Register(sig) + } + app.remoteProposalBuilder = remoteProposalBuilder } else { proposalBuilder = miner.New( From 31f2831f51066211ede8edd4ae9e1bfe691e810d Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Tue, 22 Oct 2024 14:49:56 -0600 Subject: [PATCH 11/27] wip --- miner/remote_proposals.go | 8 ++++++-- node/node.go | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/miner/remote_proposals.go b/miner/remote_proposals.go index b58656274f..6121db6b8a 100644 --- a/miner/remote_proposals.go +++ b/miner/remote_proposals.go @@ -126,11 +126,15 @@ func NewRemoteBuilder( clock layerClock, publisher pubsub.Publisher, svc nodeService, + layerSize uint32, + layersPerEpoch uint32, ) *RemoteProposalBuilder { pb := &RemoteProposalBuilder{ cfg: config{ - workersLimit: runtime.NumCPU(), - activeSet: DefaultActiveSetPreparation(), + workersLimit: runtime.NumCPU(), + activeSet: DefaultActiveSetPreparation(), + layerSize: layerSize, + layersPerEpoch: layersPerEpoch, }, logger: zap.NewNop(), clock: clock, diff --git a/node/node.go b/node/node.go index 2d9e04fc8f..7dbe79b036 100644 --- a/node/node.go +++ b/node/node.go @@ -1033,7 +1033,7 @@ func (app *App) initServices(ctx context.Context) error { var proposalBuilder *miner.ProposalBuilder var remoteProposalBuilder *miner.RemoteProposalBuilder if nodeServiceClient != nil { - remoteProposalBuilder = miner.NewRemoteBuilder(app.clock, nodeServiceClient, nodeServiceClient) + remoteProposalBuilder = miner.NewRemoteBuilder(app.clock, nodeServiceClient, nodeServiceClient, layerSize, layersPerEpoch) for _, sig := range app.signers { remoteProposalBuilder.Register(sig) } From 23c03795b5433520da7c5579258508ce9c9fa80c Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Tue, 22 Oct 2024 15:10:50 -0600 Subject: [PATCH 12/27] prints --- api/node/client/client.go | 8 +++++++- api/node/server/server.go | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/api/node/client/client.go b/api/node/client/client.go index 356f4d3bd1..8540655b06 100644 --- a/api/node/client/client.go +++ b/api/node/client/client.go @@ -199,21 +199,26 @@ func (s *NodeService) Proposal(ctx context.Context, layer types.LayerID, node ty } switch resp.StatusCode { case http.StatusOK: + fmt.Println("client got OK for proposal") case http.StatusNoContent: // special case - no error but also no proposal, means // we're no eligibile this epoch with this node ID + fmt.Println("client not eligible for proposal") return nil, 0, nil default: + fmt.Println("client got unexpected status code") return nil, 0, fmt.Errorf("unexpected status: %s", resp.Status) } + bytes, err := io.ReadAll(resp.Body) if err != nil { return nil, 0, fmt.Errorf("read all: %w", err) } + fmt.Println("client going for decode") prop := types.Proposal{} codec.MustDecode(bytes, &prop) - + fmt.Println("client decoded proposal") atxNonce := resp.Header.Get("x-spacemesh-atx-nonce") if atxNonce == "" { panic("no nonce") @@ -224,5 +229,6 @@ func (s *NodeService) Proposal(ctx context.Context, layer types.LayerID, node ty panic("bad atx integer parse") return nil, 0, fmt.Errorf("nonce parse: %w", err) } + fmt.Println("client returning proposal with nonce", prop, nonce) return &prop, nonce, nil } diff --git a/api/node/server/server.go b/api/node/server/server.go index 2ee6cbcfa8..94350e1cad 100644 --- a/api/node/server/server.go +++ b/api/node/server/server.go @@ -299,6 +299,7 @@ type proposalResp struct { func (p *proposalResp) VisitGetProposalLayerNodeResponse(w http.ResponseWriter) error { if p.buf == nil { + fmt.Println("writing no content to requester") w.WriteHeader(204) return nil } @@ -323,5 +324,6 @@ func (s *Server) GetProposalLayerNode(ctx context.Context, request GetProposalLa if proposal.Ballot.EpochData.EligibilityCount == 0 { return &proposalResp{}, nil } + fmt.Println("writing response to client") return &proposalResp{buf: codec.MustEncode(proposal), nonce: nonce}, err } From 5d2d7b70f54a0f8168f48a2df5ab7f8af6ad5d1e Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Tue, 22 Oct 2024 15:23:13 -0600 Subject: [PATCH 13/27] logger --- miner/remote_proposals.go | 8 ++++++-- node/node.go | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/miner/remote_proposals.go b/miner/remote_proposals.go index 6121db6b8a..01cb6f33a7 100644 --- a/miner/remote_proposals.go +++ b/miner/remote_proposals.go @@ -128,6 +128,7 @@ func NewRemoteBuilder( svc nodeService, layerSize uint32, layersPerEpoch uint32, + logger *zap.Logger, ) *RemoteProposalBuilder { pb := &RemoteProposalBuilder{ cfg: config{ @@ -136,7 +137,7 @@ func NewRemoteBuilder( layerSize: layerSize, layersPerEpoch: layersPerEpoch, }, - logger: zap.NewNop(), + logger: logger, clock: clock, publisher: publisher, nodeSvc: svc, @@ -147,6 +148,9 @@ func NewRemoteBuilder( signers: map[types.NodeID]*signerSession{}, }, } + if logger == nil { + pb.logger = zap.NewNop() + } return pb } @@ -215,7 +219,7 @@ func (pb *RemoteProposalBuilder) build(ctx context.Context, layer types.LayerID) if err != nil { pb.logger.Error("get partial proposal", zap.Error(err)) } - + fmt.Println("remote proposal builder got proposal and nonce", proposal, nonce, err) if proposal == nil { // this node signer isn't eligible this epoch, continue pb.logger.Info("node not eligible on this layer. will try next") diff --git a/node/node.go b/node/node.go index 7dbe79b036..5fffb39281 100644 --- a/node/node.go +++ b/node/node.go @@ -1033,7 +1033,7 @@ func (app *App) initServices(ctx context.Context) error { var proposalBuilder *miner.ProposalBuilder var remoteProposalBuilder *miner.RemoteProposalBuilder if nodeServiceClient != nil { - remoteProposalBuilder = miner.NewRemoteBuilder(app.clock, nodeServiceClient, nodeServiceClient, layerSize, layersPerEpoch) + remoteProposalBuilder = miner.NewRemoteBuilder(app.clock, nodeServiceClient, nodeServiceClient, layerSize, layersPerEpoch, app.addLogger(ProposalBuilderLogger, lg).Zap()) for _, sig := range app.signers { remoteProposalBuilder.Register(sig) } From 97210228a13451c1a8da769add9f84421a24f144 Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Tue, 22 Oct 2024 15:31:29 -0600 Subject: [PATCH 14/27] housekeeping --- api/node/client/client.go | 8 -------- api/node/server/server.go | 2 -- hare3/hare.go | 2 -- miner/remote_proposals.go | 4 ---- node/node.go | 1 - 5 files changed, 17 deletions(-) diff --git a/api/node/client/client.go b/api/node/client/client.go index 8540655b06..92d2182d5e 100644 --- a/api/node/client/client.go +++ b/api/node/client/client.go @@ -199,14 +199,11 @@ func (s *NodeService) Proposal(ctx context.Context, layer types.LayerID, node ty } switch resp.StatusCode { case http.StatusOK: - fmt.Println("client got OK for proposal") case http.StatusNoContent: // special case - no error but also no proposal, means // we're no eligibile this epoch with this node ID - fmt.Println("client not eligible for proposal") return nil, 0, nil default: - fmt.Println("client got unexpected status code") return nil, 0, fmt.Errorf("unexpected status: %s", resp.Status) } @@ -215,20 +212,15 @@ func (s *NodeService) Proposal(ctx context.Context, layer types.LayerID, node ty return nil, 0, fmt.Errorf("read all: %w", err) } - fmt.Println("client going for decode") prop := types.Proposal{} codec.MustDecode(bytes, &prop) - fmt.Println("client decoded proposal") atxNonce := resp.Header.Get("x-spacemesh-atx-nonce") if atxNonce == "" { - panic("no nonce") return nil, 0, errors.New("atx nonce header not found") } nonce, err := strconv.ParseUint(atxNonce, 10, 64) if err != nil { - panic("bad atx integer parse") return nil, 0, fmt.Errorf("nonce parse: %w", err) } - fmt.Println("client returning proposal with nonce", prop, nonce) return &prop, nonce, nil } diff --git a/api/node/server/server.go b/api/node/server/server.go index 94350e1cad..2ee6cbcfa8 100644 --- a/api/node/server/server.go +++ b/api/node/server/server.go @@ -299,7 +299,6 @@ type proposalResp struct { func (p *proposalResp) VisitGetProposalLayerNodeResponse(w http.ResponseWriter) error { if p.buf == nil { - fmt.Println("writing no content to requester") w.WriteHeader(204) return nil } @@ -324,6 +323,5 @@ func (s *Server) GetProposalLayerNode(ctx context.Context, request GetProposalLa if proposal.Ballot.EpochData.EligibilityCount == 0 { return &proposalResp{}, nil } - fmt.Println("writing response to client") return &proposalResp{buf: codec.MustEncode(proposal), nonce: nonce}, err } diff --git a/hare3/hare.go b/hare3/hare.go index 64efb84c03..943d73d94c 100644 --- a/hare3/hare.go +++ b/hare3/hare.go @@ -363,7 +363,6 @@ func (h *Hare) onLayer(layer types.LayerID) { return } beacon, err := beacons.Get(h.db, layer.GetEpoch()) - fmt.Println("beacon value get result", beacon) h.log.Info("hare tried to get beacon value", zap.Error(err)) if err != nil || beacon == types.EmptyBeacon { h.log.Debug("no beacon", @@ -374,7 +373,6 @@ func (h *Hare) onLayer(layer types.LayerID) { return } h.patrol.SetHareInCharge(layer) - fmt.Println("continuing hare") h.mu.Lock() // signer can't join mid session s := &session{ diff --git a/miner/remote_proposals.go b/miner/remote_proposals.go index 01cb6f33a7..95a431152e 100644 --- a/miner/remote_proposals.go +++ b/miner/remote_proposals.go @@ -2,7 +2,6 @@ package miner import ( "context" - "fmt" "runtime" "sync" @@ -197,7 +196,6 @@ func (pb *RemoteProposalBuilder) Run(ctx context.Context) error { if current <= types.GetEffectiveGenesis() { continue } - fmt.Println("remote proposal builder going to build. layer", current.Uint32()) if err := pb.build(ctx, current); err != nil { pb.logger.Warn("failed to build proposal", log.ZContext(ctx), @@ -213,13 +211,11 @@ func (pb *RemoteProposalBuilder) build(ctx context.Context, layer types.LayerID) pb.signers.mu.Lock() signers := maps.Values(pb.signers.signers) pb.signers.mu.Unlock() - fmt.Println("remote proposal builder got some signers", signers) for _, signer := range signers { proposal, nonce, err := pb.nodeSvc.Proposal(ctx, layer, signer.signer.NodeID()) if err != nil { pb.logger.Error("get partial proposal", zap.Error(err)) } - fmt.Println("remote proposal builder got proposal and nonce", proposal, nonce, err) if proposal == nil { // this node signer isn't eligible this epoch, continue pb.logger.Info("node not eligible on this layer. will try next") diff --git a/node/node.go b/node/node.go index 5fffb39281..5bdeea3bbe 100644 --- a/node/node.go +++ b/node/node.go @@ -1507,7 +1507,6 @@ func (app *App) startServices(ctx context.Context) error { }) app.eg.Go(func() error { if app.remoteProposalBuilder != nil { - fmt.Println("starting remote proposal building") return app.remoteProposalBuilder.Run(ctx) } return nil From 9fa34d43aaa8d6c056659a42279123eb82f90f4f Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Thu, 24 Oct 2024 12:44:47 -0600 Subject: [PATCH 15/27] setup --- activation_service_poc/config.standalone.node-service.json | 5 +++++ activation_service_poc/docker-compose.yml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/activation_service_poc/config.standalone.node-service.json b/activation_service_poc/config.standalone.node-service.json index e511285b6c..524d8b384c 100644 --- a/activation_service_poc/config.standalone.node-service.json +++ b/activation_service_poc/config.standalone.node-service.json @@ -20,5 +20,10 @@ "main": { "data-folder": "/tmp/spacemesh-node-service", "filelock": "/tmp/spacemesh-node-service/node.lock" + }, + "smeshing": { + "smeshing-opts": { + "smeshing-opts-datadir": "/tmp/spacemesh-node-service/post-data" + } } } diff --git a/activation_service_poc/docker-compose.yml b/activation_service_poc/docker-compose.yml index 6963bb6fea..edbb5b0e76 100644 --- a/activation_service_poc/docker-compose.yml +++ b/activation_service_poc/docker-compose.yml @@ -12,7 +12,7 @@ services: node-service: image: spacemeshos/go-spacemesh-dev:activation-service-poc.0 - command: ["-c", "/config.json", "--smeshing-opts-datadir", "/tmp/spacemesh-node-post"] + command: ["-c", "/config.json"] volumes: - /tmp/spacemesh-node-service:/tmp/spacemesh-node-service - ./config.standalone.node-service.json:/config.json From c3e8dea099ac67412328c0f7bcd8bef0876b4070 Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Thu, 24 Oct 2024 12:45:49 -0600 Subject: [PATCH 16/27] setup --- activation_service_poc/start.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activation_service_poc/start.sh b/activation_service_poc/start.sh index b1e2e96326..bc7af4abf3 100644 --- a/activation_service_poc/start.sh +++ b/activation_service_poc/start.sh @@ -10,5 +10,5 @@ TIME=$(date -u -d '2 minutes' "+%Y-%m-%dT%H:%M:%S%:z") sed -i "s/\"genesis-time\".*/\"genesis-time\"\:\"$TIME\"/g" config.standalone.client.json sed -i "s/\"genesis-time\".*/\"genesis-time\"\:\"$TIME\"/g" config.standalone.node-service.json -rm -rf /tmp/spacemesh* +rm -rf /tmp/space* docker compose up From 5e427452461004c1105d3e256cb2ef3a4dccdb41 Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Thu, 24 Oct 2024 13:55:01 -0600 Subject: [PATCH 17/27] config --- activation_service_poc/config.standalone.client.json | 6 +++--- activation_service_poc/config.standalone.node-service.json | 2 +- activation_service_poc/start.sh | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/activation_service_poc/config.standalone.client.json b/activation_service_poc/config.standalone.client.json index 335ecd9a26..e475c1b491 100644 --- a/activation_service_poc/config.standalone.client.json +++ b/activation_service_poc/config.standalone.client.json @@ -10,9 +10,9 @@ "logging": { "trtl": "WARN", "beacon": "ERROR", - "proposalBuilder": "ERROR", - "atxBuilder": "DEBUG", - "hare": "DEBUG" + "proposalBuilder": "DEBUG", + "atxBuilder": "ERROR", + "hare": "ERROR" }, "main": { "node-service-address": "http://0.0.0.0:9099", diff --git a/activation_service_poc/config.standalone.node-service.json b/activation_service_poc/config.standalone.node-service.json index 524d8b384c..d27f3597d4 100644 --- a/activation_service_poc/config.standalone.node-service.json +++ b/activation_service_poc/config.standalone.node-service.json @@ -12,7 +12,7 @@ "trtl": "WARN", "beacon": "ERROR", "proposalBuilder": "ERROR", - "hare": "DEBUG" + "hare": "ERROR" }, "hare3": { "enable": true diff --git a/activation_service_poc/start.sh b/activation_service_poc/start.sh index bc7af4abf3..a2106d60b1 100644 --- a/activation_service_poc/start.sh +++ b/activation_service_poc/start.sh @@ -6,7 +6,7 @@ cd activation_service_poc IMAGE=$(docker images | head -n 2 | tail -n 1 | awk '{print $3}') sed -i "s/image.*/image:\ $IMAGE/g" docker-compose.yml -TIME=$(date -u -d '2 minutes' "+%Y-%m-%dT%H:%M:%S%:z") +TIME=$(date -u -d '1 minutes' "+%Y-%m-%dT%H:%M:%S%:z") sed -i "s/\"genesis-time\".*/\"genesis-time\"\:\"$TIME\"/g" config.standalone.client.json sed -i "s/\"genesis-time\".*/\"genesis-time\"\:\"$TIME\"/g" config.standalone.node-service.json From 409baaaaedb1dfb5317beca02d8793f7d5aee64c Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Thu, 24 Oct 2024 13:58:40 -0600 Subject: [PATCH 18/27] compose-ports --- activation_service_poc/docker-compose.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/activation_service_poc/docker-compose.yml b/activation_service_poc/docker-compose.yml index edbb5b0e76..ec6e3cb945 100644 --- a/activation_service_poc/docker-compose.yml +++ b/activation_service_poc/docker-compose.yml @@ -18,6 +18,9 @@ services: - ./config.standalone.node-service.json:/config.json networks: - spacemesh-net + ports: + - 9092:9092 + - 9093:9093 networks: spacemesh-net: From 5a0371078cca63720c4007e38557d351d7072006 Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:03:28 -0600 Subject: [PATCH 19/27] chmod --- activation_service_poc/start.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 activation_service_poc/start.sh diff --git a/activation_service_poc/start.sh b/activation_service_poc/start.sh old mode 100644 new mode 100755 From 3843e22e39a1966fe2f7b5100331053b68a1a47f Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:25:32 -0600 Subject: [PATCH 20/27] print coinbase --- activation/activation.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activation/activation.go b/activation/activation.go index bd27a313ce..4118d934b5 100644 --- a/activation/activation.go +++ b/activation/activation.go @@ -744,7 +744,7 @@ func (b *Builder) PublishActivationTx(ctx context.Context, sig *signing.EdSigner ) size, err := b.broadcast(ctx, atx) if err == nil { - b.logger.Info("atx published", log.ZShortStringer("atx_id", atx.ID()), zap.Int("size", size)) + b.logger.Info("atx published", log.ZShortStringer("atx_id", atx.ID()), zap.Stringer("coinbase", b.Coinbase().String()), zap.Int("size", size)) break } From 4590513e5044bfc64368f8834255a95d036960e0 Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:30:07 -0600 Subject: [PATCH 21/27] build --- activation/activation.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activation/activation.go b/activation/activation.go index 4118d934b5..dd5321606e 100644 --- a/activation/activation.go +++ b/activation/activation.go @@ -744,7 +744,7 @@ func (b *Builder) PublishActivationTx(ctx context.Context, sig *signing.EdSigner ) size, err := b.broadcast(ctx, atx) if err == nil { - b.logger.Info("atx published", log.ZShortStringer("atx_id", atx.ID()), zap.Stringer("coinbase", b.Coinbase().String()), zap.Int("size", size)) + b.logger.Info("atx published", log.ZShortStringer("atx_id", atx.ID()), zap.Stringer("coinbase", b.Coinbase()), zap.Int("size", size)) break } From 49ef08ce6ab61da04f182bcd322b39f46baaf233 Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:40:02 -0600 Subject: [PATCH 22/27] smesh --- activation_service_poc/config.standalone.node-service.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/activation_service_poc/config.standalone.node-service.json b/activation_service_poc/config.standalone.node-service.json index d27f3597d4..48cd4947eb 100644 --- a/activation_service_poc/config.standalone.node-service.json +++ b/activation_service_poc/config.standalone.node-service.json @@ -24,6 +24,7 @@ "smeshing": { "smeshing-opts": { "smeshing-opts-datadir": "/tmp/spacemesh-node-service/post-data" - } + }, + "smeshing-start": true } } From 8cda487d37c8cc2bf7bfe878e1af0ced277dc31b Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:46:35 -0600 Subject: [PATCH 23/27] unsmesh --- activation_service_poc/config.standalone.node-service.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/activation_service_poc/config.standalone.node-service.json b/activation_service_poc/config.standalone.node-service.json index 48cd4947eb..d27f3597d4 100644 --- a/activation_service_poc/config.standalone.node-service.json +++ b/activation_service_poc/config.standalone.node-service.json @@ -24,7 +24,6 @@ "smeshing": { "smeshing-opts": { "smeshing-opts-datadir": "/tmp/spacemesh-node-service/post-data" - }, - "smeshing-start": true + } } } From a40c6855311434a1b8828ab66bf01cfea2d3d604 Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:23:27 -0600 Subject: [PATCH 24/27] just rand shuffle --- miner/remote_proposals.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/miner/remote_proposals.go b/miner/remote_proposals.go index 95a431152e..201e9d1bf8 100644 --- a/miner/remote_proposals.go +++ b/miner/remote_proposals.go @@ -2,8 +2,10 @@ package miner import ( "context" + "math/rand" "runtime" "sync" + "time" "github.com/spacemeshos/go-spacemesh/codec" "github.com/spacemeshos/go-spacemesh/common/types" @@ -238,6 +240,9 @@ func (pb *RemoteProposalBuilder) build(ctx context.Context, layer types.LayerID) continue } + rng := rand.New(rand.NewSource(time.Now().UnixNano())) + rng.Shuffle(len(proposal.TxIDs), func(i, j int) { proposal.TxIDs[i], proposal.TxIDs[j] = proposal.TxIDs[j], proposal.TxIDs[i] }) + proposal.EligibilityProofs = eligibilities proposal.Ballot.Signature = signer.signer.Sign(signing.BALLOT, proposal.Ballot.SignedBytes()) proposal.Signature = signer.signer.Sign(signing.PROPOSAL, proposal.SignedBytes()) From 73da8a2bbc6222a416a2b0998e26560fe07fb2b7 Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:26:31 -0600 Subject: [PATCH 25/27] docker --- .../config.standalone.client2.json | 32 +++++++++++++++++++ activation_service_poc/docker-compose.yml | 8 +++++ 2 files changed, 40 insertions(+) create mode 100644 activation_service_poc/config.standalone.client2.json diff --git a/activation_service_poc/config.standalone.client2.json b/activation_service_poc/config.standalone.client2.json new file mode 100644 index 0000000000..9988c0789b --- /dev/null +++ b/activation_service_poc/config.standalone.client2.json @@ -0,0 +1,32 @@ +{ + "preset": "standalone", + "api": { + "grpc-public-listener": "0.0.0.0:9082", + "grpc-private-listener": "0.0.0.0:9083" + }, + "genesis": { + "genesis-time": "2024-09-25T13:00:00.000Z" + }, + "logging": { + "trtl": "WARN", + "beacon": "ERROR", + "proposalBuilder": "DEBUG", + "atxBuilder": "ERROR", + "hare": "ERROR" + }, + "main": { + "node-service-address": "http://0.0.0.0:9099", + "data-folder": "/tmp/spacemesh-client2", + "filelock": "/tmp/spacemesh-client2/node.lock", + "poet-servers": [ + { + "address": "http://127.0.0.1:10011" + } + ] + }, + "smeshing": { + "smeshing-opts": { + "smeshing-opts-datadir": "/tmp/spacemesh-client2/post-data" + } + } +} diff --git a/activation_service_poc/docker-compose.yml b/activation_service_poc/docker-compose.yml index ec6e3cb945..657037fe3d 100644 --- a/activation_service_poc/docker-compose.yml +++ b/activation_service_poc/docker-compose.yml @@ -9,6 +9,14 @@ services: - ./config.standalone.client.json:/config.json networks: - spacemesh-net + activation-service-2: + image: spacemeshos/go-spacemesh-dev:activation-service-poc.0 + command: ["-c", "/config.json", "--node-service-address", "http://node-service:9099"] + volumes: + - /tmp/spacemesh-client2:/tmp/spacemesh-client2 + - ./config.standalone.client2.json:/config.json + networks: + - spacemesh-net node-service: image: spacemeshos/go-spacemesh-dev:activation-service-poc.0 From 0bbe0eb40f7d971a9702081aeee337d78dade5a2 Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:28:29 -0600 Subject: [PATCH 26/27] one --- activation_service_poc/docker-compose.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/activation_service_poc/docker-compose.yml b/activation_service_poc/docker-compose.yml index 657037fe3d..ec6e3cb945 100644 --- a/activation_service_poc/docker-compose.yml +++ b/activation_service_poc/docker-compose.yml @@ -9,14 +9,6 @@ services: - ./config.standalone.client.json:/config.json networks: - spacemesh-net - activation-service-2: - image: spacemeshos/go-spacemesh-dev:activation-service-poc.0 - command: ["-c", "/config.json", "--node-service-address", "http://node-service:9099"] - volumes: - - /tmp/spacemesh-client2:/tmp/spacemesh-client2 - - ./config.standalone.client2.json:/config.json - networks: - - spacemesh-net node-service: image: spacemeshos/go-spacemesh-dev:activation-service-poc.0 From 8d2ec429684e464bf7321005f086f4a167595b17 Mon Sep 17 00:00:00 2001 From: acud <12988138+acud@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:49:56 -0600 Subject: [PATCH 27/27] cleanups --- miner/remote_proposals.go | 90 +-------------------------------------- 1 file changed, 1 insertion(+), 89 deletions(-) diff --git a/miner/remote_proposals.go b/miner/remote_proposals.go index 201e9d1bf8..06be2c7c41 100644 --- a/miner/remote_proposals.go +++ b/miner/remote_proposals.go @@ -17,85 +17,6 @@ import ( "golang.org/x/sync/errgroup" ) -// Opt for configuring ProposalBuilder. -// type Opt func(h *RemoteProposalBuilder) - -//// WithLayerSize defines the average number of proposal per layer. -//func WithLayerSize(size uint32) Opt { -//return func(pb *RemoteProposalBuilder) { -//pb.cfg.layerSize = size -//} -//} - -//// WithWorkersLimit configures paralelization factor for builder operation when working with -//// more than one signer. -//func WithWorkersLimit(limit int) Opt { -//return func(pb *RemoteProposalBuilder) { -//pb.cfg.workersLimit = limit -//} -//} - -//// WithLayerPerEpoch defines the number of layers per epoch. -//func WithLayerPerEpoch(layers uint32) Opt { -//return func(pb *RemoteProposalBuilder) { -//pb.cfg.layersPerEpoch = layers -//} -//} - -//func WithMinimalActiveSetWeight(weight []types.EpochMinimalActiveWeight) Opt { -//return func(pb *RemoteProposalBuilder) { -//pb.cfg.minActiveSetWeight = weight -//} -//} - -//// WithLogger defines the logger. -//func WithLogger(logger *zap.Logger) Opt { -//return func(pb *RemoteProposalBuilder) { -//pb.logger = logger -//} -//} - -//func WithHdist(dist uint32) Opt { -//return func(pb *RemoteProposalBuilder) { -//pb.cfg.hdist = dist -//} -//} - -//func WithNetworkDelay(delay time.Duration) Opt { -//return func(pb *RemoteProposalBuilder) { -//pb.cfg.networkDelay = delay -//} -//} - -//func WithMinGoodAtxPercent(percent int) Opt { -//return func(pb *RemoteProposalBuilder) { -//pb.cfg.goodAtxPercent = percent -//} -//} - -//// WithSigners guarantees that builder will start execution with provided list of signers. -//// Should be after logging. -//func WithSigners(signers ...*signing.EdSigner) Opt { -//return func(pb *RemoteProposalBuilder) { -//for _, signer := range signers { -//pb.Register(signer) -//} -//} -//} - -//// WithActivesetPreparation overwrites configuration for activeset preparation. -//func WithActivesetPreparation(prep ActiveSetPreparation) Opt { -//return func(pb *RemoteProposalBuilder) { -//pb.cfg.activeSet = prep -//} -//} - -//func withAtxSearch(p atxSearch) Opt { -//return func(pb *RemoteProposalBuilder) { -//pb.atxs = p -//} -//} - type nodeService interface { Proposal(ctx context.Context, layer types.LayerID, node types.NodeID) (*types.Proposal, uint64, error) } @@ -103,19 +24,10 @@ type RemoteProposalBuilder struct { logger *zap.Logger cfg config - // db sql.Executor - // localdb sql.Executor - // atxsdata *atxsdata.Data clock layerClock publisher pubsub.Publisher nodeSvc nodeService - // conState conservativeState - // tortoise votesEncoder - // syncer system.SyncStateProvider - // activeGen *activeSetGenerator - // atxs atxSearch - - signers struct { + signers struct { mu sync.Mutex signers map[types.NodeID]*signerSession }