v1.0.1 probe
This commit is contained in:
@@ -0,0 +1,18 @@
|
|||||||
|
BINARY_NAME=obsero-probe
|
||||||
|
|
||||||
|
all: build
|
||||||
|
|
||||||
|
build:
|
||||||
|
go build -o $(BINARY_NAME) ./cmd/obsero-probe
|
||||||
|
|
||||||
|
build-linux:
|
||||||
|
GOOS=linux GOARCH=amd64 go build -o $(BINARY_NAME)-linux ./cmd/obsero-probe
|
||||||
|
|
||||||
|
build-mac:
|
||||||
|
GOOS=darwin GOARCH=amd64 go build -o $(BINARY_NAME)-mac ./cmd/obsero-probe
|
||||||
|
|
||||||
|
build-arm:
|
||||||
|
GOOS=linux GOARCH=arm64 go build -o $(BINARY_NAME)-arm64 ./cmd/obsero-probe
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(BINARY_NAME)*
|
||||||
@@ -1,20 +1,41 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.cryptolab.re/foudre/whitepaper_obsero/pkg/geo"
|
"git.cryptolab.re/foudre/whitepaper_obsero/pkg/geo"
|
||||||
"git.cryptolab.re/foudre/whitepaper_obsero/pkg/probe"
|
"git.cryptolab.re/foudre/whitepaper_obsero/pkg/probe"
|
||||||
"git.cryptolab.re/foudre/whitepaper_obsero/pkg/proof"
|
"git.cryptolab.re/foudre/whitepaper_obsero/pkg/proof"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
target := "https://example.com"
|
target := flag.String("target", "https://example.com", "Target URL to probe")
|
||||||
|
output := flag.String("output", "proof_http_signed.json", "Output file name for proof JSON")
|
||||||
|
useIPFS := flag.Bool("ipfs", false, "Upload to IPFS after proof generation")
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
location := geo.GetGeoLocation()
|
location := geo.GetGeoLocation()
|
||||||
result := probe.HttpPing(target)
|
result := probe.HttpPing(*target)
|
||||||
observation := proof.BuildProof(result, location)
|
observation := proof.BuildProof(result, location)
|
||||||
|
|
||||||
proof.SaveProof(observation, "proof_http_result.json")
|
err := proof.SignProof(&observation)
|
||||||
fmt.Println("✅ Proof generated and saved.")
|
if err != nil {
|
||||||
|
fmt.Println("❌ Failed to sign proof:", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
proof.SaveProof(observation, *output)
|
||||||
|
fmt.Println("✅ Signed proof saved to", *output)
|
||||||
|
|
||||||
|
if *useIPFS {
|
||||||
|
cid, err := proof.UploadToIPFS(*output)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("❌ Failed to upload to IPFS:", err)
|
||||||
|
} else {
|
||||||
|
fmt.Println("📡 Uploaded to IPFS with CID:", cid)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,34 @@
|
|||||||
package proof
|
package proof
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"git.cryptolab.re/foudre/whitepaper_obsero/pkg/geo"
|
"git.cryptolab.re/foudre/whitepaper_obsero/pkg/geo"
|
||||||
"git.cryptolab.re/foudre/whitepaper_obsero/pkg/probe"
|
"git.cryptolab.re/foudre/whitepaper_obsero/pkg/probe"
|
||||||
|
import (
|
||||||
|
...
|
||||||
|
shell "github.com/ipfs/go-ipfs-api"
|
||||||
|
...
|
||||||
)
|
)
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
func UploadToIPFS(filepath string) (string, error) {
|
||||||
|
sh := shell.NewShell("localhost:5001")
|
||||||
|
cid, err := sh.AddNoPin(shell.NewShellFile(filepath))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return cid, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
type Observation struct {
|
type Observation struct {
|
||||||
Timestamp string `json:"timestamp"`
|
Timestamp string `json:"timestamp"`
|
||||||
Target string `json:"target"`
|
Target string `json:"target"`
|
||||||
@@ -17,6 +38,7 @@ type Observation struct {
|
|||||||
Error string `json:"error_message"`
|
Error string `json:"error_message"`
|
||||||
Observer ObserverInfo `json:"observer"`
|
Observer ObserverInfo `json:"observer"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
|
Proof ProofMeta `json:"proof"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ObserverInfo struct {
|
type ObserverInfo struct {
|
||||||
@@ -27,6 +49,11 @@ type ObserverInfo struct {
|
|||||||
ProbeVersion string `json:"probe_version"`
|
ProbeVersion string `json:"probe_version"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ProofMeta struct {
|
||||||
|
Hash string `json:"hash"`
|
||||||
|
Signature string `json:"signature"`
|
||||||
|
}
|
||||||
|
|
||||||
func BuildProof(result probe.PingResult, loc geo.GeoInfo) Observation {
|
func BuildProof(result probe.PingResult, loc geo.GeoInfo) Observation {
|
||||||
return Observation{
|
return Observation{
|
||||||
Timestamp: result.Timestamp,
|
Timestamp: result.Timestamp,
|
||||||
@@ -50,3 +77,25 @@ func SaveProof(obs Observation, filename string) {
|
|||||||
file, _ := json.MarshalIndent(obs, "", " ")
|
file, _ := json.MarshalIndent(obs, "", " ")
|
||||||
_ = os.WriteFile(filename, file, 0644)
|
_ = os.WriteFile(filename, file, 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SignProof(obs *Observation) error {
|
||||||
|
// Replace with your own private key (for demo only)
|
||||||
|
privKeyHex := "4f3edf983ac636a65a842ce7c78d9aa706d3b113bce03738e0f7b6267d5bdc25"
|
||||||
|
privKey, err := crypto.HexToECDSA(privKeyHex)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash relevant fields
|
||||||
|
data := fmt.Sprintf("%s|%s|%s|%d|%d", obs.Timestamp, obs.Target, obs.Status, obs.HTTPStatus, obs.LatencyMs)
|
||||||
|
hash := sha256.Sum256([]byte(data))
|
||||||
|
obs.Proof.Hash = hex.EncodeToString(hash[:])
|
||||||
|
|
||||||
|
sigBytes, err := crypto.Sign(hash[:], privKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
obs.Proof.Signature = hex.EncodeToString(sigBytes)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
+60
-38
@@ -1,48 +1,57 @@
|
|||||||
# 🛰️ Obsero Probe
|
# 🛰️ Obsero Probe (Full)
|
||||||
|
|
||||||
Lightweight monitoring agent for generating Proof-of-Observability JSON files.
|
Obsero Probe is a lightweight Go-based agent that generates cryptographically signed uptime proofs and can optionally upload them to IPFS.
|
||||||
|
|
||||||
This probe performs HTTP health checks, automatically geolocates itself, and exports signed observation files compliant with the Obsero specification.
|
---
|
||||||
|
|
||||||
|
## 🚀 Features
|
||||||
|
|
||||||
|
- HTTP ping with latency measurement
|
||||||
|
- Automatic geolocation of probe (city, region, country)
|
||||||
|
- SHA256 hashing of observation data
|
||||||
|
- EVM-compatible signature using Ethereum private key
|
||||||
|
- IPFS upload support (`--ipfs`)
|
||||||
|
- CLI support for target, output, and IPFS toggle
|
||||||
|
- Cross-platform Makefile for easy builds
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ⚙️ Requirements
|
## ⚙️ Requirements
|
||||||
|
|
||||||
- Go 1.21+
|
- Go 1.21+
|
||||||
- Internet access (for geo lookup and ping)
|
- Local IPFS node (optional, for `--ipfs`)
|
||||||
|
- Ethereum private key (test key included by default)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🚀 Quick Start
|
## 📦 Quick Start
|
||||||
|
|
||||||
### 1. Clone & Enter
|
### 1. Install dependencies
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd probe
|
cd probe
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Install dependencies
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go mod tidy
|
go mod tidy
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Run the probe
|
### 2. Run a probe
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go run ./cmd/obsero-probe
|
go run ./cmd/obsero-probe --target https://example.com --output proof_http_signed.json --ipfs
|
||||||
```
|
```
|
||||||
|
|
||||||
This will:
|
|
||||||
- Ping `https://example.com`
|
|
||||||
- Auto-detect country, city and region
|
|
||||||
- Output a file named `proof_http_result.json`
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📄 Output Format
|
## 🛠️ CLI Options
|
||||||
|
|
||||||
The output file is a valid Obsero proof:
|
| Flag | Description |
|
||||||
|
|------------|------------------------------------|
|
||||||
|
| `--target` | URL to ping |
|
||||||
|
| `--output` | Output file name |
|
||||||
|
| `--ipfs` | Upload the proof to IPFS |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📄 Proof Format (simplified)
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -59,34 +68,47 @@ The output file is a valid Obsero proof:
|
|||||||
"city": "Paris",
|
"city": "Paris",
|
||||||
"probe_version": "0.1"
|
"probe_version": "0.1"
|
||||||
},
|
},
|
||||||
"version": "0.1"
|
"version": "0.1",
|
||||||
|
"proof": {
|
||||||
|
"hash": "ab13...cdef",
|
||||||
|
"signature": "0x..."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📦 Next steps
|
## 📁 Project Structure
|
||||||
|
|
||||||
- Add CLI support (`--target`, `--output`)
|
|
||||||
- Add cryptographic signature of the proof
|
|
||||||
- Upload to IPFS
|
|
||||||
- Submit hash + CID on Base chain
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📁 Structure
|
|
||||||
|
|
||||||
```
|
```
|
||||||
probe/
|
probe/
|
||||||
├── cmd/
|
├── cmd/
|
||||||
│ └── obsero-probe/
|
│ └── obsero-probe/main.go # CLI entrypoint
|
||||||
│ └── main.go # CLI entrypoint
|
|
||||||
├── pkg/
|
├── pkg/
|
||||||
│ ├── geo/ # IP geolocation
|
│ ├── geo/geo.go # Geolocation
|
||||||
│ ├── probe/ # HTTP ping logic
|
│ ├── probe/ping.go # HTTP ping
|
||||||
│ └── proof/ # Proof struct + output
|
│ └── proof/format.go # Build, sign and upload proof
|
||||||
├── go.mod
|
├── Makefile # Multi-platform build support
|
||||||
├── go.sum
|
├── go.mod / go.sum
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧱 Next Steps
|
||||||
|
|
||||||
|
- ✅ JSON signed and stored locally
|
||||||
|
- ✅ Upload to IPFS (`--ipfs`)
|
||||||
|
- 🔗 Submit `submitProof(hash, cid, timestamp)` to a smart contract on Base chain (coming soon)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ Makefile Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make build # Build for local platform
|
||||||
|
make build-linux # Build for Linux amd64
|
||||||
|
make build-mac # Build for macOS
|
||||||
|
make build-arm # Build for ARM64 (Raspberry Pi, etc.)
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
Reference in New Issue
Block a user