opentimestamps

package module
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 2, 2023 License: Unlicense Imports: 14 Imported by: 1

README

opentimestamps

Interact with calendar servers, create and verify OTS attestations.

How to use

Full documentation at https://pkg.go.dev/github.com/nbd-wtf/opentimestamps. See some commented pseudocode below (you probably should not try to run it as it is).

package main

import "github.com/nbd-wtf/opentimestamps"

func main () {
    // create a timestamp at a specific calendar server
    hash := sha256.Sum256([]byte{1,2,3,4,5,6})
    seq, _ := opentimestamps.Stamp(context.Background(), "https://alice.btc.calendar.opentimestamps.org/", hash)

    // you can just call .Upgrade() to get the upgraded sequence (or an error if not yet available)
    upgradedSeq, err := seq.Upgrade(context.Background(), hash[:])
    if err != nil {
        fmt.Println("wait more")
    }

    // a File is a struct that represents the content of an .ots file, which contains the initial digest and any number of sequences
    file := File{
        Digest: hash,
        Sequences: []Sequence{seq},
    }

    // it can be written to disk
    os.WriteFile("file.ots", file.SerializeToFile(), 0644)

    // or printed in human-readable format
    fmt.Println(file.Human())

    // sequences are always composed of a bunch of operation instructions -- these can be, for example, "append", "prepend", "sha256"
    fmt.Println(seq[0].Operation.Name) // "append"
    fmt.Println(seq[1].Operation.Name) // "sha256"
    fmt.Println(seq[2].Operation.Name) // "prepend"

    // "prepend" and "append" are "binary", i.e. they take an argument
    fmt.Println(hex.EncodeToString(seq[2].Argument)) // "c40fe258f9b828a0b5a7"

    // all these instructions can be executed in order, starting from the initial hash
    result := seq.Compute(hash) // this is the value we send to the calendar server in order to get the upgraded sequence on .Upgrade()
    finalResult := upgradedSeq.Compute(hash) // this should be the merkle root of a bitcoin block if this sequence is upgraded

    // each sequence always ends in an "attestation"
    // it can be either a pending attestation, i.e. a reference to a calendar server from which we will upgrade this sequence later
    fmt.Println(seq[len(seq)-1].Attestation.CalendarServerURL) // "https://alice.btc.calendar.opentimestamps.org/"
    // or it can be a reference to a bitcoin block, the merkle root of which we will check against the result of Compute() for verifying
    fmt.Println(upgradedSeq[len(upgradedSeq)-1].Attestation.BitcoinBlockHeight) // 810041

    // speaking of verifying, this is how we do it:
    // first we need some source of bitcoin blocks,
    var bitcoin opentimestamps.Bitcoin
    if useLocallyRunningBitcoindNode {
        // it can be either a locally running bitcoind node
        bitcoin, _ = opentimestamps.NewBitcoindInterface(rpcclient.ConnConfig{
            User:         "nakamoto",
            Pass:         "mumbojumbo",
            HTTPPostMode: true,
        })
    } else {
        // or an esplora HTTP endpoint
        bitcoin = opentimestamps.NewEsploraClient("https://blockstream.info/api")
    }

    // then we pass that to a sequence
    if err := upgradedSeq.Verify(bitcoin, hash); err == nil {
        fmt.Println("it works!")
    }
}

You can also take a look at ots, a simple CLI to OpenTimestamps which is basically a wrapper over this library.

License

Public Domain

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CompareInstructions

func CompareInstructions(a, b Instruction) int

CompareInstructions returns negative if a<b, 0 if a=b and positive if a>b. It considers an operation smaller than an attestation, a pending attestation smaller than a Bitcoin attestation. It orders operations by their tag byte and then by their argument.

Types

type Attestation

type Attestation struct {
	BitcoinBlockHeight uint64
	CalendarServerURL  string
}

func (Attestation) Human

func (att Attestation) Human() string

func (Attestation) Name

func (att Attestation) Name() string

type Bitcoin

type Bitcoin interface {
	GetBlockHash(height int64) (*chainhash.Hash, error)
	GetBlockHeader(hash *chainhash.Hash) (*wire.BlockHeader, error)
}

func NewBitcoindInterface

func NewBitcoindInterface(config rpcclient.ConnConfig) (Bitcoin, error)

func NewEsploraClient

func NewEsploraClient(url string) Bitcoin

type Buffer

type Buffer struct {
	// contains filtered or unexported fields
}

type File

type File struct {
	Digest    []byte
	Sequences []Sequence
}

A File represents the parsed content of an .ots file: it has an initial digest and a series of sequences of instructions. Each sequence must be evaluated separately, applying the operations on top of each other, starting with the .Digest until they end on an attestation.

func ReadFromFile

func ReadFromFile(data []byte) (*File, error)

func (File) GetBitcoinAttestedSequences

func (ts File) GetBitcoinAttestedSequences() []Sequence

func (File) GetPendingSequences

func (ts File) GetPendingSequences() []Sequence

func (File) Human

func (ts File) Human() string

func (File) SerializeInstructionSequences

func (ts File) SerializeInstructionSequences() []byte

func (File) SerializeToFile

func (ts File) SerializeToFile() []byte

type Instruction

type Instruction struct {
	*Operation
	Argument []byte
	*Attestation
}

a Instruction can be an operation like "append" or "prepend" (this will be the case when .Operation != nil) or an attestation (when .Attestation != nil). It will have a non-nil .Argument whenever the operation requires an argument.

type Operation

type Operation struct {
	Name   string
	Tag    byte
	Binary bool // it's an operation that takes one argument, otherwise takes none
	Apply  func(curr []byte, arg []byte) []byte
}

type Sequence

type Sequence []Instruction

func Stamp

func Stamp(ctx context.Context, calendarUrl string, digest [32]byte) (Sequence, error)

func (Sequence) Compute

func (seq Sequence) Compute(initial []byte) []byte

func (Sequence) GetAttestation added in v0.2.2

func (seq Sequence) GetAttestation() Attestation

func (Sequence) Upgrade

func (seq Sequence) Upgrade(ctx context.Context, initial []byte) (Sequence, error)

func (Sequence) Verify

func (seq Sequence) Verify(bitcoin Bitcoin, initial []byte) error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL