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

Add the ipfs dag api object in Blockstore #356

Merged
merged 26 commits into from
May 27, 2021

Conversation

evan-forbes
Copy link
Member

@evan-forbes evan-forbes commented May 26, 2021

Description

This PR adds the ipfs object to the Blockstore struct, along with adding a method to get the IPFS dag api object to the BlockStore interface. It also removes it from the State and Node objects. It does not do anything new with the ipfs api object.

Piggy backing on the work of #352, this PR introduces DagOnlyMock. In this case, it was needed to get TestNodeSetPrivValIPC to pass.

There are also a few timeout increases in a meager attempt to decrease CI flakiness.

Closes: #355

@evan-forbes evan-forbes self-assigned this May 26, 2021
@evan-forbes evan-forbes removed the request for review from tac0turtle May 26, 2021 03:05
@evan-forbes evan-forbes changed the title Move the ipfs api object to Blockstore Move the ipfs dag api object to Blockstore May 26, 2021
@codecov-commenter
Copy link

codecov-commenter commented May 27, 2021

Codecov Report

Merging #356 (2e5a7e4) into master (f46cbc6) will decrease coverage by 0.02%.
The diff coverage is 68.42%.

@@            Coverage Diff             @@
##           master     #356      +/-   ##
==========================================
- Coverage   61.81%   61.78%   -0.03%     
==========================================
  Files         262      262              
  Lines       22920    22920              
==========================================
- Hits        14167    14161       -6     
+ Misses       7259     7257       -2     
- Partials     1494     1502       +8     
Impacted Files Coverage Δ
consensus/replay_file.go 0.00% <0.00%> (ø)
state/services.go 40.00% <ø> (ø)
node/node.go 56.33% <77.77%> (+0.38%) ⬆️
store/store.go 64.88% <80.00%> (-0.14%) ⬇️
config/config.go 78.24% <100.00%> (ø)
consensus/state.go 67.92% <100.00%> (+0.52%) ⬆️
privval/signer_listener_endpoint.go 80.00% <0.00%> (-9.42%) ⬇️
p2p/switch.go 63.27% <0.00%> (-4.63%) ⬇️
privval/socket_listeners.go 78.72% <0.00%> (-4.26%) ⬇️
privval/secret_connection.go 72.68% <0.00%> (-3.61%) ⬇️
... and 8 more

ipfs/mock.go Outdated
Comment on lines 37 to 68
// DagOnlyMock provides an empty APIProvider that only mocks the DAG portion of
// the ipfs api object. This is much lighter than the full IPFS node and should
// be favored for CI testing
func DagOnlyMock() APIProvider {
mockAPI := dagOnlyMock{mdutils.Mock()}
return func() (coreiface.CoreAPI, io.Closer, error) {
return mockAPI, mockAPI, nil
}
}

var _ coreiface.CoreAPI = dagOnlyMock{}

type dagOnlyMock struct {
format.DAGService
}

func (dom dagOnlyMock) Dag() coreiface.APIDagService { return dom }

func (dagOnlyMock) Unixfs() coreiface.UnixfsAPI { return nil }
func (dagOnlyMock) Block() coreiface.BlockAPI { return nil }
func (dagOnlyMock) Name() coreiface.NameAPI { return nil }
func (dagOnlyMock) Key() coreiface.KeyAPI { return nil }
func (dagOnlyMock) Pin() coreiface.PinAPI { return nil }
func (dagOnlyMock) Object() coreiface.ObjectAPI { return nil }
func (dagOnlyMock) Dht() coreiface.DhtAPI { return nil }
func (dagOnlyMock) Swarm() coreiface.SwarmAPI { return nil }
func (dagOnlyMock) PubSub() coreiface.PubSubAPI { return nil }
func (dagOnlyMock) ResolvePath(context.Context, path.Path) (path.Resolved, error) { return nil, nil }
func (dagOnlyMock) ResolveNode(context.Context, path.Path) (format.Node, error) { return nil, nil }
func (dagOnlyMock) WithOptions(...options.ApiOption) (coreiface.CoreAPI, error) { return nil, nil }
func (dagOnlyMock) Close() error { return nil }
func (dagOnlyMock) Pinning() format.NodeAdder { return nil }
Copy link
Member Author

@evan-forbes evan-forbes May 27, 2021

Choose a reason for hiding this comment

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

I'm not the biggest fan of these nil mocks, but it does give us a lot flexibility in the future by not modifying APIProvider, which returns the full iface.CoreAPI. If we need the full ipfs API for whatever reason, then we can still use the normal Mock. If we don't, then we can use the much lighter dagOnlyMock

Copy link
Member Author

@evan-forbes evan-forbes May 27, 2021

Choose a reason for hiding this comment

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

tbc, I'm not attached to this solution, and am very open to other ideas for passing in a dag only mock.

Copy link
Member

Choose a reason for hiding this comment

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

It's probably better to actually just pass around the DAG / the absolutely necessary API surface in these cases as well (like @Wondertan did in #352) but I think having different mocks for different purposes might still be useful. Especially as unit-tests most likely will rarely really need the whole CoreAPI object.
I'm OK with this. Would like to hear what @Wondertan thinks about this too.

Copy link
Member

Choose a reason for hiding this comment

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

Agree with @liamsi, we can simply deprecate full core API usage. We won't need anything form it except for the DAG.

Copy link
Member

Choose a reason for hiding this comment

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

So I don't see any need for dagOnlyMock

Copy link
Member Author

Choose a reason for hiding this comment

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

alrighty, the api object has been kicked from the island 1bddff2

Comment on lines 55 to 56
ipfs.Mock(),
ipfs.DagOnlyMock(),
Copy link
Member Author

@evan-forbes evan-forbes May 27, 2021

Choose a reason for hiding this comment

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

The full mock node was part of the reason why TestNodeSetPrivValIPC kept failing in the CI (passes locally). TBH, I'm still not 100% sure why, as this test was passing in #352, and the mocked IPFS api obejct was only moved to the blockstore. 🤷‍♂️

@@ -216,17 +215,20 @@ type Node struct {
indexerService *txindex.IndexerService
prometheusSrv *http.Server

ipfsAPI ipface.CoreAPI
Copy link
Member Author

Choose a reason for hiding this comment

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

removed this for now, as we weren't using it anywhere. We can easily add it back in if needed.

test-output2.txt Outdated
ok github.com/lazyledger/lazyledger-core/types (cached)
? github.com/lazyledger/lazyledger-core/types/consts [no test files]
ok github.com/lazyledger/lazyledger-core/types/time (cached)
? github.com/lazyledger/lazyledger-core/version [no test files]
Copy link
Member

Choose a reason for hiding this comment

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

This was probably checkedin by accident only?

Copy link
Member Author

@evan-forbes evan-forbes May 27, 2021

Choose a reason for hiding this comment

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

whoops. Thanks for catching this! removed c11b9fe

Copy link
Member

@Wondertan Wondertan left a comment

Choose a reason for hiding this comment

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

Overall good but my concerns are:

  1. Encapsulating DAG in the Blockstore
  2. Keep relying on CoreAPI

store/store.go Outdated
@@ -424,6 +428,12 @@ func (bs *BlockStore) SaveSeenCommit(height int64, seenCommit *types.Commit) err
return bs.db.Set(calcSeenCommitKey(height), seenCommitBytes)
}

// IpfsAPI returns the ipfs api object of the BlockStore. Fullfills the
// state.BlockStore interface.
func (bs *BlockStore) IpfsDagAPI() format.DAGService {
Copy link
Member

Choose a reason for hiding this comment

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

What about only DAG() or IpfsDAG()? Api seems redundant to me here

Also, the comment does not correspond to the name

Copy link
Member Author

Choose a reason for hiding this comment

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

removed the entire method 8a4026c because we were no longer using it after fixing #356 (comment)

store/store.go Outdated
@@ -5,6 +5,7 @@ import (
"strconv"

"github.com/gogo/protobuf/proto"
format "github.com/ipfs/go-ipld-format"
Copy link
Member

Choose a reason for hiding this comment

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

Let's use ipld alias for go-ipld-format everywhere. I also did that in the previous PR

Copy link
Member Author

Choose a reason for hiding this comment

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

changed here b2469cc

left it as format in the consensus and light packages as they use our own ipld package

Copy link
Member

Choose a reason for hiding this comment

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

Yep, I am going to propose the rename of ipld package soon. We should change its name as it does not explain what it has inside

ipfs/mock.go Outdated
Comment on lines 37 to 68
// DagOnlyMock provides an empty APIProvider that only mocks the DAG portion of
// the ipfs api object. This is much lighter than the full IPFS node and should
// be favored for CI testing
func DagOnlyMock() APIProvider {
mockAPI := dagOnlyMock{mdutils.Mock()}
return func() (coreiface.CoreAPI, io.Closer, error) {
return mockAPI, mockAPI, nil
}
}

var _ coreiface.CoreAPI = dagOnlyMock{}

type dagOnlyMock struct {
format.DAGService
}

func (dom dagOnlyMock) Dag() coreiface.APIDagService { return dom }

func (dagOnlyMock) Unixfs() coreiface.UnixfsAPI { return nil }
func (dagOnlyMock) Block() coreiface.BlockAPI { return nil }
func (dagOnlyMock) Name() coreiface.NameAPI { return nil }
func (dagOnlyMock) Key() coreiface.KeyAPI { return nil }
func (dagOnlyMock) Pin() coreiface.PinAPI { return nil }
func (dagOnlyMock) Object() coreiface.ObjectAPI { return nil }
func (dagOnlyMock) Dht() coreiface.DhtAPI { return nil }
func (dagOnlyMock) Swarm() coreiface.SwarmAPI { return nil }
func (dagOnlyMock) PubSub() coreiface.PubSubAPI { return nil }
func (dagOnlyMock) ResolvePath(context.Context, path.Path) (path.Resolved, error) { return nil, nil }
func (dagOnlyMock) ResolveNode(context.Context, path.Path) (format.Node, error) { return nil, nil }
func (dagOnlyMock) WithOptions(...options.ApiOption) (coreiface.CoreAPI, error) { return nil, nil }
func (dagOnlyMock) Close() error { return nil }
func (dagOnlyMock) Pinning() format.NodeAdder { return nil }
Copy link
Member

Choose a reason for hiding this comment

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

Agree with @liamsi, we can simply deprecate full core API usage. We won't need anything form it except for the DAG.

ipfs/mock.go Outdated
Comment on lines 37 to 68
// DagOnlyMock provides an empty APIProvider that only mocks the DAG portion of
// the ipfs api object. This is much lighter than the full IPFS node and should
// be favored for CI testing
func DagOnlyMock() APIProvider {
mockAPI := dagOnlyMock{mdutils.Mock()}
return func() (coreiface.CoreAPI, io.Closer, error) {
return mockAPI, mockAPI, nil
}
}

var _ coreiface.CoreAPI = dagOnlyMock{}

type dagOnlyMock struct {
format.DAGService
}

func (dom dagOnlyMock) Dag() coreiface.APIDagService { return dom }

func (dagOnlyMock) Unixfs() coreiface.UnixfsAPI { return nil }
func (dagOnlyMock) Block() coreiface.BlockAPI { return nil }
func (dagOnlyMock) Name() coreiface.NameAPI { return nil }
func (dagOnlyMock) Key() coreiface.KeyAPI { return nil }
func (dagOnlyMock) Pin() coreiface.PinAPI { return nil }
func (dagOnlyMock) Object() coreiface.ObjectAPI { return nil }
func (dagOnlyMock) Dht() coreiface.DhtAPI { return nil }
func (dagOnlyMock) Swarm() coreiface.SwarmAPI { return nil }
func (dagOnlyMock) PubSub() coreiface.PubSubAPI { return nil }
func (dagOnlyMock) ResolvePath(context.Context, path.Path) (path.Resolved, error) { return nil, nil }
func (dagOnlyMock) ResolveNode(context.Context, path.Path) (format.Node, error) { return nil, nil }
func (dagOnlyMock) WithOptions(...options.ApiOption) (coreiface.CoreAPI, error) { return nil, nil }
func (dagOnlyMock) Close() error { return nil }
func (dagOnlyMock) Pinning() format.NodeAdder { return nil }
Copy link
Member

Choose a reason for hiding this comment

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

So I don't see any need for dagOnlyMock

@@ -94,8 +93,6 @@ type State struct {
// store blocks and commits
blockStore sm.BlockStore

dag format.DAGService
Copy link
Member

Choose a reason for hiding this comment

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

Pls, keep DAGService in the State how it was. DAGService handles networking as well and making State rely on dag service provided by blockstore is architecturally not a good idea.

Copy link
Member

@Wondertan Wondertan May 27, 2021

Choose a reason for hiding this comment

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

Conceptually, I argue that we should change "move the ipfs dag api object to Blockstore" to "use the ipfs dag api object in Blockstore"

Copy link
Member Author

Choose a reason for hiding this comment

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

that is now true, yes.

@@ -7,4 +7,4 @@ import (
)

// APIProvider allows customizable IPFS core APIs.
type APIProvider func() (coreiface.CoreAPI, io.Closer, error)
type APIProvider func() (coreiface.APIDagService, io.Closer, error)
Copy link
Member

Choose a reason for hiding this comment

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

👍🏻
This should make the IPFS resource usage footprint in tests very low!

Copy link
Member Author

Choose a reason for hiding this comment

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

🤞

@evan-forbes evan-forbes changed the title Move the ipfs dag api object to Blockstore Use the ipfs dag api object in Blockstore May 27, 2021
@evan-forbes evan-forbes changed the title Use the ipfs dag api object in Blockstore Add the ipfs dag api object in Blockstore May 27, 2021
Copy link
Member

@liamsi liamsi left a comment

Choose a reason for hiding this comment

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

You guys rock 🚀 Great work and thanks for the thorough review as well @Wondertan.

@Wondertan
Copy link
Member

The further we go, the more we disassemble the IPFS blob. I start to like this approach as it appears to be more natural than just going straight into breaking it.

@evan-forbes evan-forbes merged commit 40acb17 into master May 27, 2021
@evan-forbes evan-forbes deleted the evan/move-ipfs-to-blockstore branch May 27, 2021 22:08
evan-forbes added a commit that referenced this pull request Aug 25, 2021
evan-forbes added a commit that referenced this pull request Aug 25, 2021
* Revert "Remove the PartSetHeader from VoteSetMaj23, VoteSetBits, and state.State (#479)"

This reverts commit 3ba47c2.

* Revert "Stop Signing over the `PartSetHeader` for Votes and remove it from the `Header` (#457)"

This reverts commit 818be04.

* Revert "Decouple PartSetHeader from BlockID (#441)"

This reverts commit 9d4265d.

* Revert "Save and load block data using IPFS (#374)"

This reverts commit 8da1644.

* fix merge error

* Revert "Add the ipfs dag api object in Blockstore (#356)" and get rid of embedded ipfs objects

This reverts commit 40acb17.

* remove ipfs node provider from new node

* stop init ipfs repos

* remove IPFS node config

* clean up remaining ipfs stuff
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.

Move the IPFS API Object to the BlockStore
4 participants