func openJournal(filename string, data *journalPersist) (*journal, error) {
	f, err := os.OpenFile(filename, os.O_RDWR, 0)
	if err != nil {
		return nil, err
	}
	dec := json.NewDecoder(f)
	var meta persist.Metadata
	if err = dec.Decode(&meta); err != nil {
		return nil, err
	} else if meta.Header != journalMeta.Header {
		return nil, fmt.Errorf("expected header %q, got %q", journalMeta.Header, meta.Header)
	} else if meta.Version != journalMeta.Version {
		return nil, fmt.Errorf("journal version (%s) is incompatible with the current version (%s)", meta.Version, journalMeta.Version)
	}
	if err = dec.Decode(data); err != nil {
		return nil, err
	}
	if data.CachedRevisions == nil {
		data.CachedRevisions = map[string]proto.V130CachedRevision{}
	}
	if data.Contracts == nil {
		data.Contracts = map[string]proto.V130Contract{}
	}
	if data.RenewedIDs == nil {
		data.RenewedIDs = map[string]string{}
	}
	for {
		var set updateSet
		if err = dec.Decode(&set); err == io.EOF || err == io.ErrUnexpectedEOF {
			break
		} else if err != nil {
			continue
		}
		for _, u := range set {
			u.apply(data)
		}
	}
	return &journal{
		f:        f,
		filename: filename,
	}, nil
}
openJournal opens the supplied journal and decodes the reconstructed
journalPersist into data.
package contractor
import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"os"
	"github.com/NebulousLabs/Sia/build"
	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/modules"
	"github.com/NebulousLabs/Sia/modules/renter/proto"
	"github.com/NebulousLabs/Sia/persist"
	"github.com/NebulousLabs/Sia/types"
)
var journalMeta = persist.Metadata{
	Header:  "Contractor Journal",
	Version: "1.1.1",
}
type journalPersist struct {
	Allowance       modules.Allowance                   `json:"allowance"`
	BlockHeight     types.BlockHeight                   `json:"blockheight"`
	CachedRevisions map[string]proto.V130CachedRevision `json:"cachedrevisions"`
	Contracts       map[string]proto.V130Contract       `json:"contracts"`
	CurrentPeriod   types.BlockHeight                   `json:"currentperiod"`
	LastChange      modules.ConsensusChangeID           `json:"lastchange"`
	OldContracts    []proto.V130Contract                `json:"oldcontracts"`
	RenewedIDs      map[string]string                   `json:"renewedids"`
}
type journal struct {
	f        *os.File
	filename string
}
func (j *journal) update(us updateSet) error {
	if err := json.NewEncoder(j.f).Encode(us); err != nil {
		return err
	}
	return j.f.Sync()
}
func (j *journal) Close() error {
	return j.f.Close()
}