func (b *Balloon) Version() uint64 {
	return b.version
}
Version function returns the current (last) balloon version.
package balloon
import (
	"errors"
	"fmt"
	"sync"
	"github.com/bbva/qed/balloon/history"
	"github.com/bbva/qed/balloon/hyper"
	"github.com/bbva/qed/crypto/hashing"
	"github.com/bbva/qed/log"
	"github.com/bbva/qed/storage"
	"github.com/bbva/qed/util"
)
var (
	BalloonVersionKey = []byte("version")
)
type Balloon struct {
	version uint64
	hasherF func() hashing.Hasher
	store   storage.Store
	historyTree *history.HistoryTree
	hyperTree   *hyper.HyperTree
	sync.RWMutex
	log log.Logger
}
func NewBalloon(store storage.Store, hasherF func() hashing.Hasher) (*Balloon, error) {
	return NewBalloonWithLogger(store, hasherF, log.L())
}
func NewBalloonWithLogger(store storage.Store, hasherF func() hashing.Hasher, logger log.Logger) (*Balloon, error) {
	historyTree := history.NewHistoryTreeWithLogger(hasherF, store, 300, logger.Named("history"))
	batchCache := hyper.NewBatchCache(hyper.DefaultBatchLevels)
	hyperTree := hyper.NewHyperTreeWithLogger(hasherF, store, batchCache, logger.Named("hyper"))
	balloon := &Balloon{
		version:     0,
		hasherF:     hasherF,
		store:       store,
		historyTree: historyTree,
		hyperTree:   hyperTree,
		log:         logger,
	}
	err := balloon.RefreshVersion()
	if err != nil {
		return nil, err
	}
	return balloon, nil
}
type Snapshot struct {
	EventDigest   hashing.Digest
	HistoryDigest hashing.Digest
	HyperDigest   hashing.Digest
	Version       uint64
}
type Verifiable interface {
	Verify(key []byte, expectedDigest hashing.Digest) bool
}
type MembershipProof struct {
	Exists         bool
	HyperProof     *hyper.QueryProof
	HistoryProof   *history.MembershipProof
	CurrentVersion uint64
	QueryVersion   uint64
	ActualVersion  uint64
	KeyDigest      hashing.Digest
	Hasher         hashing.Hasher
}
func NewMembershipProof(exists bool, hyperProof *hyper.QueryProof, historyProof *history.MembershipProof, currentVersion, queryVersion, actualVersion uint64, keyDigest hashing.Digest, Hasher hashing.Hasher) *MembershipProof {
	return &MembershipProof{
		exists,
		hyperProof,
		historyProof,
		currentVersion,
		queryVersion,
		actualVersion,
		keyDigest,
		Hasher,
	}
}
func (p MembershipProof) DigestVerify(digest hashing.Digest, snapshot *Snapshot) bool {
	if p.HyperProof == nil || p.HistoryProof == nil {
		return false
	}
	hyperCorrect := p.HyperProof.Verify(digest, snapshot.HyperDigest)
	if p.Exists {
		if p.ActualVersion <= p.QueryVersion {
			historyCorrect := p.HistoryProof.Verify(digest, snapshot.HistoryDigest)
			return hyperCorrect && historyCorrect
		}
	}
	return hyperCorrect
}
func (p MembershipProof) Verify(event []byte, snapshot *Snapshot) bool {
	return p.DigestVerify(p.Hasher.Do(event), snapshot)
}
type IncrementalProof struct {
	Start, End uint64
	AuditPath  history.AuditPath
	Hasher     hashing.Hasher
}
func NewIncrementalProof(start, end uint64, auditPath history.AuditPath, hasher hashing.Hasher) *IncrementalProof {
	return &IncrementalProof{
		start,
		end,
		auditPath,
		hasher,
	}
}
func (p IncrementalProof) Verify(snapshotStart, snapshotEnd *Snapshot) bool {
	ip := history.NewIncrementalProof(p.Start, p.End, p.AuditPath, p.Hasher)
	return ip.Verify(snapshotStart.HistoryDigest, snapshotEnd.HistoryDigest)
}