require "json"
require "tmpdir"
require "fileutils"
require "proofmode"
require "proofmode_callbacks"
class MyCallbacks < Proofmode::ProofModeCallbacks
def initialize(output_dir)
@output_dir = output_dir
end
def get_location
Proofmode::LocationData.new(
latitude: 37.7749,
longitude: -122.4194,
altitude: 10.0,
accuracy: 5.0,
provider: "gps"
)
end
def get_device_info
Proofmode::DeviceData.new(
manufacturer: "Example Corp",
model: "Ruby App",
os_version: "Ruby #{RUBY_VERSION}",
device_id: nil
)
end
def get_network_info
Proofmode::NetworkData.new(
network_type: "wifi",
wifi_ssid: "ExampleNetwork",
cell_info: nil
)
end
def save_data(hash, filename, data)
dir = File.join(@output_dir, hash)
FileUtils.mkdir_p(dir)
filepath = File.join(dir, filename)
File.open(filepath, "wb") { |f| f.write(data) }
true
rescue => e
puts "Failed to save data: #{e.message}"
false
end
def save_text(hash, filename, text)
dir = File.join(@output_dir, hash)
FileUtils.mkdir_p(dir)
filepath = File.join(dir, filename)
File.write(filepath, text)
true
rescue => e
puts "Failed to save text: #{e.message}"
false
end
def sign_data(data)
nil
end
def report_progress(message)
puts "[progress] #{message}"
end
end
def main
puts "ProofMode version: #{Proofmode.get_version}"
test_data = "Hello, ProofMode from Ruby!"
file_hash = Proofmode.get_file_hash(test_data)
puts "SHA-256 hash: #{file_hash}"
puts "\nGenerating proof..."
Dir.mktmpdir do |output_dir|
callbacks = MyCallbacks.new(output_dir)
config = Proofmode::ProofModeConfig.new(
auto_notarize: false,
track_location: true,
track_device_id: false,
track_network: true,
add_credentials: false
)
metadata = { "description" => "Ruby example proof" }
begin
result_hash = Proofmode.generate_proof(test_data, metadata, config, callbacks)
puts "Proof generated, hash: #{result_hash}"
hash_dir = File.join(output_dir, result_hash)
if Dir.exist?(hash_dir)
puts "Generated files:"
Dir.entries(hash_dir).reject { |f| f.start_with?(".") }.each do |f|
puts " #{f}"
end
end
rescue Proofmode::ProofModeError => e
puts "Error generating proof: #{e.message}"
end
end
proof_bundle = "./proof-bundle.zip"
if File.exist?(proof_bundle)
puts "\nVerifying proof bundle..."
begin
callbacks = MyCallbacks.new(Dir.tmpdir)
result_json = Proofmode.check_files([proof_bundle], callbacks)
result = JSON.parse(result_json)
puts "Verification result: #{JSON.pretty_generate(result)}"
consistency = result["consistency"] || {}
puts "\nConsistency verified: #{consistency["verified"]}"
(consistency["fileDiscrepancies"] || []).each do |fd|
puts " File: #{fd["fileName"]} (#{fd["flagCount"]} flags)"
(fd["flags"] || []).each do |flag|
puts " [#{flag["severity"]}/#{flag["kind"]}] #{flag["field"]}: #{flag["message"]}"
end
end
summary = consistency["summary"]
if summary
puts " Summary: #{summary["filesWithFlags"]}/#{summary["totalFiles"]} files flagged, #{summary["totalFlags"]} total flags"
end
synchrony = result["synchrony"] || {}
temporal = synchrony["temporal"]
if temporal
puts "\nTemporal analysis:"
puts " Range: #{temporal["earliest"]} to #{temporal["latest"]}"
puts " Elapsed: #{temporal["elapsedSeconds"].round(1)}s across #{temporal["fileCount"]} files"
patterns = temporal["patterns"]
if patterns
puts " Mean interval: #{patterns["meanIntervalSeconds"].round(1)}s (std #{patterns["stdIntervalSeconds"].round(1)}s)"
puts " Bursts: #{patterns["burstCount"]}, Gaps: #{patterns["gapCount"]}"
end
end
spatial = synchrony["spatial"]
if spatial
puts "\nSpatial analysis:"
puts " Max distance: #{"%.2f" % spatial["maxDistanceKm"]} km"
puts " Coverage area: #{"%.2f" % spatial["areaKm2"]} km^2"
puts " Centroid: [#{"%.4f" % spatial["centroid"][0]}, #{"%.4f" % spatial["centroid"][1]}]"
(spatial["pairwiseDistances"] || []).each do |pd|
puts " #{pd["fileA"]} <-> #{pd["fileB"]}: #{"%.2f" % pd["distanceKm"]} km"
end
end
rescue Proofmode::ProofModeError => e
puts "Error verifying: #{e.message}"
end
else
puts "\nSkipping check (no proof-bundle.zip found)"
end
end
main if __FILE__ == $0