A library for working with Pijul repositories in Go
package pijul

import (
	"fmt"

	"filippo.io/edwards25519"
)

// A State represents a set of changes. It is calculated from the hashes of
// the changes, using the Edwards 25519 curve.
type State struct {
	p edwards25519.Point
}

func (s State) String() string {
	return base32Encoding.EncodeToString(append(s.p.Bytes(), 1))
}

func StateFromBase32(b32 string) (State, error) {
	b, err := base32Encoding.DecodeString(b32)
	if err != nil {
		return State{}, err
	}
	if len(b) != 33 {
		return State{}, fmt.Errorf("expected 33 bytes, got %d", len(b))
	}
	if b[32] != 1 {
		return State{}, fmt.Errorf("expected Ed25519 state, got type %d", b[32])
	}

	var p edwards25519.Point
	_, err = p.SetBytes(b[:32])
	if err != nil {
		return State{}, err
	}
	return State{p}, nil
}

func mustStateFromBase32(b32 string) State {
	s, err := StateFromBase32(b32)
	if err != nil {
		panic(err)
	}
	return s
}

// EmptyState is the State that represents the empty set.
var EmptyState = mustStateFromBase32("LBTGMZTGMZTGMZTGMZTGMZTGMZTGMZTGMZTGMZTGMZTGMZTGMZTAC")

func (s State) Add(h Hash) State {
	var wideBytes [64]byte
	copy(wideBytes[:], h[:])
	var scalar edwards25519.Scalar
	scalar.SetUniformBytes(wideBytes[:])

	p := s.p
	p.ScalarMult(&scalar, &p)
	return State{p}
}