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 SQL storage support #20

Merged
merged 13 commits into from
Jul 31, 2024
Merged

Add SQL storage support #20

merged 13 commits into from
Jul 31, 2024

Conversation

jimthematrix
Copy link
Contributor

No description provided.

Signed-off-by: Jim Zhang <jim.zhang@kaleido.io>
Signed-off-by: Jim Zhang <jim.zhang@kaleido.io>
Signed-off-by: Jim Zhang <jim.zhang@kaleido.io>
Signed-off-by: Jim Zhang <jim.zhang@kaleido.io>
Signed-off-by: Jim Zhang <jim.zhang@kaleido.io>
…rcuit

Signed-off-by: Jim Zhang <jim.zhang@kaleido.io>
Signed-off-by: Jim Zhang <jim.zhang@kaleido.io>
Copy link
Contributor

@EnriqueL8 EnriqueL8 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 - a few comments and I might be missing some context so feel free to disregard comments :)

Comment on lines +205 to 206
// the node that doesn't exist yet. We can add the new leaf node here
return mt.addNode(newLeaf)
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you need a write lock?

Copy link
Contributor

Choose a reason for hiding this comment

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

It's confusing because inside addNode you also do a getNode and none of these have a lock so you are always relying on the calling function to lock which is dangerous. I understand why you are doing it because in theaddLeaf function you need to iterate and you don't want to lock and unlock on each iteration.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the nested addLeaf() calls are the main reason for now doing more granular lock/unlock. The series of updates from the lead node up to the root with the branch nodes along the way must be atomic, otherwise we end up with a broken/inconsistent tree. thus I felt having an overall write lock on the calling function is the best way to go.

zkp/golang/internal/smt/merkletree.go Show resolved Hide resolved
zkp/golang/internal/storage/sql.go Outdated Show resolved Hide resolved
const (
// we use a table to store the root node indexes for
// all the merkle trees in the database
TreeRootsTable = "smtRoots"
Copy link
Contributor

Choose a reason for hiding this comment

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

should it just be merkelTreeRoots instead of sparse merkle tree in case we implement another type of tree?

// See the License for the specific language governing permissions and
// limitations under the License.

package storage
Copy link
Contributor

@EnriqueL8 EnriqueL8 Jul 30, 2024

Choose a reason for hiding this comment

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

I also feels like this package should be inside the merkle tree pkg and not storage, because it's not a generic read from this table. It's more like read a node from this merkle tree that happens to be stored in SQL and decode it in such a way to determine if it's a leaf or a branch node etc...

Copy link
Contributor Author

@jimthematrix jimthematrix Jul 30, 2024

Choose a reason for hiding this comment

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

good point. in fact there's a subsequent PR that move all the merkle tree specific packages into a top-level sparse-merkle-tree package. hope it's OK to keep it as-is for this PR for now

zkp/golang/internal/storage/sql.go Outdated Show resolved Hide resolved
n := core.SMTNode{
RefKey: ref.Hex(),
}
err := m.p.DB().Table(m.nodesTableName).First(&n).Error
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder what it safer:

  • To have a Golang RLock?
  • To have an actual DB lock on write?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think in our case implementing the locks in golang might be the way to do, as there are complex call paths that goes from writing to reading, such as when addLeaf() calls getNode(). it'd be very complex and dead-lock prone to try to do the locks inside the DB calls in the storage package.

zkp/golang/internal/storage/sql.go Outdated Show resolved Hide resolved
Signed-off-by: Jim Zhang <jim.zhang@kaleido.io>
Signed-off-by: Jim Zhang <jim.zhang@kaleido.io>
Signed-off-by: Jim Zhang <jim.zhang@kaleido.io>
Copy link
Contributor

@EnriqueL8 EnriqueL8 left a comment

Choose a reason for hiding this comment

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

Looks good - few more small comments

Comment on lines +28 to +31
- uses: codecov/codecov-action@v4
with:
codecov_yml_path: ./codecov.yml
token: ${{ secrets.CODECOV_TOKEN }}
Copy link
Contributor

@EnriqueL8 EnriqueL8 Jul 30, 2024

Choose a reason for hiding this comment

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

awesome, I have touched base in the pass with the Hyperledger team to setup codecov! Can reach out to set it up for this repo

zkp/golang/Makefile Outdated Show resolved Hide resolved
zkp/golang/Makefile Show resolved Hide resolved
Comment on lines 69 to 72
Type byte
Index *string // only leaf nodes have an index
LeftChild *string // only branch nodes have children
RightChild *string
Copy link
Contributor

Choose a reason for hiding this comment

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

do you need to annotate this with gorm of it will default to VARCHAR for strings?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good question, they are 64 character hex strings, is there a better SQL data type to use than VARCHAR?

Copy link
Contributor

@EnriqueL8 EnriqueL8 Jul 30, 2024

Choose a reason for hiding this comment

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

What is default length that GROM generated for VARCHAR? For example SQLITE VARCHAR is unbounded but PSQL is bounded

Copy link
Contributor Author

Choose a reason for hiding this comment

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

looks like there's a way to specify a size in the gorm annotation. so added that to the structs for both tables

Signed-off-by: Jim Zhang <jim.zhang@kaleido.io>
Signed-off-by: Jim Zhang <jim.zhang@kaleido.io>
Copy link
Contributor

@EnriqueL8 EnriqueL8 left a comment

Choose a reason for hiding this comment

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

Looks good to me

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.

2 participants