WIP. TODO: Make sure client is ingesting blobs in a bundle

This commit is contained in:
Netscape Navigator 2020-04-23 07:21:00 -05:00
parent e087888e94
commit 8fed4dc0bc
17 changed files with 189 additions and 116 deletions

60
.map Normal file
View File

@ -0,0 +1,60 @@
=> #<Pigeon::Database:0x0000559bd1590cc8
@who_am_i=#<Pigeon::LocalIdentity:0x0000559bd15d1890 @seed="\x1FL^9\x90e\xF8g\xF2\x83\xB4\xC4>c\x85\xAE2w\xBA&,@\xD3\x96\xCAlO*\xB9\x8DkX", @signing_key=#<Ed25519::SigningKey:0x0000559bd15d17c8>>,
@store=
#<Pigeon::Storage:0x0000559bd15909f8
@path="old.db",
@store=
#<PStore:0x0000559bd1590458
@abort=false,
@filename="pigeon.db",
@lock=#<Thread::Mutex:0x0000559bd1597988>,
@rdonly=true,
@table=
{"blocked"=>#<Set: {}>,
"conf"=>{"SEED"=>"\x1FL^9\x90e\xF8g\xF2\x83\xB4\xC4>c\x85\xAE2w\xBA&,@\xD3\x96\xCAlO*\xB9\x8DkX", "HEAD.draft"=>nil},
"messages.count"=>{"@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519"=>4},
"messages"=>
{"%8STBRYR0WYJJRSD8DRA9RT6RF6QD6AKARCDYV17X8REGACHZ41W0.sha256"=>
#<Pigeon::Message:0x0000559bd15eb448
@author=#<Pigeon::RemoteIdentity:0x0000559bd15ea4d0 @multihash="@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519">,
@body={"a"=>"\"b\""},
@depth=0,
@kind="unit_test",
@lipmaa=0,
@prev="NONE",
@signature="8581280WEPNQGJ4DA6K0M7W726YVK1QGW5T7EPGZ61V4HV2GD1RKAB5AN8FXREW0NZKYKFANHW64H3YT0RSMMY30T8TBDJJSR0G9E0G.sig.ed25519">,
"%T88VZKCWN33CVD0TFBRPJ13NJHXF19TFRWP8NFJ1JGE5RB5ETC0G.sha256"=>
#<Pigeon::Message:0x0000559bd160cb98
@author=#<Pigeon::RemoteIdentity:0x0000559bd160c7d8 @multihash="@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519">,
@body={"c"=>"\"d\""},
@depth=1,
@kind="unit_test",
@lipmaa=0,
@prev="%8STBRYR0WYJJRSD8DRA9RT6RF6QD6AKARCDYV17X8REGACHZ41W0.sha256",
@signature="60R873HBC5GHGVFWBC3RZBHXTQW0240GNF20JYBR71V4B1Z57HHXJ6N39Y4QZZPD34PQGZEQVMSAXTC71PATXAMWBVDCF2S9S45KM1G.sig.ed25519">,
"%JD4BETS4YH4ZA7CMP4ZHG0R62T5B0EAFDYHNM5S12M04SAF9AJ4G.sha256"=>
#<Pigeon::Message:0x0000559bd16165a8
@author=#<Pigeon::RemoteIdentity:0x0000559bd1616300 @multihash="@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519">,
@body={"e"=>"\"f\""},
@depth=2,
@kind="unit_test",
@lipmaa=1,
@prev="%T88VZKCWN33CVD0TFBRPJ13NJHXF19TFRWP8NFJ1JGE5RB5ETC0G.sha256",
@signature="7DH9ZXMVT6RJEX31BPNSJ3XRA3AMPV97A1CPWW4BV0N99FW2JEPSCVQNJP7SZWA1N7BT560Y9EAK4N7AWFHDEFZV9AJ7PS81CVRF600.sig.ed25519">,
"%WTRSWSVA84DK2QMX5FDSNCVSAKQ4AFNPBW6VE93X4SJ1R60WDYMG.sha256"=>
#<Pigeon::Message:0x0000559bd1638978
@author=#<Pigeon::RemoteIdentity:0x0000559bd1638590 @multihash="@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519">,
@body={"g"=>"\"h\""},
@depth=3,
@kind="unit_test",
@lipmaa=2,
@prev="%JD4BETS4YH4ZA7CMP4ZHG0R62T5B0EAFDYHNM5S12M04SAF9AJ4G.sha256",
@signature="6KZZ2816J8V28QZG5EFM1BZAB2TF1HC87YTCQRSN1Q7395K91C9E7KE7DATT99N7XGQEJ5MRCNDS7354C5KN7763C1XVARKWRDG4T1R.sig.ed25519">},
"messages.by_depth"=>
{"@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519.0"=>"%8STBRYR0WYJJRSD8DRA9RT6RF6QD6AKARCDYV17X8REGACHZ41W0.sha256",
"@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519.1"=>"%T88VZKCWN33CVD0TFBRPJ13NJHXF19TFRWP8NFJ1JGE5RB5ETC0G.sha256",
"@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519.2"=>"%JD4BETS4YH4ZA7CMP4ZHG0R62T5B0EAFDYHNM5S12M04SAF9AJ4G.sha256",
"@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519.3"=>"%WTRSWSVA84DK2QMX5FDSNCVSAKQ4AFNPBW6VE93X4SJ1R60WDYMG.sha256"},
"peers"=>#<Set: {}>},
@thread_safe=false,
@ultra_safe=true>>>

View File

@ -91,6 +91,7 @@ TODO
- [X] Check block list before ingesting bundles. - [X] Check block list before ingesting bundles.
- [X] Need a way of importing / exporting a feeds blobs. (see "Bundle Brainstorming" below) - [X] Need a way of importing / exporting a feeds blobs. (see "Bundle Brainstorming" below)
- [X] Need a way of adding peers messages / gossip to bundles. (see "Bundle Brainstorming" below) - [X] Need a way of adding peers messages / gossip to bundles. (see "Bundle Brainstorming" below)
- [ ] Rename `who_am_i` as `get_who_am_i` to follow VERB + NOUN convention.
- [ ] Update README.md / tutorial.rb (user manual for `Pigeon::Database`). - [ ] Update README.md / tutorial.rb (user manual for `Pigeon::Database`).
- [ ] Update spec document CLI usage examples to reflect API changes in 2020. - [ ] Update spec document CLI usage examples to reflect API changes in 2020.
- [ ] Publish to RubyGems - [ ] Publish to RubyGems

BIN
a.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
b.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -41,13 +41,13 @@ module Pigeon
raise ConfigAlreadyExists raise ConfigAlreadyExists
end end
$db = Pigeon::Database.new $db = Pigeon::Database.new
puts db.local_identity.multihash puts db.who_am_i.multihash
end end
desc "show", "Prints your identiy string to STDOUT" desc "show", "Prints your identiy string to STDOUT"
def show def show
puts db.local_identity.multihash puts db.who_am_i.multihash
end end
end end
@ -56,7 +56,7 @@ module Pigeon
def set(data = "") def set(data = "")
blob = (data != "") ? data : STDIN.read blob = (data != "") ? data : STDIN.read
puts db.put_blob(blob) puts db.add_blob(blob)
end end
desc "get", "Read arbitrary data from the database" desc "get", "Read arbitrary data from the database"
@ -103,9 +103,9 @@ module Pigeon
def append(key, raw_value = "") def append(key, raw_value = "")
v = (raw_value != "") ? raw_value : STDIN.read v = (raw_value != "") ? raw_value : STDIN.read
if db.current_draft if db.get_draft
db.update_draft(key, v) db.update_draft(key, v)
puts db.current_draft.render_as_draft puts db.get_draft.render_as_draft
else else
bail("You must create a draft first") bail("You must create a draft first")
end end
@ -114,13 +114,13 @@ module Pigeon
desc "show", "Print current message to STDOUT." desc "show", "Print current message to STDOUT."
def show def show
puts db.current_draft.render_as_draft puts db.get_draft.render_as_draft
end end
desc "sign", "Commit current DRAFT to local feed." desc "sign", "Commit current DRAFT to local feed."
def sign def sign
puts db.publish_draft(db.current_draft).render puts db.publish_draft(db.get_draft).render
end end
end end
@ -128,13 +128,13 @@ module Pigeon
desc "create", "Create a pigeon bundle file" desc "create", "Create a pigeon bundle file"
def create(file_path = Pigeon::DEFAULT_BUNDLE_PATH) def create(file_path = Pigeon::DEFAULT_BUNDLE_PATH)
db.create_bundle(file_path) db.save_bundle(file_path)
end end
desc "ingest", "Ingest a pigeon bundle file" desc "ingest", "Ingest a pigeon bundle file"
def ingest(file_path = Pigeon::DEFAULT_BUNDLE_PATH) def ingest(file_path = Pigeon::DEFAULT_BUNDLE_PATH)
db.ingest_bundle(file_path) db.publish_bundle(file_path)
end end
end end
@ -148,13 +148,13 @@ module Pigeon
desc "find-all", "Find all message IDs of a particular identity." desc "find-all", "Find all message IDs of a particular identity."
def find_all(author = nil) def find_all(author = nil)
puts db.find_all_messages(author).join(Pigeon::CR) + Pigeon::CR puts db.all_messages(author).join(Pigeon::CR) + Pigeon::CR
end end
desc "last", "Grab your last message. INTERNAL USE ONLY" desc "last", "Grab your last message. INTERNAL USE ONLY"
def last def last
me = db.local_identity me = db.who_am_i
mcount = db.get_message_count_for(me.multihash) mcount = db.get_message_count_for(me.multihash)
multihash = db.get_message_by_depth(me.multihash, mcount - 1) multihash = db.get_message_by_depth(me.multihash, mcount - 1)
puts multihash puts multihash
@ -165,7 +165,7 @@ module Pigeon
desc "status", "Show various information about the `.pgn` directory" desc "status", "Show various information about the `.pgn` directory"
def status def status
me = db.local_identity.multihash me = db.who_am_i.multihash
mine = db.get_message_count_for(me) mine = db.get_message_count_for(me)
puts " puts "
-`. Pigeon Protocol Ruby Client -`. Pigeon Protocol Ruby Client
@ -173,7 +173,7 @@ module Pigeon
_) ( Peers: #{db.all_peers.count} _) ( Peers: #{db.all_peers.count}
/ ) Blocked: #{db.all_blocks.count} / ) Blocked: #{db.all_blocks.count}
/_,' / Msgs Published: #{mine} /_,' / Msgs Published: #{mine}
\\ / Msgs Total: #{db.find_all_messages.count} \\ / Msgs Total: #{db.all_messages.count}
===m\" \"m=== ===m\" \"m===
Your local identity hash: Your local identity hash:
#{me} #{me}

BIN
c.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 708 B

View File

@ -154,7 +154,7 @@ module Pigeon
end end
def self.publish_draft(db, draft) def self.publish_draft(db, draft)
author = db.local_identity author = db.who_am_i
mhash = author.multihash mhash = author.multihash
template = MessageSerializer.new(draft) template = MessageSerializer.new(draft)
depth = db.get_message_count_for(mhash) depth = db.get_message_count_for(mhash)
@ -173,7 +173,7 @@ module Pigeon
end end
def self.update_draft(db, key, value) def self.update_draft(db, key, value)
draft = db.current_draft draft = db.get_draft
draft[key] = value draft[key] = value
db.save_draft(draft) db.save_draft(draft)
return draft.body[key] return draft.body[key]

View File

@ -1,6 +1,6 @@
module Pigeon module Pigeon
class Database class Database
attr_reader :local_identity attr_reader :who_am_i
def initialize(path: PIGEON_DB_PATH) def initialize(path: PIGEON_DB_PATH)
@store = Pigeon::Storage.new(path: path) @store = Pigeon::Storage.new(path: path)
@ -16,10 +16,10 @@ module Pigeon
def all_peers(); store.all_peers(); end def all_peers(); store.all_peers(); end
# === MESSAGES # === MESSAGES
def find_all_messages(mhash = nil); store.find_all_messages(mhash); end def all_messages(mhash = nil); store.all_messages(mhash); end
def message_saved?(multihash); store.message_saved?(multihash); end def message_saved?(multihash); store.message_saved?(multihash); end
def save_message(msg_obj) def _save_message(msg_obj)
store.insert_message(Helpers.verify_message(self, msg_obj)) store.insert_message(Helpers.verify_message(self, msg_obj))
end end
@ -33,19 +33,19 @@ module Pigeon
store.get_message_by_depth(multihash, depth) store.get_message_by_depth(multihash, depth)
end end
def create_message(kind, params) def add_message(kind, params)
publish_draft(new_draft(kind: kind, body: params)) publish_draft(new_draft(kind: kind, body: params))
end end
# Store a message that someone (not the LocalIdentity) # Store a message that someone (not the LocalIdentity)
# has authored. # has authored.
def ingest_message(author:, def _ingest_message(author:,
body:, body:,
depth:, depth:,
kind:, kind:,
lipmaa:, lipmaa:,
prev:, prev:,
signature:) signature:)
msg = Message.new(author: RemoteIdentity.new(author), msg = Message.new(author: RemoteIdentity.new(author),
kind: kind, kind: kind,
body: body, body: body,
@ -53,11 +53,11 @@ module Pigeon
lipmaa: lipmaa, lipmaa: lipmaa,
signature: signature, signature: signature,
depth: depth) depth: depth)
save_message(msg) _save_message(msg)
end end
# === DRAFTS # === DRAFTS
def reset_current_draft; set_config(CURRENT_DRAFT, nil); end def reset_draft; add_config(CURRENT_DRAFT, nil); end
def new_draft(kind:, body: {}) def new_draft(kind:, body: {})
old = get_config(CURRENT_DRAFT) old = get_config(CURRENT_DRAFT)
@ -68,11 +68,11 @@ module Pigeon
end end
def save_draft(draft) def save_draft(draft)
set_config(CURRENT_DRAFT, draft) add_config(CURRENT_DRAFT, draft)
draft draft
end end
def current_draft def get_draft
draft = store.get_config(CURRENT_DRAFT) draft = store.get_config(CURRENT_DRAFT)
if draft if draft
return draft return draft
@ -84,20 +84,20 @@ module Pigeon
def update_draft(k, v); Helpers.update_draft(self, k, v); end def update_draft(k, v); Helpers.update_draft(self, k, v); end
def reset_draft def reset_draft
set_config(CURRENT_DRAFT, nil) add_config(CURRENT_DRAFT, nil)
end end
# Author a new message. # Author a new message.
def publish_draft(draft = self.current_draft) def publish_draft(draft = self.get_draft)
Helpers.publish_draft(self, draft) Helpers.publish_draft(self, draft)
end end
# === BUNDLES # === BUNDLES
def create_bundle(file_path = DEFAULT_BUNDLE_PATH) def save_bundle(file_path = DEFAULT_BUNDLE_PATH)
# Fetch messages for all peers # Fetch messages for all peers
peers = all_peers + [local_identity.multihash] peers = all_peers + [who_am_i.multihash]
messages = peers.map do |peer| messages = peers.map do |peer|
find_all_messages(peer) all_messages(peer)
.map { |multihash| read_message(multihash) } .map { |multihash| read_message(multihash) }
.sort_by(&:depth) .sort_by(&:depth)
end.flatten end.flatten
@ -114,10 +114,11 @@ module Pigeon
content = messages content = messages
.map { |message| message.render } .map { |message| message.render }
.join(BUNDLE_MESSAGE_SEPARATOR) .join(BUNDLE_MESSAGE_SEPARATOR)
File.join(file_path, "gossip.pgn")
File.write(File.join(file_path, "gossip.pgn"), content + CR) File.write(File.join(file_path, "gossip.pgn"), content + CR)
end end
def ingest_bundle(file_path = DEFAULT_BUNDLE_PATH) def publish_bundle(file_path = DEFAULT_BUNDLE_PATH)
bundle = File.read(File.join(file_path, "gossip.pgn")) bundle = File.read(File.join(file_path, "gossip.pgn"))
tokens = Pigeon::Lexer.tokenize(bundle) tokens = Pigeon::Lexer.tokenize(bundle)
Pigeon::Parser.parse(self, tokens) Pigeon::Parser.parse(self, tokens)
@ -125,11 +126,11 @@ module Pigeon
# === BLOBS # === BLOBS
def get_blob(b); store.get_blob(b); end def get_blob(b); store.get_blob(b); end
def put_blob(b); store.put_blob(b); end def add_blob(b); store.add_blob(b); end
# === DB Management # === DB Management
def get_config(k); store.get_config(k); end def get_config(k); store.get_config(k); end
def set_config(k, v); store.set_config(k, v); end def add_config(k, v); store.add_config(k, v); end
def reset_database; store.reset; init_ident; end def reset_database; store.reset; init_ident; end
private private
@ -139,11 +140,11 @@ module Pigeon
def init_ident def init_ident
secret = get_config(SEED_CONFIG_KEY) secret = get_config(SEED_CONFIG_KEY)
if secret if secret
@local_identity = LocalIdentity.new(secret) @who_am_i = LocalIdentity.new(secret)
else else
new_seed = SecureRandom.random_bytes(Ed25519::KEY_SIZE) new_seed = SecureRandom.random_bytes(Ed25519::KEY_SIZE)
set_config(SEED_CONFIG_KEY, new_seed) add_config(SEED_CONFIG_KEY, new_seed)
@local_identity = LocalIdentity.new(new_seed) @who_am_i = LocalIdentity.new(new_seed)
end end
end end
end end

View File

@ -41,7 +41,7 @@ module Pigeon
def finish_this_message! def finish_this_message!
@scratchpad.freeze @scratchpad.freeze
unless @db.peer_blocked?(@scratchpad.fetch(:author)) unless @db.peer_blocked?(@scratchpad.fetch(:author))
@results.push(@db.ingest_message(**@scratchpad)) @results.push(@db._ingest_message(**@scratchpad))
end end
reset_scratchpad reset_scratchpad
end end

View File

@ -43,7 +43,7 @@ module Pigeon
read { store[CONF_NS][key] } read { store[CONF_NS][key] }
end end
def set_config(key, value) def add_config(key, value)
write do write do
a = store.fetch(CONF_NS) a = store.fetch(CONF_NS)
raise "FIX SAVED DRAFTS" if value.instance_variable_get(:@db) raise "FIX SAVED DRAFTS" if value.instance_variable_get(:@db)
@ -51,7 +51,7 @@ module Pigeon
end end
end end
def put_blob(data) def add_blob(data)
size = data.bytesize size = data.bytesize
if (size > BLOB_BYTE_LIMIT) if (size > BLOB_BYTE_LIMIT)
raise "Blob size limit is #{BLOB_BYTE_LIMIT} bytes. Got #{size}" raise "Blob size limit is #{BLOB_BYTE_LIMIT} bytes. Got #{size}"
@ -79,7 +79,7 @@ module Pigeon
read { store[COUNT_INDEX_NS][mhash] || 0 } read { store[COUNT_INDEX_NS][mhash] || 0 }
end end
def find_all_messages(author) def all_messages(author)
if author if author
all = [] all = []
depth = -1 depth = -1

BIN
pigeon.db

Binary file not shown.

View File

@ -13,35 +13,41 @@ RSpec.describe Pigeon::Message do
end end
def create_fake_messages def create_fake_messages
blobs = [db.create_message(db.put_blob("one"), { "a" => "b" }), blobs = [db.add_message(db.add_blob("one"), { "a" => "b" }),
db.create_message("a", { db.put_blob("two") => "b" }), db.add_message("a", { db.add_blob("two") => "b" }),
db.create_message("a", { "b" => db.put_blob("three") })] db.add_message("a", { "b" => db.add_blob("three") })]
normal = (1..10) normal = (1..10)
.to_a .to_a
.map do |n| { "foo" => ["bar", "123", SecureRandom.uuid].sample } end .map do |n| { "foo" => ["bar", "123", SecureRandom.uuid].sample } end
.map do |d| db.create_message(SecureRandom.uuid, d) end .map do |d| db.add_message(SecureRandom.uuid, d) end
blobs + normal blobs + normal
end end
it "creates a bundle" do it "creates a bundle" do
expected_bundle = create_fake_messages.map(&:render).join("\n\n") + "\n" expected_bundle = create_fake_messages.map(&:render).join("\n\n") + "\n"
db.create_bundle db.save_bundle
actual_bundle = File.read(File.join(Pigeon::DEFAULT_BUNDLE_PATH, "gossip.pgn")) actual_bundle = File.read(File.join(Pigeon::DEFAULT_BUNDLE_PATH, "gossip.pgn"))
expect(expected_bundle).to eq(actual_bundle) expect(expected_bundle).to eq(actual_bundle)
end end
it "does not crash when ingesting old messages" do it "does not crash when ingesting old messages" do
create_fake_messages create_fake_messages
db.create_bundle db.save_bundle
db.ingest_bundle db.publish_bundle
end end
it "does not ingest messages from blocked peers" do it "does not ingest messages from blocked peers" do
db.reset_database db.reset_database
antagonist = "@PPJQ3Q36W258VQ1NKYY2G7VW24J8NMAACHXCD83GCQ3K8F4C9X2G.ed25519" antagonist = "@PPJQ3Q36W258VQ1NKYY2G7VW24J8NMAACHXCD83GCQ3K8F4C9X2G.ed25519"
db.block_peer(antagonist) db.block_peer(antagonist)
db.ingest_bundle("./spec/fixtures/x") db.publish_bundle("./spec/fixtures/x")
expect(db.find_all_messages.count).to eq(0) expect(db.all_messages.count).to eq(0)
end
it "ingests a bundle's blobs" do
db.reset_database
db.publish_bundle("./spec/fixtures/has_blobs")
expect(db.all_messages.count).to eq(0)
end end
end end

View File

@ -12,8 +12,8 @@ RSpec.describe Pigeon::Draft do
db.new_draft(kind: "unit_test") db.new_draft(kind: "unit_test")
logo = File.read("./logo.png") logo = File.read("./logo.png")
db.update_draft("a", "bar") db.update_draft("a", "bar")
db.update_draft("b", db.put_blob(logo)) db.update_draft("b", db.add_blob(logo))
db.current_draft db.get_draft
end end
MSG = [ MSG = [
@ -28,7 +28,7 @@ RSpec.describe Pigeon::Draft do
].join("\n") ].join("\n")
it "renders a message" do it "renders a message" do
pk = db.local_identity.multihash pk = db.who_am_i.multihash
actual = message.render_as_draft actual = message.render_as_draft
expected = MSG.gsub("___", pk) expected = MSG.gsub("___", pk)
expect(actual).to start_with(expected) expect(actual).to start_with(expected)
@ -37,7 +37,7 @@ RSpec.describe Pigeon::Draft do
it "creates a new message" do it "creates a new message" do
db.reset_draft db.reset_draft
db.new_draft(kind: "unit_test") db.new_draft(kind: "unit_test")
hash = db.put_blob(File.read("./logo.png")) hash = db.add_blob(File.read("./logo.png"))
expectations = { expectations = {
kind: "unit_test", kind: "unit_test",
body: { body: {
@ -52,7 +52,7 @@ RSpec.describe Pigeon::Draft do
expect(message.kind).to eq("unit_test") expect(message.kind).to eq("unit_test")
expect(message.body).to eq(expectations.fetch(:body)) expect(message.body).to eq(expectations.fetch(:body))
expectations.map do |k, v| expectations.map do |k, v|
left = db.current_draft.send(k) left = db.get_draft.send(k)
expect(left).to eq(v) expect(left).to eq(v)
end end
end end

View File

@ -4,10 +4,10 @@ RSpec.describe Pigeon::Message do
def reset_draft(params) def reset_draft(params)
db.reset_draft db.reset_draft
db.new_draft(kind: "unit_test", body: params) db.new_draft(kind: "unit_test", body: params)
db.current_draft db.get_draft
end end
def create_message(params) def add_message(params)
draft = reset_draft(params) draft = reset_draft(params)
db.publish_draft(draft) db.publish_draft(draft)
end end
@ -19,11 +19,11 @@ RSpec.describe Pigeon::Message do
end end
let(:draft) do let(:draft) do
hash = db.put_blob(File.read("./logo.png")) hash = db.add_blob(File.read("./logo.png"))
reset_draft({ "a" => "bar", "b" => hash }) reset_draft({ "a" => "bar", "b" => hash })
end end
let(:templated_message) { create_message({ "a" => "b" }) } let(:templated_message) { add_message({ "a" => "b" }) }
let (:template) do let (:template) do
Pigeon::MessageSerializer.new(templated_message) Pigeon::MessageSerializer.new(templated_message)
@ -31,12 +31,12 @@ RSpec.describe Pigeon::Message do
it "discards a draft after signing" do it "discards a draft after signing" do
db.publish_draft(draft) db.publish_draft(draft)
expect { db.current_draft }.to raise_error("THERE IS NO DRAFT. CREATE ONE FIRST.") expect { db.get_draft }.to raise_error("THERE IS NO DRAFT. CREATE ONE FIRST.")
end end
it "creates a single message" do it "creates a single message" do
message = db.publish_draft(draft) message = db.publish_draft(draft)
expect(message.author.multihash).to eq(db.local_identity.multihash) expect(message.author.multihash).to eq(db.who_am_i.multihash)
expect(message.body).to eq(draft.body) expect(message.body).to eq(draft.body)
expect(message.depth).to eq(0) expect(message.depth).to eq(0)
expect(message.kind).to eq("unit_test") expect(message.kind).to eq("unit_test")
@ -79,10 +79,10 @@ RSpec.describe Pigeon::Message do
end end
it "verifies accuracy of hash chain" do it "verifies accuracy of hash chain" do
m1 = create_message({ "a" => "b" }) m1 = add_message({ "a" => "b" })
m2 = create_message({ "c" => "d" }) m2 = add_message({ "c" => "d" })
m3 = create_message({ "e" => "f" }) m3 = add_message({ "e" => "f" })
m4 = create_message({ "g" => "h" }) m4 = add_message({ "g" => "h" })
expect(m1.prev).to eq(Pigeon::NOTHING) expect(m1.prev).to eq(Pigeon::NOTHING)
expect(m2.prev).to be expect(m2.prev).to be
@ -100,7 +100,7 @@ RSpec.describe Pigeon::Message do
body[SecureRandom.hex(6)] = SecureRandom.hex(6) body[SecureRandom.hex(6)] = SecureRandom.hex(6)
end end
expect do expect do
create_message(body) add_message(body)
end.to raise_error(Pigeon::Helpers::MessageSizeError, error) end.to raise_error(Pigeon::Helpers::MessageSizeError, error)
end end
@ -112,7 +112,7 @@ RSpec.describe Pigeon::Message do
plaintext = template.render_without_signature plaintext = template.render_without_signature
# Make fake pairs of data for cross-checking # Make fake pairs of data for cross-checking
key1 = db.local_identity.instance_variable_get(:@signing_key) key1 = db.who_am_i.instance_variable_get(:@signing_key)
key2 = Ed25519::SigningKey.new(secret) key2 = Ed25519::SigningKey.new(secret)
sig1 = key1.sign(plaintext) sig1 = key1.sign(plaintext)

View File

@ -30,7 +30,7 @@ RSpec.describe Pigeon::Lexer do
end end
it "ingests and reconstructs a bundle" do it "ingests and reconstructs a bundle" do
messages = db.ingest_bundle("./spec/fixtures/normal") messages = db.publish_bundle("./spec/fixtures/normal")
expect(messages.length).to eq(10) expect(messages.length).to eq(10)
expect(messages.map(&:class).uniq).to eq([Pigeon::Message]) expect(messages.map(&:class).uniq).to eq([Pigeon::Message])
re_bundled = messages.map(&:render).join("\n\n") + "\n" re_bundled = messages.map(&:render).join("\n\n") + "\n"

View File

@ -12,22 +12,22 @@ RSpec.describe Pigeon::Storage do
end end
it "sets a config" do it "sets a config" do
db.set_config("FOO", "BAR") db.add_config("FOO", "BAR")
value = db.get_config("FOO") value = db.get_config("FOO")
expect(value).to eq("BAR") expect(value).to eq("BAR")
db.set_config("FOO", nil) db.add_config("FOO", nil)
value = db.get_config("FOO") value = db.get_config("FOO")
expect(value).to eq(nil) expect(value).to eq(nil)
end end
it "manages configs" do it "manages configs" do
db.set_config("FOO", "BAR") db.add_config("FOO", "BAR")
value = db.get_config("FOO") value = db.get_config("FOO")
expect(value).to eq("BAR") expect(value).to eq("BAR")
end end
it "manages blobs" do it "manages blobs" do
logo_hash = db.put_blob(LOGO_BLOB) logo_hash = db.add_blob(LOGO_BLOB)
expect(db.get_blob(logo_hash)).to eq(LOGO_BLOB) expect(db.get_blob(logo_hash)).to eq(LOGO_BLOB)
end end
@ -48,27 +48,27 @@ RSpec.describe Pigeon::Storage do
end end
it "finds all authored by a particular feed" do it "finds all authored by a particular feed" do
ingested_messages = db.ingest_bundle("./spec/fixtures/normal") ingested_messages = db.publish_bundle("./spec/fixtures/normal")
author = ingested_messages.first.author.multihash author = ingested_messages.first.author.multihash
actual_messages = db.find_all_messages(author) actual_messages = db.all_messages(author)
search_results = db.find_all_messages(author) search_results = db.all_messages(author)
end end
it "finds all messages" do it "finds all messages" do
msgs = [ msgs = [
db.create_message("strings", { db.add_message("strings", {
"example_1.1" => "This is a string.", "example_1.1" => "This is a string.",
"example=_." => "A second string.", "example=_." => "A second string.",
}), }),
db.create_message("d", { db.add_message("d", {
"e" => db.put_blob(File.read("./logo.png")), "e" => db.add_blob(File.read("./logo.png")),
}), }),
db.create_message("g", { db.add_message("g", {
"me_myself_and_i" => db.local_identity.multihash, "me_myself_and_i" => db.who_am_i.multihash,
}), }),
] ]
me = db.local_identity.multihash me = db.who_am_i.multihash
results = db.find_all_messages(me) results = db.all_messages(me)
expect(results.length).to eq(3) expect(results.length).to eq(3)
expect(msgs[0].multihash).to eq(results[0]) expect(msgs[0].multihash).to eq(results[0])
expect(msgs[1].multihash).to eq(results[1]) expect(msgs[1].multihash).to eq(results[1])

View File

@ -1,31 +1,36 @@
require "pigeon" # add_blob
# add_config
# add_message
# add_peer
# all_blocks
# all_messages
# all_peers
# block_peer
# get_blob
# get_config
# get_draft
# get_message_by_depth
# get_message_count_for
# message_saved?
# peer_blocked?
# who_am_i
# new_draft
# publish_bundle
# publish_draft
# read_message
# remove_peer
# reset_database
# reset_draft
# save_bundle
# save_draft
# update_draft
require_relative "lib/pigeon"
require "pry" require "pry"
files = %w(a.gif b.gif c.gif)
db = Pigeon::Database.new(path: "my.db") body = { "what" => "A simple bundle with a few blobs" }
db = Pigeon::Database.new(path: "new.db")
db.reset_draft db.add_message("description", body)
db.current_draft files.map { |file| db.add_blob(file) }
db.reset_draft binding.pry
db.publish_draft db.save_bundle("./spec/fixtures/has_blobs")
db.save_draft
db.save_message
db.reset_current_draft
db.message_saved?
db.read_message
db.create_message
db.find_all_messages
db.get_message_by_depth
db.get_message_count_for
db.local_identity
db.remove_peer
db.add_peer
db.block_peer
db.all_peers
db.all_blocks
db.get_blob
db.put_blob
db.create_bundle
db.get_config
db.ingest_bundle
db.set_config
db.reset_database