Skip to content

create, read, upgrade and verify opentimestamps proofs

License

Notifications You must be signed in to change notification settings

nbd-wtf/opentimestamps

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ba1196a · Oct 27, 2024

History

23 Commits
Sep 18, 2023
Sep 30, 2023
Oct 2, 2023
Sep 20, 2023
Feb 8, 2024
Feb 8, 2024
Feb 8, 2024
Feb 8, 2024
Oct 27, 2024
Feb 8, 2024
Oct 27, 2024
Sep 28, 2023
Sep 30, 2023
Oct 27, 2024

Repository files navigation

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 UpgradeSequence() to get the upgraded sequence (or an error if not yet available)
    upgradedSeq, err := opentimestamps.UpgradeSequence(context.Background(), seq, 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
    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

About

create, read, upgrade and verify opentimestamps proofs

Topics

Resources

License

Stars

Watchers

Forks

Languages