pod

package
v0.1.3 Latest Latest
Warning

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

Go to latest
Published: Jul 2, 2025 License: MIT Imports: 16 Imported by: 0

README

pod

Package pod provides functionality to create and verify a cryptographically signed POD (Provable Object Datatype). PODs signed in Go include:

  • Arbitrary key-value pairs (PodEntries)
  • A cryptographic signature (Signature)
  • The public key of the signer (SignerPublicKey)

Table of Contents


Installation

To install this package, run:

go get github.com/0xPARC/parcnet/go/pod

Then import it in your Go code:

import "github.com/0xPARC/parcnet/go/pod"

Types

A Pod struct consists of:

  • Entries: A map of string keys to PodValue items.
  • Signature: The EdDSA-Poseidon signature over the content ID, in unpadded base64.
  • SignerPublicKey: The EdDSA public key of the signer, in unpadded base64.
type Pod struct {
  Entries         PodEntries `json:"entries"`
  Signature       string     `json:"signature"`
  SignerPublicKey string     `json:"signerPublicKey"`
}

PodValue is a union type that can hold any of the POD value types


type PodEntries map[string]PodValue

type PodValue struct {
	ValueType PodValueType // string, bytes, cryptographic, int, boolean, or date
	StringVal string
	BytesVal  []byte
	BigVal    *big.Int
	BoolVal   bool
	TimeVal   time.Time
}

API

Creating a POD

Use the function CreatePod() to sign a set of key-value pairs (PodEntries) with a Baby Jubjub private key, returning a new Pod. Internally, the data is hashed via Poseidon, then signed using the provided private key.

func CreatePod(privateKeyHex string, entries PodEntries) (*Pod, error)
Verifying a POD

Use the function Verify() to verify a POD. Internally, the data is hashed into a content ID via a Poseidon-hash lean incremental merkle tree, then compared to the signature.

func Verify(pod Pod) (bool, error)

Example Usage

package main

import (
	"encoding/json"
    "fmt"
    "log"

    "github.com/0xPARC/parcnet/go/pod"
)

func main() {
    // 1) Initialize your entries
    entries := pod.PodEntries{
        "message": {ValueType: pod.PodStringValue, StringVal: "Welcome to PARCNET!"},
    }

    // Replace with your own EdDSA private key in hex (32 bytes)
    privateKey := "0000000000000000000000000000000000000000000000000000000000000000"

    // 2) Create and sign the POD
    newPod, err := pod.CreatePod(privateKey, entries)
    if err != nil {
        log.Fatalf("Error creating POD: %v", err)
    }

    // 3) Verify the POD
    isValid, err := newPod.Verify()
    if err != nil {
        log.Fatalf("Verification error: %v", err)
    }
    fmt.Printf("Is the POD valid? %v\n", isValid)

    // 4) Serialize the POD to JSON
    jsonPod, err := json.Marshal(newPod)
    if err != nil {
        log.Fatalf("JSON marshalling error: %v", err)
    }

    // 5) Deserialize a POD from JSON
    var deserializedPOD Pod
    err = json.Unmarshal(jsonPod, &deserializedPod)
    if err != nil {
        log.Fatalf("JSON unmarshalling error: %v", err)
    }
}

For a more comprehensive illustration, see the cmd/server/main.go file, which shows how to:

  1. Create a new POD with specific entries.
  2. Expose endpoints (in an HTTP server) to create and verify PODs.
  3. Combine with external services (e.g., Redis).

More Resources

You can find more documentation in the code, or on go.dev

ART_DBG

Documentation

Index

Constants

This section is empty.

Variables

View Source
var PodNameRegex = regexp.MustCompile(`^[A-Za-z_]\w*$`)

Regular expression defining the legal format for the name of a POD entry.

View Source
var PrivateKeyRegex = regexp.MustCompile(`^(?:([A-Za-z0-9+/]{43}=?)|([0-9A-Fa-f]{64}))$`)

Private keys are 32 bytes (any arbitrary bytes), represented as Base64 or hexadecimal

This regex matches any supported format, with match groups usable to determine the format, in the order above.

View Source
var PublicKeyRegex = regexp.MustCompile(`^(?:([A-Za-z0-9+/]{43}=?)|([0-9A-Fa-f]{64}))$`)

Public keys are 32 bytes (a packed elliptic curve point), represented as Base64 or hexadecimal. Base64 padding is optional.

This regex matches any supported format, with match groups usable to determine the format, in the order above.

View Source
var SignatureRegex = regexp.MustCompile(`^(?:([A-Za-z0-9+/]{86}(?:==)?)|([0-9A-Fa-f]{128}))$`)

Signatures are 64 bytes (one packed elliptic curve point, one scalar), represented as Base64 or hexadecimal. Base64 padding is optional.

This regex matches any supported format, with match groups usable to determine the format, in the order above.

Functions

func CheckPodName

func CheckPodName(name string) error

Checks that the given name is legal for a POD entry. Returns nil if so.

func DecodeBase64Bytes

func DecodeBase64Bytes(encodedBytes string) ([]byte, error)

Decode a variable number of bytes in Base64 encoding, with or without padding.

func DecodeBytes

func DecodeBytes(encodedBytes string, expectedBytes int) ([]byte, error)

Decode a fixed number of bytes which may be encoded as hex, or Base64 with or without padding. This will fail on any other encoding, or an unexpected number of bytes.

func PodCryptographicMax

func PodCryptographicMax() *big.Int

Maximum legal POD cryptographic value is 1 less than the Baby Jubjub prime, i.e. 21888242871839275222246405745257275088548364400416034343698204186575808495616

func PodCryptographicMin

func PodCryptographicMin() *big.Int

Minimum legal POD cryptographic value is 0

func PodDateMax

func PodDateMax() time.Time

Maximum legal POD date value is 8,640,000,000,000,000ms since epoch

func PodDateMin

func PodDateMin() time.Time

Minimum legal POD int value is -8,640,000,000,000,000ms since epoch

func PodIntMax

func PodIntMax() *big.Int

Maximum legal POD int value is 2^63-1

func PodIntMin

func PodIntMin() *big.Int

Minimum legal POD int value is -2^63

Types

type Pod

type Pod struct {
	Entries         PodEntries `json:"entries"`
	Signature       string     `json:"signature"`
	SignerPublicKey string     `json:"signerPublicKey"`
}

Provable Object Datatype containing a cryptographically verified key/value store

func CreatePod

func CreatePod(privateKeyHex string, entries PodEntries) (*Pod, error)

Create and sign a new POD. This involves hashing all the given entries to generate a Content ID, then signing that content ID with the given private key.

func (*Pod) CheckFormat

func (p *Pod) CheckFormat() error

Checks that the data in this POD is well-formed and in valid ranges, including all entries. This does check the cryptographic signature. For that you should call Verify() instead, in which case this function would be redundant.

func (*Pod) UnmarshalJSON

func (p *Pod) UnmarshalJSON(data []byte) error

Parse a POD from JSON in POD's terse human-readable format

func (*Pod) Verify

func (p *Pod) Verify() (bool, error)

Cryptographically verify the contents of this POD. This involves hashing all of its entries to generate a Content ID, then verifying the signature on the Content ID.

type PodEntries

type PodEntries map[string]PodValue

The keys and values stored in a POD

func (*PodEntries) Check

func (p *PodEntries) Check() error

Checks that all the names and values in entries are well-formed and in valid ranges for their types. Returns nil if all are legal.

func (*PodEntries) UnmarshalJSON

func (p *PodEntries) UnmarshalJSON(data []byte) error

Parse entries from JSON in POD's terse human-readable format

type PodValue

type PodValue struct {
	ValueType PodValueType
	StringVal string
	BytesVal  []byte
	BigVal    *big.Int
	BoolVal   bool
	TimeVal   time.Time
}

Tagged union struct representing the value of a POD entry. Which of the value fields is set depends on the ValueType.

func NewPodBooleanValue

func NewPodBooleanValue(val bool) PodValue

Constructor for int POD values. Error if input is nil or out of range.

func NewPodBytesValue

func NewPodBytesValue(val []byte) (PodValue, error)

Constructor for bytes POD values. Error if input is nil.

func NewPodCryptographicValue

func NewPodCryptographicValue(val *big.Int) (PodValue, error)

Constructor for cryptographic POD values. Error if input is nil or out of range.

func NewPodDateValue

func NewPodDateValue(val time.Time) (PodValue, error)

Constructor for int POD values. Error if input is nil or out of range.

func NewPodEdDSAPubkeyValue

func NewPodEdDSAPubkeyValue(val string) (PodValue, error)

Constructor for int POD values. Error if input is not 32 bytes encoded in Base64 (with or without padding).

func NewPodIntValue

func NewPodIntValue(val *big.Int) (PodValue, error)

Constructor for int POD values. Error if input is nil or out of range.

func NewPodNullValue

func NewPodNullValue() PodValue

Constructor for null POD values

func NewPodStringValue

func NewPodStringValue(val string) PodValue

Constructor for string POD values

func (*PodValue) Check

func (p *PodValue) Check() error

Checks that the value is well-formed and in the legal bounds for its type. Returns nil if it is, otherwise an error explaining what's wrong.

func (PodValue) Hash

func (p PodValue) Hash() (*big.Int, error)

Produces the cryptographic hash which represents a POD value in ZK circuits The resulting BigInt value has the same range as the Cryptographic value type

func (PodValue) MarshalJSON

func (p PodValue) MarshalJSON() ([]byte, error)

Marshal this value to JSON in a terse human-readable format.

func (*PodValue) UnmarshalJSON

func (p *PodValue) UnmarshalJSON(data []byte) error

Parse a value from JSON in POD's terse human-readable format

type PodValueType

type PodValueType string

Type tag for the PodValue union. For legal values see the type constants Pod*Value in this package

const (
	// Null values don't use any of the value fields
	PodNullValue PodValueType = "null"

	// String values use the StringVal field
	PodStringValue PodValueType = "string"

	// Bytes values use the BytesVal field
	PodBytesValue PodValueType = "bytes"

	// Cryptographic values use the BigVal field to store an unsigned integer
	// between 0 and p-1 (see PodCryptographicMax())
	PodCryptographicValue PodValueType = "cryptographic"

	// Int values use the BigVal field to store an integer with the same range
	// as Go's int64
	PodIntValue PodValueType = "int"

	// Boolean values use the BoolVal field
	PodBooleanValue PodValueType = "boolean"

	// EdDSA public key values use the StringVal field to store the encoded
	// bytes of a cryptographic key
	PodEdDSAPubkeyValue PodValueType = "eddsa_pubkey"

	// Date values use the TimeVal field to store a millisecond-accuracy
	// time between PodDateMin() and PodDateMax()
	PodDateValue PodValueType = "date"
)

type Signer

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

A reusable POD signer which can create multiple PODs with the same key.

func NewSigner

func NewSigner(privateKeyHex string) (*Signer, error)

Create a new Signer with the given private key.

func (*Signer) Sign

func (s *Signer) Sign(entries PodEntries) (*Pod, error)

Create and sign a new POD. This involves hashing all the given entries to generate a Content ID, then signing that content ID with the given private key.

Jump to

Keyboard shortcuts

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