Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce --force-winning-ticket on mining once subcommand. #520

Closed
wants to merge 0 commits into from

Conversation

aboodman
Copy link
Contributor

Fixes #504

@aboodman aboodman requested review from phritz and acruikshank May 31, 2018 00:05
Copy link
Contributor Author

@aboodman aboodman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an alternate implementation of #519. I greatly prefer this approach because it strengthens and reuses abstractions we already have (isWinningTicket, AsyncWorker, etc) rather than creating new ones. But it does have the downside that it pulls a tiny bit of the implementation up into the command, which we've said that we don't want to do. There isn't a good way to bridge this divide IMO.

createPoST DoSomeWorkFunc // TODO: rename createPoSTFunc?
mine mineFunc
nullBlockTimer NullBlockTimerFunc
BlockGenerator BlockGenerator
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were already exposing these configuration knobs via the NewWorker constructor - but doing it that way require you to specify each one of them, even when only a few are needed. Exposing the fields directly seems more convenient to users, and then we can remove NewWorkerWithDeps.


// NewWorkerWithDeps instantiates a new Worker with custom functions.
func NewWorkerWithDeps(blockGenerator BlockGenerator, mine mineFunc, createPoST DoSomeWorkFunc, nullBlockTimer NullBlockTimerFunc) Worker {
func NewWorker(blockGenerator BlockGenerator) *AsyncWorker {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was already possible to construct and use AsyncWorker directly, because it was exported. But having NewWorker return it (pre-defaulted) makes it more convenient to use because you can then go and set just the customizations you want.

// Mine does the actual work. It's the implementation of worker.mine.
func Mine(ctx context.Context, input Input, nullBlockTimer NullBlockTimerFunc, blockGenerator BlockGenerator, createPoST DoSomeWorkFunc, outCh chan<- Output) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nobody was using this function publicly, so I de-exported it.

@@ -198,7 +201,6 @@ func Mine(ctx context.Context, input Input, nullBlockTimer NullBlockTimerFunc, b
proof := createProof(challenge, createPoST)
ticket := createTicket(proof)

// TODO: Test the interplay of isWinningTicket() and createPoST()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was an old TODO I forgot to remove.

@whyrusleeping
Copy link
Member

clarification, this causes the miner to think that the block that they mine has a winning ticket. Not for them to actually get a winning ticket. Other nodes they are connected to won't think their ticket is a winner.

Copy link
Contributor

@dignifiedquire dignifiedquire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a good way to go to me

forceWinningTicket = v.(bool)
}
worker := mining.NewWorker(blockGenerator)
if forceWinningTicket {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

non-blocking: This would read a little easier and save a little code if you nested this if within the option loop above. i.e.

if forceTicket, ok := req.Options["force-winning-ticket"]; ok {
    if forceTicket(bool) {
      ...
    }
}

or

if forceTicket, ok := req.Options["force-winning-ticket"]; ok && forceTicket(bool) {
    ...
}

r = <-outCh
})()
go mine(ctx, input, nullBlockImmediately, mockBg, everyThirdWinningTicket(), func() { workCount++ }, outCh)
r = <-outCh
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Contributor

@acruikshank acruikshank left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great. I like this feature.

@aboodman
Copy link
Contributor Author

Thanks, will land when tests pass. @phritz happy to circle back async.

@whyrusleeping
Copy link
Member

I feel like people didn't read my comment.

Copy link
Member

@whyrusleeping whyrusleeping left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocking until we discuss the issue i brought up

@aboodman
Copy link
Contributor Author

Sorry @whyrusleeping, I interpreted your comment as a statement, not a question. I agree with the statement. Do you have a specific change you want to see made?

@whyrusleeping
Copy link
Member

i mean, it kinda makes this feature useless outside of the context of a single node. I think that kinda makes this less useful (and should be clearly documented at least). It also will break things pretty angrily if you restart the node, as it will (should) fail while loading the chain from disk.

@aboodman
Copy link
Contributor Author

i mean, it kinda makes this feature useless outside of the context of a single node. I think that kinda makes this less useful (and should be clearly documented at least).

Agree. Are you thinking more documentation just in the flag description, or somewhere else?

It also will break things pretty angrily if you restart the node, as it will (should) fail while loading the chain from disk.

Yeah, hadn't thought about that.

===

To recap, this solution came out of the discussion here.

You suggested to make the mine always succeed. But since these tests are running the code via the CLI, there is not currently any pattern in the code to modify their behavior other than via flags.

Here are some potential ideas for how to do this better. Please let me know if you prefer one of them, or else if you want me to do something else:

  1. We could write tests like these that require deeper modifications to core behavior as unit tests (e.g., in process, using the Go API), not integration tests. Then there would be no need for any CLI modifications.
  2. We could come up with some other way to modify the behavior of the binary out of process, for example we could add an FILECOIN_TEST_MODE=1 env var that causes certain flags that only exist to facilitate tests to become available.
  3. We could leave it pretty much as-is and improve the documentation/flag name.

I guess I prefer 1, personally, but I was trying to go with the flow of the existing code and what we had discussed when the issue came up.

@whyrusleeping
Copy link
Member

this ones hard. Adding a flag that only works in test mode, and only works if you don't reboot your node, and only works locally, is a bit weird. I guess if we make the flag name a lot scarier, that might help? also better documentation around it? My biggest issue here (aside from the gimped functionality) is that this is a flag that we will ship the product with, unless we find some different way to accomplish the same thing in tests. shipping with a command flag that says "mine a block right now and just accept it" feels rather unprofessional, do you agree?

Choice 1 seems reasonable, but changes how we think about testing the daemon. which may be okay.

@aboodman
Copy link
Contributor Author

shipping with a command flag that says "mine a block right now and just accept it" feels rather unprofessional, do you agree?

100%. I actually brought it up in original discussion -- #482 (comment) -- so I'm glad we're sorting it out.

I'll take a look and see if this can be accomplished reasonably in the unit testing style. If not we can talk about how to add a "test mode" to the binary.

@mishmosh mishmosh added this to the Sprint 13 👻 milestone Jun 5, 2018
@dignifiedquire
Copy link
Contributor

@aboodman what is the state of this?

@dignifiedquire dignifiedquire modified the milestone: Sprint 13 👻 Jun 11, 2018
@aboodman
Copy link
Contributor Author

aboodman commented Jun 11, 2018 via email

@aboodman
Copy link
Contributor Author

Gonna close this for now, it doesn't seem to be causing problems.

@aboodman aboodman closed this Jun 22, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants