Coo... coo...

This commit is contained in:
Netscape Navigator 2019-09-21 21:30:03 -05:00
commit 5ae1a0a943
14 changed files with 422 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
coverage/
.pigeon/

1
.rspec Normal file
View File

@ -0,0 +1 @@
--require spec_helper

12
Gemfile Normal file
View File

@ -0,0 +1,12 @@
# frozen_string_literal: true
source "https://rubygems.org"
gem "ed25519"
gem "thor"
group :dev do
gem "rspec"
gem "pry"
gem "simplecov"
end

44
Gemfile.lock Normal file
View File

@ -0,0 +1,44 @@
GEM
remote: https://rubygems.org/
specs:
coderay (1.1.2)
diff-lcs (1.3)
docile (1.3.2)
ed25519 (1.2.4)
json (2.2.0)
method_source (0.9.2)
pry (0.12.2)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
rspec (3.8.0)
rspec-core (~> 3.8.0)
rspec-expectations (~> 3.8.0)
rspec-mocks (~> 3.8.0)
rspec-core (3.8.2)
rspec-support (~> 3.8.0)
rspec-expectations (3.8.4)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-mocks (3.8.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-support (3.8.2)
simplecov (0.17.1)
docile (~> 1.1)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.2)
thor (0.20.3)
PLATFORMS
ruby
DEPENDENCIES
ed25519
pry
rspec
simplecov
thor
BUNDLED WITH
2.0.2

35
README.md Normal file
View File

@ -0,0 +1,35 @@
# Pigeon Ruby
A WIP pigeon protocol client.
# How to Use
This is a pre-release skeleton project. There is no gem yet. The gem will be released after we are fully compliant with the spec and have high test coverage stats.
To get started, clone this repo and run `./pigeon-cli` in place of `pigeon`.
Eg: `pigeon identity show` becomes `./pigeon-cli show`.
# Current Status
- [X] pigeon status
- [X] pigeon identity new
- [X] pigeon identity show
- [ ] pigeon blob set
- [ ] pigeon blob get
- [ ] pigeon message new
- [ ] pigeon message current
- [ ] pigeon message append
- [ ] pigeon message save
- [ ] pigeon message find
- [ ] pigeon message find-all
- [ ] pigeon peer add
- [ ] pigeon peer remove
- [ ] pigeon peer block
- [ ] pigeon peer all
- [ ] pigeon bundle create
- [ ] pigeon bundle consume

100
TODO.md Normal file
View File

@ -0,0 +1,100 @@
I need to implement these.
I'm adding them here for quick reference.
```bash
pigeon status
# => BLOBS: 10,234
# => PEERS: 26
# => VERSION: 0.0.1
# => FOO: BAR
pigeon identity new
# => @ajgdylxeifojlxpbmen3exlnsbx8buspsjh37b/ipvi=.ed25519
pigeon identity show
# => @ajgdylxeifojlxpbmen3exlnsbx8buspsjh37b/ipvi=.ed25519
pigeon blob set '"Lol, data"'
# => &2e7a0bc31f3c4fe6114051c3a56c8ed8a030b3b394df7d29d37648e9b8cbf54b.sha256
# Or use echo for big files:
echo "Lol, data"' > pigeon blob set
# => &2e7a0bc31f3c4fe6114051c3a56c8ed8a030b3b394df7d29d37648e9b8cbf54b.sha256
pigeon blob get "&2e7a0bc31f3c4fe6114051c3a56c8ed8a030b3b394df7d29d37648e9b8cbf54b.sha256"
# => "Lol, data"
pigeon message new my_message
# => "Switched to message `my_message`
pigeon message current # Show active log entry.
# => author: @ajgdylxeifojlxpbmen3exlnsbx8buspsjh37b/ipvi=.ed25519
# => depth: 1
# => kind: &82244417f956ac7c599f191593f7e441a4fafa20a4158fd52e154f1dc4c8ed92.sha256
# => prev: %jvKh9yoiEJaePzoWCF1nnqpIlPgTk9FHEtqczQbvzGM=.sha256
# =>
# =>
pigeon message append --name=2e7a0bc3 --value=2e7a0bc3
# => \n
# => This needs to be cleaner.
# => No one likes the way it is right now.
# => We will come back to this monstrosity later.
pigeon message save
# => author: @ajgdylxeifojlxpbmen3exlnsbx8buspsjh37b/ipvi=.ed25519
# => depth: 1
# => kind: &82244417f956ac7c599f191593f7e441a4fafa20a4158fd52e154f1dc4c8ed92.sha256
# => prev: %jvKh9yoiEJaePzoWCF1nnqpIlPgTk9FHEtqczQbvzGM=.sha256
# =>
# => &ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb.sha256:&2e7a0bc31f3c4fe6114051c3a56c8ed8a030b3b394df7d29d37648e9b8cbf54b.sha256
# =>
pigeon message find %g0Fs9yoiEJaePzoWCF1nnqpIlPgTk9FHEtqczQbvzGM=.sha256
# => author: @ajgdylxeifojlxpbmen3exlnsbx8buspsjh37b/ipvi=.ed25519
# => depth: 1
# => kind: &82244417f956ac7c599f191593f7e441a4fafa20a4158fd52e154f1dc4c8ed92.sha256
# => prev: %jvKh9yoiEJaePzoWCF1nnqpIlPgTk9FHEtqczQbvzGM=.sha256
# =>
# => &ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb.sha256:&2e7a0bc31f3c4fe6114051c3a56c8ed8a030b3b394df7d29d37648e9b8cbf54b.sha256
# =>
pigeon message find-all --author=@ajgdylxeifojlxpbmen3exlnsbx8buspsjh37b/ipvi=.ed25519 --since=1
# => author: @ajgdylxeifojlxpbmen3exlnsbx8buspsjh37b/ipvi=.ed25519
# => depth: 1
# => kind: &82244417f956ac7c599f191593f7e441a4fafa20a4158fd52e154f1dc4c8ed92.sha256
# => prev: %jvKh9yoiEJaePzoWCF1nnqpIlPgTk9FHEtqczQbvzGM=.sha256
# =>
# => &ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb.sha256:&2e7a0bc31f3c4fe6114051c3a56c8ed8a030b3b394df7d29d37648e9b8cbf54b.sha256
# =>
# => author: @ajgdylxeifojlxpbmen3exlnsbx8buspsjh37b/ipvi=.ed25519
# => depth: 2
# => kind: &82244417f956ac7c599f191593f7e441a4fafa20a4158fd52e154f1dc4c8ed92.sha256
# => prev: %jvKh9yoiEJaePzoWCF1nnqpIlPgTk9FHEtqczQbvzGM=.sha256
# =>
# => &ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb.sha256:&2e7a0bc31f3c4fe6114051c3a56c8ed8a030b3b394df7d29d37648e9b8cbf54b.sha256
# =>
pigeon peer add @m0LEP+0NrGqu1wT8/4a3nOPuRBM+DrMpUahDZ3/cDi8=.ed25519
# =>
pigeon peer remove @78daXMc/BOq5F1RWLMN4zgPVBVLqA4ShkLgE6z9OUGQ=.ed25519
# =>
pigeon peer block @GOl+398b2kWeLi6+DCcU0i3AWD6vWmUtocBVYbpkpNk=.ed25519
# =>
pigeon peer all
# => @c8hovH5OOzNJ1SXUsIN+zI23xMcvGdEbs3ZJgzpthrw=.ed25519
# => @GOl+398b2kWeLi6+DCcU0i3AWD6vWmUtocBVYbpkpNk=.ed25519
# => @m0LEP+0NrGqu1wT8/4a3nOPuRBM+DrMpUahDZ3/cDi8=.ed25519
pigeon bundle create
# => (creates @GOl+398b2kWeLi6+DCcU0i3AWD6vWmUtocBVYbpkpNk=.ed25519.pigeon)
pigeon bundle consume @GOl+398b2kWeLi6+DCcU0i3AWD6vWmUtocBVYbpkpNk=.ed25519.pigeon
# =>
```

6
dist/pigeon.rb vendored Normal file
View File

@ -0,0 +1,6 @@
require_relative File.join("pigeon", "config.rb")
require_relative File.join("pigeon", "storage.rb")
require_relative File.join("pigeon", "key_pair.rb")
module Pigeon
end

6
dist/pigeon/config.rb vendored Normal file
View File

@ -0,0 +1,6 @@
module Pigeon
module Config
VERSION = "0.0.1"
end
end

43
dist/pigeon/key_pair.rb vendored Normal file
View File

@ -0,0 +1,43 @@
require "ed25519"
require "securerandom"
require "base64"
module Pigeon
# This is a wrapper around the `ed25519` gem to
# help us maintain our sanity when the Gem's API
# changes.
class KeyPair
HEADER, FOOTER = ["@", ".ed25519"]
def self.current
raise "TODO"
end
# `seed` is a 32-byte seed value from which
# the key should be derived
def initialize(seed = SecureRandom.random_bytes(Ed25519::KEY_SIZE))
@seed = seed
@raw_key = Ed25519::SigningKey.new(seed)
end
def private_key
@private_key ||= Base64.strict_encode64(@seed)
end
def public_key
bytes = @raw_key.verify_key.to_bytes
b64 = Base64.strict_encode64(bytes)
@public_key ||= [HEADER, b64, FOOTER].join("")
end
def save!
{
public_key: public_key,
private_key: private_key,
}.map do |k, v|
Pigeon::Storage.current.save_conf(k, v)
end
end
end
end

75
dist/pigeon/storage.rb vendored Normal file
View File

@ -0,0 +1,75 @@
require "pry"
require "digest"
module Pigeon
class Storage
ROOT_DIR = ".pigeon"
CONF_DIR = "conf"
BLOB_DIR = "blobs"
def self.current
@current ||= self.new
end
def initialize
unless initialized?
create_root_dir
create_conf_dir
create_blob_dir
end
end
def save_conf(key, value)
path = conf_path_for(key)
File.write(path, value.to_s)
end
def get_conf(key)
File.read(conf_path_for(key))
end
def set_blob(data)
hash = Digest::SHA256.hexdigest(data)
path = blob_path_for(hash)
File.write(path, data)
end
def initialized?
File.directory?(root_dir)
end
private
def blob_dir
@blob_dir ||= File.join(ROOT_DIR, BLOB_DIR, "sha256")
end
def root_dir
@root_dir ||= File.join(ROOT_DIR)
end
# WARNING: Side effects. Im in a hurry. -RC
def blob_path_for(hex_hash_string)
first_part = File.join(blob_dir, hex_hash_string[0, 2])
FileUtils.mkdir_p(first_part)
File.join(first_part, hex_hash_string[2..-1])
end
def conf_path_for(key)
File.join(conf_dir, key.to_s)
end
def create_conf_dir
FileUtils.mkdir_p(File.join(ROOT_DIR, CONF_DIR))
end
def create_blob_dir
FileUtils.mkdir_p(blob_dir)
end
def create_root_dir
FileUtils.mkdir_p(root_dir)
end
end
end

63
pigeon-cli Executable file
View File

@ -0,0 +1,63 @@
#!/usr/bin/env ruby
require_relative File.join("dist", "pigeon")
require "thor"
module Pigeon
class Identity < Thor
class RoostAlreadyExists < StandardError; end
desc "new", "Creates a new identiy in `.pigeon` directory if none exists"
def new
# TODO: --force flag
# TODO: --seed flag
if Dir.exist?(Pigeon::Storage::ROOT_DIR)
puts "Pigeon has detected a `.pigeon` directory.
Refusing to overwrite existing Pigeon config.
Remove roost or switch to a different directory."
raise RoostAlreadyExists
end
kp = Pigeon::KeyPair.new()
kp.save!
puts kp.public_key
end
desc "show", "Prints a base64 identiy string to STDOUT"
def show
puts Pigeon::Storage.current.get_conf("public_key")
end
end
class Blob < Thor
desc "set", "Copy arbitrary binary data into the roost"
def set(data)
Pigeon::Storage.current.set_blob(data)
end
desc "get", "Read arbitrary data from the roost"
def get
raise "WIP"
end
end
class CLI < Thor
desc "status", "Show various information about the `.pigeon` directory"
def status
puts "Version: #{Config::VERSION}"
end
desc "identity SUBCOMMAND ...ARGS", "Manage `.pigeon` identity"
subcommand "identity", Identity
desc "blob SUBCOMMAND ...ARGS", "Manage blob storage"
subcommand "blob", Blob
end
end
Pigeon::CLI.start(ARGV)

View File

@ -0,0 +1,7 @@
require "spec_helper"
RSpec.describe Pigeon::Config do
it "has a `foo`" do
expect(Pigeon::Config::VERSION).to eq("0.0.1")
end
end

View File

@ -0,0 +1,19 @@
require "spec_helper"
RSpec.describe Pigeon::KeyPair do
FAKE_SEED = "\x15\xB1\xA8\x1D\xE1\x1Cx\xF0" \
"\xC6\xDCK\xDE\x9A\xB7>\x86o\x92\xEF\xB7\x17" \
")\xFF\x01E\b$b)\xC9\x82\b"
let(:kp) { Pigeon::KeyPair.new(FAKE_SEED) }
it "generates a pair from a seed" do
x = "@7n/g0ca9FFWvMkXy2TMwM7bdMn6tNiEHKzrFX+CzAmQ=.ed25519"
expect(kp.public_key).to eq(x)
y = "FbGoHeEcePDG3Evemrc+hm+S77cXKf8BRQgkYinJggg="
expect(kp.private_key).to eq(y)
end
# TODO Add fakefs https://github.com/fakefs/fakefss
it "saves keypairs to disk"
end

9
spec/spec_helper.rb Normal file
View File

@ -0,0 +1,9 @@
require "pry"
require "simplecov"
SimpleCov.start
require_relative File.join("..", "dist", "pigeon")
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
RSpec.configure do |config|
config.disable_monkey_patching!
config.order = :random
end