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

Bloch hash generation by merkle trie root of transactions, results and state root #689

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

bianyuanop
Copy link
Contributor

Context

This PR covers #412 and #503, the goal is to generate block hash Based on Hash Trie of Transactions + State Root + Results Root + Warp Outputs Root . Several things aren't clear to me

  1. Warp Outputs are not found under the builder.go that seems the outputs from warp messages are results of transactions if warpMessage field is not nil of a transaction
  2. How to allow users to verify transactions/results, two ways i can think of depending on the current implementation, we either make modification on the existing merkletree implementation that let it return proofs in order of given TrieItems or we hash the transactions/results and letting the TrieItem.x to be the hash of each item then double hashing won't be needed.

Testing

e2e tests under morpheusvm and tokenvm are passed

Dependencies

The merkletrie implementation borrowed from cbergoon/merkletree, which is a pure implementation so no more dependencies are introduced except itself

chain/block.go Outdated Show resolved Hide resolved
chain/block.go Outdated Show resolved Hide resolved
@bianyuanop
Copy link
Contributor Author

New root generation with stateless merkledb was updated. One thing I'm not sure that will the tx.Bytes() contains info about actor and transaction content itself to distinguish it from other transactions so the keys generated will be different.

block.go#L313

chain/block.go Outdated Show resolved Hide resolved
@bianyuanop
Copy link
Contributor Author

The root generation has been made into a function, I put it under utils/utils.go since it seems unmatch if i put it under crypto. e2e tests under two hypervms were passed

@patrick-ogrady
Copy link
Contributor

The root generation has been made into a function, I put it under utils/utils.go since it seems unmatch if i put it under crypto. e2e tests under two hypervms were passed

could you move it to its own package called merkle? We'll eventually want to write some tests/benchmarks around its performance (say if we added 10k transactions)

utils/utils.go Outdated
@@ -116,3 +122,43 @@ func LoadBytes(filename string, expectedSize int) ([]byte, error) {
}
return bytes, nil
}

// Generate merkle root for a set of items
func GenerateMerkleRoot(ctx context.Context, tracer trace.Tracer, merkleItems [][]byte, consumeBytes bool) ([]byte, merkledb.MerkleDB, error) {
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

Choose a reason for hiding this comment

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

@dboehm-avalabs it would be great if you could confirm correctness here.

chain/block.go Outdated
// transaction hash generation
merkleItems := make([][]byte, 0, len(b.Txs)+len(b.results))
for _, tx := range b.Txs {
merkleItems = append(merkleItems, tx.Bytes())
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it make sense to use txID as key and then put something useful in the value?

Copy link
Contributor Author

@bianyuanop bianyuanop Jan 20, 2024

Choose a reason for hiding this comment

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

will the same type of transactions have distinct id for different actors? nor there will be collision

chain/block.go Outdated Show resolved Hide resolved
@bianyuanop
Copy link
Contributor Author

Root generation function has been moved to merkle package. Now the TxsRoot are generated by root of merkle trie with items in format [txID + result]

Copy link

This PR has become stale because it has been open for 30 days with no activity. Adding the lifecycle/frozen label will exempt this PR from future lifecycle events..

@iFrostizz
Copy link
Contributor

iFrostizz commented Mar 18, 2024

Having the transaction hashes concatenated with the transaction results doesn't look very idiomatic to me, and at the same time if we provide results in a flat data structure then it will do a collision. Do we really need to be able to prove that the result of a transaction given the current state is correct using the merkle tree ? If it's something that people really want to do, then they could execute the transactions in the block sequentially to find that their execution results matches the one stored in the block.
Also, if the aim is to avoid any execution because it may be expensive, then we could just keep the transaction root as well as the slice of results so that the index of the transaction (whose inclusion can be proven) can be used to retrieve the result of the transaction which is already available in the block.

@bianyuanop
Copy link
Contributor Author

I agree with that, and especially currently I see the transaction results won't get stored locally so when do hashing it's better without concatenating result along with the tx.

Copy link

This PR has become stale because it has been open for 30 days with no activity. Adding the lifecycle/frozen label will exempt this PR from future lifecycle events..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Backlog 🗄️
Development

Successfully merging this pull request may close these issues.

4 participants