refactor
This commit is contained in:
130
cmd/ots/create.go
Normal file
130
cmd/ots/create.go
Normal file
@@ -0,0 +1,130 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.intruders.space/public/opentimestamps"
|
||||
"git.intruders.space/public/opentimestamps/ots"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Default calendar servers
|
||||
var defaultCalendars = []string{
|
||||
"https://alice.btc.calendar.opentimestamps.org",
|
||||
"https://bob.btc.calendar.opentimestamps.org",
|
||||
"https://finney.calendar.eternitywall.com",
|
||||
}
|
||||
|
||||
var (
|
||||
// Create command flags
|
||||
createOutput string
|
||||
createCalendarsStr string
|
||||
createTimeout time.Duration
|
||||
)
|
||||
|
||||
// createCmd represents the create command
|
||||
var createCmd = &cobra.Command{
|
||||
Use: "create [flags] <file>",
|
||||
Short: "Create a timestamp for a file",
|
||||
Long: `Create a timestamp for a file by submitting its digest to OpenTimestamps calendar servers.
|
||||
The resulting timestamp is saved to a .ots file, which can later be verified or upgraded.`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: runCreateCmd,
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Local flags for the create command
|
||||
createCmd.Flags().StringVarP(&createOutput, "output", "o", "", "Output filename (default: input filename with .ots extension)")
|
||||
createCmd.Flags().StringVar(&createCalendarsStr, "calendar", strings.Join(defaultCalendars, ","), "Comma-separated list of calendar server URLs")
|
||||
createCmd.Flags().DurationVar(&createTimeout, "timeout", 30*time.Second, "Timeout for calendar server connections")
|
||||
}
|
||||
|
||||
func runCreateCmd(cmd *cobra.Command, args []string) {
|
||||
inputPath := args[0]
|
||||
|
||||
// Determine output file path
|
||||
outputPath := createOutput
|
||||
if outputPath == "" {
|
||||
outputPath = inputPath + ".ots"
|
||||
}
|
||||
|
||||
// Parse calendar servers
|
||||
calendars := strings.Split(createCalendarsStr, ",")
|
||||
if len(calendars) == 0 {
|
||||
calendars = defaultCalendars
|
||||
}
|
||||
|
||||
// Read the input file
|
||||
fileData, err := os.ReadFile(inputPath)
|
||||
if err != nil {
|
||||
slog.Error("Failed to read input file", "file", inputPath, "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Compute the file digest
|
||||
digest := sha256.Sum256(fileData)
|
||||
slog.Info("Computed file digest", "digest", fmt.Sprintf("%x", digest))
|
||||
|
||||
// Create context with timeout
|
||||
ctx, cancel := context.WithTimeout(context.Background(), createTimeout)
|
||||
defer cancel()
|
||||
|
||||
// Create timestamps using all calendar servers
|
||||
var sequences []ots.Sequence
|
||||
var errors []string
|
||||
|
||||
for _, calendarURL := range calendars {
|
||||
calendarURL = strings.TrimSpace(calendarURL)
|
||||
if calendarURL == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
slog.Info("Submitting to calendar", "url", calendarURL)
|
||||
seq, err := opentimestamps.Stamp(ctx, calendarURL, digest)
|
||||
if err != nil {
|
||||
slog.Warn("Calendar submission failed", "url", calendarURL, "error", err)
|
||||
errors = append(errors, fmt.Sprintf("%s: %v", calendarURL, err))
|
||||
continue
|
||||
}
|
||||
|
||||
sequences = append(sequences, seq)
|
||||
slog.Info("Calendar submission successful", "url", calendarURL)
|
||||
}
|
||||
|
||||
if len(sequences) == 0 {
|
||||
slog.Error("All calendar submissions failed", "errors", errors)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Create the timestamp file
|
||||
file := &ots.File{
|
||||
Digest: digest[:],
|
||||
Sequences: sequences,
|
||||
}
|
||||
|
||||
// Write the OTS file
|
||||
otsData := file.SerializeToFile()
|
||||
err = os.WriteFile(outputPath, otsData, 0644)
|
||||
if err != nil {
|
||||
slog.Error("Failed to write OTS file", "file", outputPath, "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
slog.Info("Timestamp file created successfully",
|
||||
"file", outputPath,
|
||||
"timestamps", len(sequences),
|
||||
"size", len(otsData))
|
||||
|
||||
// Print human-readable representation
|
||||
slog.Debug("Timestamp details", "info", file.Human(false))
|
||||
|
||||
slog.Info("Timestamp creation complete",
|
||||
"status", "pending",
|
||||
"note", "Use 'ots upgrade' to upgrade this timestamp when it's confirmed in the Bitcoin blockchain")
|
||||
}
|
||||
Reference in New Issue
Block a user