Skip to content

Commit

Permalink
Rename balloon.Commitment to balloon.Snapshot
Browse files Browse the repository at this point in the history
  • Loading branch information
iknite committed Nov 27, 2018
1 parent e098527 commit eaa6102
Show file tree
Hide file tree
Showing 15 changed files with 73 additions and 72 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ This software is experimental and part of the research being done at BBVA Labs.
## Motivation
The use of a technology that allows to verify the information it stores is quite broad. Audit logs are a common tool for forensic investigations and legal proceedings due to its utility for detecting database tampering. Malicious users, including insiders with high-level access, may perform unlogged activities or tamper with the recorded history. The evidence one seeks in these sorts of investigations often takes the form of statements of existence and order. But this kind of tamper-evident logs have also been used for other use cases: building versioned filesystems like version control systems, p2p protocols or as a mechanism to detect conflicts in distributing systems, like data inconsistencies between replicas.

All of these use cases share something in common: the proof of order and integrity is fulfilled building data structures based on the concept of hash chaining. This technique allows to establish a provable order between entries, and comes with the benefit of tamper-evidence, ensuring that any commitment to a given state of the log is implicitly a commitment to all prior states. Therefore, any subsequent attempt to remove or alter some log entries will invalidate the hash chain.
All of these use cases share something in common: the proof of order and integrity is fulfilled building data structures based on the concept of hash chaining. This technique allows to establish a provable order between entries, and comes with the benefit of tamper-evidence, ensuring that any snapshot to a given state of the log is implicitly a snapshot to all prior states. Therefore, any subsequent attempt to remove or alter some log entries will invalidate the hash chain.

In order to prove that an entry has been included in the information storage, and that it has not been modified in an inconsistent way we need:

Expand Down
4 changes: 2 additions & 2 deletions api/apihttp/apihttp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ type fakeRaftBalloon struct {
raftID string
}

func (b fakeRaftBalloon) Add(event []byte) (*balloon.Commitment, error) {
return &balloon.Commitment{hashing.Digest{0x02}, hashing.Digest{0x00}, hashing.Digest{0x01}, 0}, nil
func (b fakeRaftBalloon) Add(event []byte) (*balloon.Snapshot, error) {
return &balloon.Snapshot{hashing.Digest{0x02}, hashing.Digest{0x00}, hashing.Digest{0x01}, 0}, nil
}

func (b fakeRaftBalloon) Join(nodeID, addr string) error {
Expand Down
21 changes: 11 additions & 10 deletions balloon/balloon.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,10 @@ func NewBalloon(store storage.Store, hasherF func() hashing.Hasher) (*Balloon, e
return balloon, nil
}

// Commitment is the struct that has both history and hyper digest and the
// Snapshot is the struct that has both history and hyper digest and the
// current version for that rootNode digests.
type Commitment struct {
type Snapshot struct {
EventDigest hashing.Digest
HistoryDigest hashing.Digest
HyperDigest hashing.Digest
Version uint64
Expand Down Expand Up @@ -111,17 +112,17 @@ func NewMembershipProof(
// Verify verifies a proof and answer from QueryMembership. Returns true if the
// answer and proof are correct and consistent, otherwise false.
// Run by a client on input that should be verified.
func (p MembershipProof) Verify(event []byte, commitment *Commitment) bool {
func (p MembershipProof) Verify(event []byte, snapshot *Snapshot) bool {
if p.HyperProof == nil || p.HistoryProof == nil {
return false
}

digest := p.Hasher.Do(event)
hyperCorrect := p.HyperProof.Verify(digest, commitment.HyperDigest)
hyperCorrect := p.HyperProof.Verify(digest, snapshot.HyperDigest)

if p.Exists {
if p.QueryVersion <= p.ActualVersion {
historyCorrect := p.HistoryProof.Verify(digest, commitment.HistoryDigest)
historyCorrect := p.HistoryProof.Verify(digest, snapshot.HistoryDigest)
return hyperCorrect && historyCorrect
}
}
Expand All @@ -148,9 +149,9 @@ func NewIncrementalProof(
}
}

func (p IncrementalProof) Verify(commitmentStart, commitmentEnd *Commitment) bool {
func (p IncrementalProof) Verify(snapshotStart, snapshotEnd *Snapshot) bool {
ip := history.NewIncrementalProof(p.Start, p.End, p.AuditPath, p.Hasher)
return ip.Verify(commitmentStart.HistoryDigest, commitmentEnd.HistoryDigest)
return ip.Verify(snapshotStart.HistoryDigest, snapshotEnd.HistoryDigest)
}

func (b Balloon) Version() uint64 {
Expand All @@ -170,7 +171,7 @@ func (b *Balloon) RefreshVersion() error {
return nil
}

func (b *Balloon) Add(event []byte) (*Commitment, []*storage.Mutation, error) {
func (b *Balloon) Add(event []byte) (*Snapshot, []*storage.Mutation, error) {

// Activate metrics gathering
stats := metrics.Balloon
Expand Down Expand Up @@ -208,7 +209,7 @@ func (b *Balloon) Add(event []byte) (*Commitment, []*storage.Mutation, error) {
// Append trees mutations
mutations = append(mutations, historyMutations...)

commitment := &Commitment{
snapshot := &Snapshot{
EventDigest: eventDigest,
HistoryDigest: historyDigest,
HyperDigest: hyperDigest,
Expand All @@ -219,7 +220,7 @@ func (b *Balloon) Add(event []byte) (*Commitment, []*storage.Mutation, error) {
stats.AddFloat("add_hits", 1)
stats.Set("version", metrics.Uint64ToVar(version))

return commitment, mutations, nil
return snapshot, mutations, nil
}

func (b Balloon) QueryMembership(event []byte, version uint64) (*MembershipProof, error) {
Expand Down
52 changes: 26 additions & 26 deletions balloon/balloon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ func TestAdd(t *testing.T) {
require.NoError(t, err)

for i := uint64(0); i < 9; i++ {
commitment, mutations, err := balloon.Add(rand.Bytes(128))
snapshot, mutations, err := balloon.Add(rand.Bytes(128))
store.Mutate(mutations)

require.NoError(t, err)
assert.Truef(t, len(mutations) > 0, "There should be some mutations in test %d", i)
assert.Equalf(t, i, commitment.Version, "Wrong version in test %d", i)
assert.NotNil(t, commitment.HyperDigest, "The HyperDigest shouldn't be nil in test %d", i)
assert.NotNil(t, commitment.HistoryDigest, "The HistoryDigest shouldn't be nil in test %d", i)
assert.Equalf(t, i, snapshot.Version, "Wrong version in test %d", i)
assert.NotNil(t, snapshot.HyperDigest, "The HyperDigest shouldn't be nil in test %d", i)
assert.NotNil(t, snapshot.HistoryDigest, "The HistoryDigest shouldn't be nil in test %d", i)
}

}
Expand Down Expand Up @@ -122,7 +122,7 @@ func TestMembershipProofVerify(t *testing.T) {

for i, c := range testCases {
event := []byte("Yadda yadda")
commitment := &Commitment{
snapshot := &Snapshot{
event, //TODO: should be eventDigest and used in the test
hashing.Digest("Some hyperDigest"),
hashing.Digest("Some historyDigest"),
Expand All @@ -139,7 +139,7 @@ func TestMembershipProofVerify(t *testing.T) {
hashing.NewSha256Hasher(),
)

result := proof.Verify(event, commitment)
result := proof.Verify(event, snapshot)

require.Equalf(t, c.expectedResult, result, "Unexpected result '%v' in test case '%d'", result, i)
}
Expand Down Expand Up @@ -193,15 +193,15 @@ func TestAddQueryAndVerify(t *testing.T) {
event := hashing.Digest("Never knows best")

// Add event
commitment, mutations, err := b.Add(event)
snapshot, mutations, err := b.Add(event)
store.Mutate(mutations)

// Query event
proof, err := b.QueryMembership(event, commitment.Version)
proof, err := b.QueryMembership(event, snapshot.Version)
assert.NoError(t, err)

// Verify
assert.True(t, proof.Verify(event, commitment), "The proof should verify correctly")
assert.True(t, proof.Verify(event, snapshot), "The proof should verify correctly")
}

func TestCacheWarmingUp(t *testing.T) {
Expand All @@ -216,11 +216,11 @@ func TestCacheWarmingUp(t *testing.T) {
require.NoError(t, err)

// add 100 elements
var lastCommitment *Commitment
var lastSnapshot *Snapshot
for i := uint64(0); i < 100; i++ {
commitment, mutations, err := balloon.Add(util.Uint64AsBytes(i))
snapshot, mutations, err := balloon.Add(util.Uint64AsBytes(i))
require.NoError(t, err)
lastCommitment = commitment
lastSnapshot = snapshot
store.Mutate(mutations)
}

Expand All @@ -235,9 +235,9 @@ func TestCacheWarmingUp(t *testing.T) {
// query for all elements
for i := uint64(0); i < 100; i++ {
key := util.Uint64AsBytes(i)
proof, err := balloon.QueryMembership(key, lastCommitment.Version)
proof, err := balloon.QueryMembership(key, lastSnapshot.Version)
require.NoError(t, err)
require.Truef(t, proof.Verify(key, lastCommitment), "The proof should verify correctly for element %d", i)
require.Truef(t, proof.Verify(key, lastSnapshot), "The proof should verify correctly for element %d", i)
}
}

Expand All @@ -253,12 +253,12 @@ func TestTamperAndVerify(t *testing.T) {
event := hashing.Digest("Never knows best")
eventDigest := b.hasher.Do(event)

commitment, mutations, err := b.Add(event)
snapshot, mutations, err := b.Add(event)
store.Mutate(mutations)

memProof, err := b.QueryMembership(event, commitment.Version)
memProof, err := b.QueryMembership(event, snapshot.Version)
assert.NoError(t, err)
assert.True(t, memProof.Verify(event, commitment), "The proof should verify correctly")
assert.True(t, memProof.Verify(event, snapshot), "The proof should verify correctly")

original, err := store.Get(storage.IndexPrefix, eventDigest)
assert.NoError(t, err)
Expand All @@ -275,7 +275,7 @@ func TestTamperAndVerify(t *testing.T) {
assert.Equal(t, tpBytes, tampered.Value, "Tamper unsuccessful")
assert.NotEqual(t, original.Value, tampered.Value, "Tamper unsuccessful")

_, err = b.QueryMembership(event, commitment.Version)
_, err = b.QueryMembership(event, snapshot.Version)
require.Error(t, err)
}

Expand All @@ -291,18 +291,18 @@ func TestDeleteAndVerify(t *testing.T) {
event := hashing.Digest("Never knows best")
eventDigest := b.hasher.Do(event)

commitment, mutations, err := b.Add(event)
snapshot, mutations, err := b.Add(event)
store.Mutate(mutations)

memProof, err := b.QueryMembership(event, commitment.Version)
memProof, err := b.QueryMembership(event, snapshot.Version)
assert.NoError(t, err)
assert.True(t, memProof.Verify(event, commitment), "The proof should verify correctly")
assert.True(t, memProof.Verify(event, snapshot), "The proof should verify correctly")
assert.NoError(t, store.Delete(storage.IndexPrefix, eventDigest), "store delete returned non nil value")

tampered, _ := store.Get(storage.IndexPrefix, eventDigest)
assert.Nil(t, tampered)

proof, err := b.QueryMembership(event, commitment.Version)
proof, err := b.QueryMembership(event, snapshot.Version)
assert.Nil(t, proof)
assert.Error(t, err, "ballon should not return a proof")
}
Expand All @@ -317,20 +317,20 @@ func TestGenIncrementalAndVerify(t *testing.T) {
assert.NoError(t, err)

size := 10
c := make([]*Commitment, size)
s := make([]*Snapshot, size)
for i := 0; i < size; i++ {
event := hashing.Digest(fmt.Sprintf("Never knows %d best", i))
commitment, mutations, _ := b.Add(event)
snapshot, mutations, _ := b.Add(event)
store.Mutate(mutations)
c[i] = commitment
s[i] = snapshot
}

start := uint64(1)
end := uint64(7)
proof, err := b.QueryConsistency(start, end)
assert.NoError(t, err)

correct := proof.Verify(c[start], c[end])
correct := proof.Verify(s[start], s[end])
assert.True(t, correct, "Unable to verify incremental proof")
}

Expand Down
8 changes: 4 additions & 4 deletions balloon/hyper/tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ func TestAdd(t *testing.T) {

for i, c := range testCases {
index := uint64(i)
commitment, mutations, err := tree.Add(c.eventDigest, index)
snapshot, mutations, err := tree.Add(c.eventDigest, index)
tree.store.Mutate(mutations)
require.NoErrorf(t, err, "This should not fail for index %d", i)
assert.Equalf(t, c.expectedRootHash, commitment, "Incorrect root hash for index %d", i)
assert.Equalf(t, c.expectedRootHash, snapshot, "Incorrect root hash for index %d", i)

}
}
Expand Down Expand Up @@ -154,7 +154,7 @@ func TestAddAndVerify(t *testing.T) {
tree := NewHyperTree(c.hasherF, store, simpleCache)

key := hasher.Do(hashing.Digest("a test event"))
commitment, mutations, err := tree.Add(key, value)
snapshot, mutations, err := tree.Add(key, value)
tree.store.Mutate(mutations)
require.NoErrorf(t, err, "This should not fail for index %d", i)

Expand All @@ -165,7 +165,7 @@ func TestAddAndVerify(t *testing.T) {
require.Nilf(t, err, "Error must be nil for index %d", i)
assert.Equalf(t, util.Uint64AsBytes(value), proof.Value, "Incorrect actual value for index %d", i)

correct := tree.VerifyMembership(proof, value, key, commitment)
correct := tree.VerifyMembership(proof, value, key, snapshot)
assert.Truef(t, correct, "Key %x should be a member for index %d", key, i)
}
}
Expand Down
2 changes: 1 addition & 1 deletion balloon/visitor/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func NewFakeVerifiable(result bool) *FakeVerifiable {
return &FakeVerifiable{result}
}

func (f FakeVerifiable) Verify(key []byte, commitment hashing.Digest) bool {
func (f FakeVerifiable) Verify(key []byte, snapshot hashing.Digest) bool {
return f.result
}

Expand Down
8 changes: 4 additions & 4 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ func (c HttpClient) Verify(result *protocol.MembershipResult, snap *protocol.Sna

proof := protocol.ToBalloonProof([]byte(c.apiKey), result, hasherF)

return proof.Verify(snap.EventDigest, &balloon.Commitment{
return proof.Verify(snap.EventDigest, &balloon.Snapshot{
snap.EventDigest,
snap.HistoryDigest,
snap.HyperDigest,
Expand All @@ -183,19 +183,19 @@ func (c HttpClient) VerifyIncremental(result *protocol.IncrementalResponse, star

proof := protocol.ToIncrementalProof(result, hasher)

startCommitment := &balloon.Commitment{
start := &balloon.Snapshot{
startSnapshot.EventDigest,
startSnapshot.HistoryDigest,
startSnapshot.HyperDigest,
startSnapshot.Version,
}
endCommitment := &balloon.Commitment{
end := &balloon.Snapshot{
endSnapshot.EventDigest,
endSnapshot.HistoryDigest,
endSnapshot.HyperDigest,
endSnapshot.Version,
}

return proof.Verify(startCommitment, endCommitment)
return proof.Verify(start, end)

}
2 changes: 1 addition & 1 deletion cmd/agent_monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func newAgentMonitorCommand(ctx *agentContext) *cobra.Command {
Short: "Start a QED monitor",
Long: `Start a QED monitor that reacts to snapshot batches
propagated by QED servers and periodically executes incremental
queries to verify the consistency between commitments`,
queries to verify the consistency between snaphots`,
Run: func(cmd *cobra.Command, args []string) {

log.SetLogger("QedMonitor", logLevel)
Expand Down
2 changes: 1 addition & 1 deletion cmd/client_incremental.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func newIncrementalCommand(ctx *clientContext) *cobra.Command {
startSnapshot := &protocol.Snapshot{sdBytes, nil, start, nil}
endSnapshot := &protocol.Snapshot{edBytes, nil, end, nil}

log.Infof("Verifying with commitments: \n\tStartDigest: %s\n\tEndDigest: %s\n",
log.Infof("Verifying with snapshots: \n\tStartDigest: %s\n\tEndDigest: %s\n",
startDigest, endDigest)
if ctx.client.VerifyIncremental(proof, startSnapshot, endSnapshot, hashing.NewSha256Hasher()) {
log.Info("Verify: OK")
Expand Down
4 changes: 2 additions & 2 deletions cmd/client_membership.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ func newMembershipCommand(ctx *clientContext) *cobra.Command {
htdBytes, _ := hex.DecodeString(historyDigest)
snapshot := &protocol.Snapshot{htdBytes, hdBytes, version, event}

log.Infof("Verifying with commitment: \n\tHyperDigest: %s\n\tHistoryDigest: %s\n\tVersion: %d\n",
hyperDigest, historyDigest, version)
log.Infof("Verifying with Snapshot: \n\tEventDigest:%s\n\tHyperDigest: %s\n\tHistoryDigest: %s\n\tVersion: %d\n",
event, hyperDigest, historyDigest, version)
if ctx.client.Verify(proof, snapshot, hashing.NewSha256Hasher) {
log.Info("Verify: OK")
} else {
Expand Down
2 changes: 1 addition & 1 deletion gossip/sender/sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func (s *Sender) doSign(snapshot *protocol.Snapshot) (*protocol.SignedSnapshot,

signature, err := s.signer.Sign([]byte(fmt.Sprintf("%v", snapshot)))
if err != nil {
fmt.Println("Publisher: error signing commitment")
fmt.Println("Publisher: error signing snapshot")
return nil, err
}
return &protocol.SignedSnapshot{snapshot, signature}, nil
Expand Down
14 changes: 7 additions & 7 deletions raftwal/fsm.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ type fsmGenericResponse struct {
}

type fsmAddResponse struct {
commitment *balloon.Commitment
error error
snapshot *balloon.Snapshot
error error
}

type BalloonFSM struct {
Expand Down Expand Up @@ -175,7 +175,7 @@ func (fsm *BalloonFSM) Close() error {

func (fsm *BalloonFSM) applyAdd(event []byte, state *fsmState) *fsmAddResponse {

commitment, mutations, err := fsm.balloon.Add(event)
snapshot, mutations, err := fsm.balloon.Add(event)
if err != nil {
return &fsmAddResponse{error: err}
}
Expand All @@ -194,13 +194,13 @@ func (fsm *BalloonFSM) applyAdd(event []byte, state *fsmState) *fsmAddResponse {

//Send snapshot to gossip agents
fsm.agentsQueue <- &protocol.Snapshot{
HistoryDigest: commitment.HistoryDigest,
HyperDigest: commitment.HyperDigest,
Version: commitment.Version,
HistoryDigest: snapshot.HistoryDigest,
HyperDigest: snapshot.HyperDigest,
Version: snapshot.Version,
EventDigest: event,
}

return &fsmAddResponse{commitment: commitment}
return &fsmAddResponse{snapshot: snapshot}
}

// Decode reverses the encode operation on a byte slice input
Expand Down
Loading

0 comments on commit eaa6102

Please sign in to comment.