// Update updates balloon with the slice of events, producing the next snapshot. // Run by the author on trusted input. func (balloon *Balloon) Update(events []Event, current *Snapshot, sk []byte) (next *Snapshot, err error) { if len(events) == 0 { return nil, errors.New("you need to add at least one event") } if !util.Equal(current.Roots.History, balloon.history.Root()) || !util.Equal(current.Roots.Treap, balloon.treap.Root()) { return nil, errors.New("provided snapshot is not current") } sort.Sort(ByKey(events)) // attempt to add events treap := balloon.treap ht := balloon.history.Clone() for i := 0; i < len(events); i++ { // add the hash of the entire event to the history tree _, err = ht.Add(util.Hash(append(events[i].Key, events[i].Value...))) if err != nil { return } // add to the treap the hash of the key pointing to the index (version) of the // hash of the event in the history tree treap, err = treap.Add(util.Hash(events[i].Key), util.Itob(ht.LatestVersion())) if err != nil { return } } // attempt to create next snapshot next = new(Snapshot) next.Index = current.Index + 1 next.Roots.History = ht.Root() next.Roots.Treap = treap.Root() next.Roots.Version = ht.LatestVersion() next.Previous = current.Signature signature, err := util.Sign(balloon.sk, append(append([]byte("snapshot"), next.Roots.History...), append(next.Roots.Treap, next.Previous...)...)) if err != nil { panic(err) } next.Signature = signature // all is OK, save result err = balloon.Storage.Store(events, *next) if err != nil { return nil, err } balloon.latestsnapshot = *next if len(events) > 0 { balloon.latesteventkey = events[len(events)-1].Key } balloon.treap = treap balloon.history = ht return }
// Setup creates a new balloon based on the slice of events (may be empty or nil). Returns the // first snapshot. Run by the author on trusted input. func Setup(events []Event, sk, vk []byte, storage EventStorage) (balloon *Balloon, snap *Snapshot, err error) { balloon = NewBalloon(storage) balloon.sk = sk balloon.vk = vk // do same as update, allow events to be empty if len(events) > 0 { sort.Sort(ByKey(events)) // add events for i := 0; i < len(events); i++ { // add the hash of the entire event to the history tree _, err = balloon.history.Add(util.Hash(append(events[i].Key, events[i].Value...))) if err != nil { return nil, nil, err } // add to the treap the hash of the key pointing to the index (version) of the // hash of the event in the history tree balloon.treap, err = balloon.treap.Add(util.Hash(events[i].Key), util.Itob(balloon.history.LatestVersion())) if err != nil { return nil, nil, err } } } // create first snapshot snap = new(Snapshot) snap.Index = 0 snap.Roots.History = balloon.history.Root() snap.Roots.Treap = balloon.treap.Root() snap.Roots.Version = balloon.history.LatestVersion() snap.Previous = nil signature, err := util.Sign(balloon.sk, append(append([]byte("snapshot"), snap.Roots.History...), append(snap.Roots.Treap, snap.Previous...)...)) if err != nil { panic(err) } snap.Signature = signature // actually store events err = balloon.Storage.Store(events, *snap) if err != nil { return nil, nil, err } balloon.latestsnapshot = *snap if len(events) > 0 { balloon.latesteventkey = events[len(events)-1].Key } return }
// Update creates the next snapshot from adding the provided events in the balloon // fixed by the current snapshot. This function depends on that the provided prune proof has // been successfully verified for the answer true. // Run by the author on input that should have been verified before by using Verify. func (proof *PruneProof) Update(events []Event, current *Snapshot, sk []byte) (next *Snapshot, err error) { sort.Sort(ByKey(events)) // calculate balloon internal keys and values based on events startIndex := current.Roots.Version + 1 values := make([][]byte, len(events)) treapKeys := make([][]byte, len(events)) treapValues := make([][]byte, len(events)) for i := 0; i < len(events); i++ { values[i] = util.Hash(append(events[i].Key, events[i].Value...)) treapKeys[i] = util.Hash(events[i].Key) treapValues[i] = util.Itob(startIndex + i) } // calculate updated commitment on the history tree c, version, err := proof.QueryProof.HistoryProof.Update(values) if err != nil { return nil, err } // calculate updated hash treap root root, err := proof.TreapProof.Update(treapKeys, treapValues) if err != nil { return nil, err } next = new(Snapshot) next.Index = current.Index + 1 next.Roots.History = c next.Roots.Treap = root next.Roots.Version = version next.Previous = current.Signature signature, err := util.Sign(sk, append(append([]byte("snapshot"), next.Roots.History...), append(next.Roots.Treap, next.Previous...)...)) if err != nil { panic(err) } next.Signature = signature return }