research/archive/merkleslash/merkleslash_test.go

184 lines
6.1 KiB
Go

package main
import "testing"
import "log"
import "github.com/cbergoon/merkletree"
func TestBasicGood(t *testing.T) {
// Pre-compute expected tree
var list []merkletree.Content
list = append(list, TestContent{x: "1"})
list = append(list, TestContent{x: "2"})
list = append(list, TestContent{x: "3"})
list = append(list, TestContent{x: "4"})
mt, _ := merkletree.NewTree(list)
trustedRoot := toHex(mt.MerkleRoot())
// Local node setup, partial
// Assume has access to trustedRoot
var contents []merkletree.Content
contents = append(contents, TestContent{x: "1"})
contents = append(contents, TestContent{x: "2"})
contents = append(contents, TestContent{x: "3"})
// Byzantine case, currently sending nothing
// TODO: Since haves is empty it should return full contents?
// XXX: Doesn't make sense to have tree hardcoded in other code
var haves []string
untrustedPayloads := pull("good", trustedRoot, haves)
content := TestContent{x: untrustedPayloads[0]}
contents = append(contents, content)
// XXX: is there no way to append to tree?
untrusted := mt
_ = untrusted.RebuildTreeWith(contents)
untrustedRoot := toHex(untrusted.MerkleRoot())
expect := (untrustedRoot == trustedRoot)
if !expect {
t.Errorf("Good basic: Untrusted root %s and trusted root %s should match", untrustedRoot, trustedRoot)
}
}
func TestBasicByzantine(t *testing.T) {
// Pre-compute expected tree
var list []merkletree.Content
list = append(list, TestContent{x: "1"})
list = append(list, TestContent{x: "2"})
list = append(list, TestContent{x: "3"})
list = append(list, TestContent{x: "4"})
mt, _ := merkletree.NewTree(list)
trustedRoot := toHex(mt.MerkleRoot())
// Local node setup, partial
// Assume has access to trustedRoot
var contents []merkletree.Content
contents = append(contents, TestContent{x: "1"})
contents = append(contents, TestContent{x: "2"})
contents = append(contents, TestContent{x: "3"})
// Byzantine case, currently sending nothing
// TODO: Since haves is empty it should return full contents?
// XXX: Doesn't make sense to have tree hardcoded in other code
var haves []string
untrustedPayloads := pull("byzantine", trustedRoot, haves)
content := TestContent{x: untrustedPayloads[0]}
contents = append(contents, content)
// XXX: is there no way to append to tree?
untrusted := mt
_ = untrusted.RebuildTreeWith(contents)
untrustedRoot := toHex(untrusted.MerkleRoot())
expect := (untrustedRoot != trustedRoot)
if !expect {
t.Errorf("Byzantine basic: Untrusted root %s and trusted root %s shouldn't match", untrustedRoot, trustedRoot)
}
}
// Here's what I want to test:
// Full tree: C->A; C->B; B->h(3); B->h(4); h(4)->4
// Trusted root: C
// Get from untrusted root: A, h(3) ("small") and 4 ("big"). Through these pieces of data we can verify.
// What does this mean if you have or don't have e.g. A branch? (which can hide a lot of data)
// I guess this is difference between thin and full client.
// See: https://bitcoin.stackexchange.com/questions/50674/why-is-the-full-merkle-path-needed-to-verify-a-transaction
//
// Next question: how do we specify path? Index [0 1], etc.
// Lets try GetMerklePath
// Not clear exactly how it maps or changes as we rebuild tree but ok for now
// Now, how can we do partial rebuild here?
//
// As a client, I say I have A [x, y], h(3) [x, y]. And a trusted root hash.
// So I guess there are two ways the query can go: for a specific piece of data (how know?) and diff.
// Lets graph: https://notes.status.im/MLGgpdgqRzeyTqVWkl7gjg#
// Can use Whisper/mailservers as well for compatibility before Swarm Feeds ready, boom new topic
func printPath(mt merkletree.MerkleTree, item merkletree.Content, name string) {
_, x, err := mt.GetMerklePath(item)
log.Println("Path to", name, x)
if err != nil {
log.Fatal(err)
}
}
// 4 nodes
// 2019/04/18 11:49:07 Path to 1 [1 1]
// 2019/04/18 11:49:07 Path to 2 [0 1]
// 2019/04/18 11:49:07 Path to 3 [1 0]
// 2019/04/18 11:49:07 Path to 4 [0 0]
// 5 nodes
// 2019/04/18 11:54:36 Path to 1 [1 1 1]
// 2019/04/18 11:54:36 Path to 2 [0 1 1]
// 2019/04/18 11:54:36 Path to 3 [1 0 1]
// 2019/04/18 11:54:36 Path to 4 [0 0 1]
// 2019/04/18 11:54:36 Path to 5 [1 1 0]
// XXX: Probably need a less naive implementation
// Yellow paper quote:
// > The core of the trie, and its sole requirement in termsof the protocol specification,
// > is to provide a single value that identifies a given set of key-value pairs, which may be
// > either a 32-byte sequence or the empty byte sequence.
//
// So let's start there and happily rebuild
func TestPartialVerification(t *testing.T) {
// Pre-compute expected tree
// XXX: Have you heard of for loops
var list []merkletree.Content
item1 := TestContent{x: "1"}
item2 := TestContent{x: "2"}
item3 := TestContent{x: "3"}
item4 := TestContent{x: "4"}
item5 := TestContent{x: "5"}
list = append(list, item1)
list = append(list, item2)
list = append(list, item3)
list = append(list, item4)
list = append(list, item5)
mt, _ := merkletree.NewTree(list)
//trustedRoot := toHex(mt.MerkleRoot())
printPath(*mt, item1, "1")
printPath(*mt, item2, "2")
printPath(*mt, item3, "3")
printPath(*mt, item4, "4")
printPath(*mt, item5, "5")
// print tree
log.Print("TREE", mt.String())
// // Local node setup, partial
// // Assume has access to trustedRoot
// var contents []merkletree.Content
// contents = append(contents, TestContent{x: "1"})
// contents = append(contents, TestContent{x: "2"})
// contents = append(contents, TestContent{x: "3"})
// // Byzantine case, currently sending nothing
// // TODO: Since haves is empty it should return full contents?
// // XXX: Doesn't make sense to have tree hardcoded in other code
// var haves []string
// untrustedPayloads := pull("good", trustedRoot, haves)
// content := TestContent{x: untrustedPayloads[0]}
// contents = append(contents, content)
// // XXX: is there no way to append to tree?
// untrusted := mt
// _ = untrusted.RebuildTreeWith(contents)
// untrustedRoot := toHex(untrusted.MerkleRoot())
// expect := (untrustedRoot == trustedRoot)
// if !expect {
// t.Errorf("Good basic: Untrusted root %s and trusted root %s should match", untrustedRoot, trustedRoot)
// }
}