From 8fed4dc0bcd9c5ff78ff32913578576812b82f53 Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Thu, 23 Apr 2020 07:21:00 -0500 Subject: [PATCH] WIP. TODO: Make sure client is ingesting blobs in a bundle --- .map | 60 +++++++++++++++++++++++++++++++++ README.md | 1 + a.gif | Bin 0 -> 2201 bytes b.gif | Bin 0 -> 2322 bytes bin/pigeon-cli | 26 +++++++-------- c.gif | Bin 0 -> 708 bytes lib/pigeon.rb | 4 +-- lib/pigeon/database.rb | 53 ++++++++++++++--------------- lib/pigeon/parser.rb | 2 +- lib/pigeon/storage.rb | 6 ++-- pigeon.db | Bin 181 -> 406 bytes spec/pigeon/bundle_spec.rb | 24 ++++++++----- spec/pigeon/draft_spec.rb | 10 +++--- spec/pigeon/message_spec.rb | 24 ++++++------- spec/pigeon/parser_spec.rb | 2 +- spec/pigeon/storage_spec.rb | 28 ++++++++-------- tutorial.rb | 65 +++++++++++++++++++----------------- 17 files changed, 189 insertions(+), 116 deletions(-) create mode 100644 .map create mode 100644 a.gif create mode 100644 b.gif create mode 100644 c.gif diff --git a/.map b/.map new file mode 100644 index 0000000..2782e3f --- /dev/null +++ b/.map @@ -0,0 +1,60 @@ +=> #c\x85\xAE2w\xBA&,@\xD3\x96\xCAlO*\xB9\x8DkX", @signing_key=#>, + @store= + #, + @rdonly=true, + @table= + {"blocked"=>#, + "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"=> + #, + @body={"a"=>"\"b\""}, + @depth=0, + @kind="unit_test", + @lipmaa=0, + @prev="NONE", + @signature="8581280WEPNQGJ4DA6K0M7W726YVK1QGW5T7EPGZ61V4HV2GD1RKAB5AN8FXREW0NZKYKFANHW64H3YT0RSMMY30T8TBDJJSR0G9E0G.sig.ed25519">, + "%T88VZKCWN33CVD0TFBRPJ13NJHXF19TFRWP8NFJ1JGE5RB5ETC0G.sha256"=> + #, + @body={"c"=>"\"d\""}, + @depth=1, + @kind="unit_test", + @lipmaa=0, + @prev="%8STBRYR0WYJJRSD8DRA9RT6RF6QD6AKARCDYV17X8REGACHZ41W0.sha256", + @signature="60R873HBC5GHGVFWBC3RZBHXTQW0240GNF20JYBR71V4B1Z57HHXJ6N39Y4QZZPD34PQGZEQVMSAXTC71PATXAMWBVDCF2S9S45KM1G.sig.ed25519">, + "%JD4BETS4YH4ZA7CMP4ZHG0R62T5B0EAFDYHNM5S12M04SAF9AJ4G.sha256"=> + #, + @body={"e"=>"\"f\""}, + @depth=2, + @kind="unit_test", + @lipmaa=1, + @prev="%T88VZKCWN33CVD0TFBRPJ13NJHXF19TFRWP8NFJ1JGE5RB5ETC0G.sha256", + @signature="7DH9ZXMVT6RJEX31BPNSJ3XRA3AMPV97A1CPWW4BV0N99FW2JEPSCVQNJP7SZWA1N7BT560Y9EAK4N7AWFHDEFZV9AJ7PS81CVRF600.sig.ed25519">, + "%WTRSWSVA84DK2QMX5FDSNCVSAKQ4AFNPBW6VE93X4SJ1R60WDYMG.sha256"=> + #, + @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"=>#}, + @thread_safe=false, + @ultra_safe=true>>> diff --git a/README.md b/README.md index d39de57..dc0e05e 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,7 @@ TODO - [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 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 spec document CLI usage examples to reflect API changes in 2020. - [ ] Publish to RubyGems diff --git a/a.gif b/a.gif new file mode 100644 index 0000000000000000000000000000000000000000..ed902d41fa66599bb6d46a30da9ecff42ec6aa88 GIT binary patch literal 2201 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 H0kGtME<{UO literal 0 HcmV?d00001 diff --git a/bin/pigeon-cli b/bin/pigeon-cli index 95f6c46..3e5974a 100755 --- a/bin/pigeon-cli +++ b/bin/pigeon-cli @@ -41,13 +41,13 @@ module Pigeon raise ConfigAlreadyExists end $db = Pigeon::Database.new - puts db.local_identity.multihash + puts db.who_am_i.multihash end desc "show", "Prints your identiy string to STDOUT" def show - puts db.local_identity.multihash + puts db.who_am_i.multihash end end @@ -56,7 +56,7 @@ module Pigeon def set(data = "") blob = (data != "") ? data : STDIN.read - puts db.put_blob(blob) + puts db.add_blob(blob) end desc "get", "Read arbitrary data from the database" @@ -103,9 +103,9 @@ module Pigeon def append(key, raw_value = "") v = (raw_value != "") ? raw_value : STDIN.read - if db.current_draft + if db.get_draft db.update_draft(key, v) - puts db.current_draft.render_as_draft + puts db.get_draft.render_as_draft else bail("You must create a draft first") end @@ -114,13 +114,13 @@ module Pigeon desc "show", "Print current message to STDOUT." def show - puts db.current_draft.render_as_draft + puts db.get_draft.render_as_draft end desc "sign", "Commit current DRAFT to local feed." def sign - puts db.publish_draft(db.current_draft).render + puts db.publish_draft(db.get_draft).render end end @@ -128,13 +128,13 @@ module Pigeon desc "create", "Create a pigeon bundle file" def create(file_path = Pigeon::DEFAULT_BUNDLE_PATH) - db.create_bundle(file_path) + db.save_bundle(file_path) end desc "ingest", "Ingest a pigeon bundle file" def ingest(file_path = Pigeon::DEFAULT_BUNDLE_PATH) - db.ingest_bundle(file_path) + db.publish_bundle(file_path) end end @@ -148,13 +148,13 @@ module Pigeon desc "find-all", "Find all message IDs of a particular identity." 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 desc "last", "Grab your last message. INTERNAL USE ONLY" def last - me = db.local_identity + me = db.who_am_i mcount = db.get_message_count_for(me.multihash) multihash = db.get_message_by_depth(me.multihash, mcount - 1) puts multihash @@ -165,7 +165,7 @@ module Pigeon desc "status", "Show various information about the `.pgn` directory" def status - me = db.local_identity.multihash + me = db.who_am_i.multihash mine = db.get_message_count_for(me) puts " -`. Pigeon Protocol Ruby Client @@ -173,7 +173,7 @@ module Pigeon _) ( Peers: #{db.all_peers.count} / ) Blocked: #{db.all_blocks.count} /_,' / Msgs Published: #{mine} - \\ / Msgs Total: #{db.find_all_messages.count} + \\ / Msgs Total: #{db.all_messages.count} ===m\" \"m=== Your local identity hash: #{me} diff --git a/c.gif b/c.gif new file mode 100644 index 0000000000000000000000000000000000000000..38b1f66bcd737bed41ee45a0f41c11f09f45e2f7 GIT binary patch literal 708 zcmV;#0z3UjNk%w1VORhk0P_F<|NsC0_1DhM&i}@x|M!&tt#ih`d!?LX|CCDqIXV9T zIkf<_a{zMyLP7ul0RMacEC2ui09XJY000F35XecZy*TU5v+H0ej+^rVf~h(}>%MR- z&vb3urgT#4?bnT;aF&wG4>YvVZ_Ug>188 zjW{eWZw2Y_x>ql_^IJt^WM&Ro0y-*KiUR>}E?&0 z)pgt4#(*ad3k(c}w+PQF1=76KKElSYrjqpF63eyc&->5p?)CJt35@qmiiB}y^xay4 z0A0UD&{k=JmCaWxP1s;?BGhop1QY%Z`K8+v3=c71+T@u$welDMa$CxkLxQMb$O0X~ z=$xnV1UW*=XgMH2faV$%HXS6}sZ-tyG2@oOgh`aBQ5^^zBuKE7X%wd}2}u=K?m$(m zZPcjP>Zpc-w=Lev1@i=M&wJxkAar2%>{&Nb+S0HaSAkc;PftXRT8^*Z$3=SynOpd< z;TU3mHa^f7^4~^Ge8|0wc(jYrs4rKRQRKi1&YsWqJ)%qS4ATPaQr>MCF5=v(?*bse z8FuWd2F^MdX~TDK(!q774i20~k>ijLBqxyEK}g#%q)UGx9yN^Li6vmKs@=eL_ediS zhCco@ee>k03tzvTsC)R{c|<4QZL0A`pM9$haUF4x8PM5(280IEfal>>8f6GpS0N53 zyw{m_$e9ISPoa5b;xSvKsN#w&w&>!EFvck3j5O95V*~&p{xec#WOZX@WFR#$B_Kc` qcXxL#a$$3DVr6o2d1z^DY%XJOZ7*kOW_M|NVRB?HXmo9C0027!z)%eU literal 0 HcmV?d00001 diff --git a/lib/pigeon.rb b/lib/pigeon.rb index be336d8..d45c457 100644 --- a/lib/pigeon.rb +++ b/lib/pigeon.rb @@ -154,7 +154,7 @@ module Pigeon end def self.publish_draft(db, draft) - author = db.local_identity + author = db.who_am_i mhash = author.multihash template = MessageSerializer.new(draft) depth = db.get_message_count_for(mhash) @@ -173,7 +173,7 @@ module Pigeon end def self.update_draft(db, key, value) - draft = db.current_draft + draft = db.get_draft draft[key] = value db.save_draft(draft) return draft.body[key] diff --git a/lib/pigeon/database.rb b/lib/pigeon/database.rb index df5a338..2b48ed0 100644 --- a/lib/pigeon/database.rb +++ b/lib/pigeon/database.rb @@ -1,6 +1,6 @@ module Pigeon class Database - attr_reader :local_identity + attr_reader :who_am_i def initialize(path: PIGEON_DB_PATH) @store = Pigeon::Storage.new(path: path) @@ -16,10 +16,10 @@ module Pigeon def all_peers(); store.all_peers(); end # === 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 save_message(msg_obj) + def _save_message(msg_obj) store.insert_message(Helpers.verify_message(self, msg_obj)) end @@ -33,19 +33,19 @@ module Pigeon store.get_message_by_depth(multihash, depth) end - def create_message(kind, params) + def add_message(kind, params) publish_draft(new_draft(kind: kind, body: params)) end # Store a message that someone (not the LocalIdentity) # has authored. - def ingest_message(author:, - body:, - depth:, - kind:, - lipmaa:, - prev:, - signature:) + def _ingest_message(author:, + body:, + depth:, + kind:, + lipmaa:, + prev:, + signature:) msg = Message.new(author: RemoteIdentity.new(author), kind: kind, body: body, @@ -53,11 +53,11 @@ module Pigeon lipmaa: lipmaa, signature: signature, depth: depth) - save_message(msg) + _save_message(msg) end # === 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: {}) old = get_config(CURRENT_DRAFT) @@ -68,11 +68,11 @@ module Pigeon end def save_draft(draft) - set_config(CURRENT_DRAFT, draft) + add_config(CURRENT_DRAFT, draft) draft end - def current_draft + def get_draft draft = store.get_config(CURRENT_DRAFT) if draft return draft @@ -84,20 +84,20 @@ module Pigeon def update_draft(k, v); Helpers.update_draft(self, k, v); end def reset_draft - set_config(CURRENT_DRAFT, nil) + add_config(CURRENT_DRAFT, nil) end # Author a new message. - def publish_draft(draft = self.current_draft) + def publish_draft(draft = self.get_draft) Helpers.publish_draft(self, draft) end # === BUNDLES - def create_bundle(file_path = DEFAULT_BUNDLE_PATH) + def save_bundle(file_path = DEFAULT_BUNDLE_PATH) # Fetch messages for all peers - peers = all_peers + [local_identity.multihash] + peers = all_peers + [who_am_i.multihash] messages = peers.map do |peer| - find_all_messages(peer) + all_messages(peer) .map { |multihash| read_message(multihash) } .sort_by(&:depth) end.flatten @@ -114,10 +114,11 @@ module Pigeon content = messages .map { |message| message.render } .join(BUNDLE_MESSAGE_SEPARATOR) + File.join(file_path, "gossip.pgn") File.write(File.join(file_path, "gossip.pgn"), content + CR) 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")) tokens = Pigeon::Lexer.tokenize(bundle) Pigeon::Parser.parse(self, tokens) @@ -125,11 +126,11 @@ module Pigeon # === BLOBS 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 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 private @@ -139,11 +140,11 @@ module Pigeon def init_ident secret = get_config(SEED_CONFIG_KEY) if secret - @local_identity = LocalIdentity.new(secret) + @who_am_i = LocalIdentity.new(secret) else new_seed = SecureRandom.random_bytes(Ed25519::KEY_SIZE) - set_config(SEED_CONFIG_KEY, new_seed) - @local_identity = LocalIdentity.new(new_seed) + add_config(SEED_CONFIG_KEY, new_seed) + @who_am_i = LocalIdentity.new(new_seed) end end end diff --git a/lib/pigeon/parser.rb b/lib/pigeon/parser.rb index 0156069..40ea00c 100644 --- a/lib/pigeon/parser.rb +++ b/lib/pigeon/parser.rb @@ -41,7 +41,7 @@ module Pigeon def finish_this_message! @scratchpad.freeze unless @db.peer_blocked?(@scratchpad.fetch(:author)) - @results.push(@db.ingest_message(**@scratchpad)) + @results.push(@db._ingest_message(**@scratchpad)) end reset_scratchpad end diff --git a/lib/pigeon/storage.rb b/lib/pigeon/storage.rb index 711abc9..7234683 100644 --- a/lib/pigeon/storage.rb +++ b/lib/pigeon/storage.rb @@ -43,7 +43,7 @@ module Pigeon read { store[CONF_NS][key] } end - def set_config(key, value) + def add_config(key, value) write do a = store.fetch(CONF_NS) raise "FIX SAVED DRAFTS" if value.instance_variable_get(:@db) @@ -51,7 +51,7 @@ module Pigeon end end - def put_blob(data) + def add_blob(data) size = data.bytesize if (size > BLOB_BYTE_LIMIT) raise "Blob size limit is #{BLOB_BYTE_LIMIT} bytes. Got #{size}" @@ -79,7 +79,7 @@ module Pigeon read { store[COUNT_INDEX_NS][mhash] || 0 } end - def find_all_messages(author) + def all_messages(author) if author all = [] depth = -1 diff --git a/pigeon.db b/pigeon.db index 6e8b1a9e8faa796cc2d6931b770d968a50a9e40b..4636c73ccca35d280e1d51c9cf774774a9f58b58 100644 GIT binary patch delta 283 zcmdnWIE{INK|Q;t5@)chs|%YoLx_^99R9IA$vt@|4k)NfTp=qGIUU5dEk*OKjNjwgTrGh0H`9(li@i^pU7UU)-I`B`7 G3kLvDO;?lv delta 57 zcmV-90LK581GNE=FfIm3A_-GPMMMTW08}C+fR8wWyWr2jw5Y(gL%F151e4C "b" }), - db.create_message("a", { db.put_blob("two") => "b" }), - db.create_message("a", { "b" => db.put_blob("three") })] + blobs = [db.add_message(db.add_blob("one"), { "a" => "b" }), + db.add_message("a", { db.add_blob("two") => "b" }), + db.add_message("a", { "b" => db.add_blob("three") })] normal = (1..10) .to_a .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 end it "creates a bundle" do 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")) expect(expected_bundle).to eq(actual_bundle) end it "does not crash when ingesting old messages" do create_fake_messages - db.create_bundle - db.ingest_bundle + db.save_bundle + db.publish_bundle end it "does not ingest messages from blocked peers" do db.reset_database antagonist = "@PPJQ3Q36W258VQ1NKYY2G7VW24J8NMAACHXCD83GCQ3K8F4C9X2G.ed25519" db.block_peer(antagonist) - db.ingest_bundle("./spec/fixtures/x") - expect(db.find_all_messages.count).to eq(0) + db.publish_bundle("./spec/fixtures/x") + 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 diff --git a/spec/pigeon/draft_spec.rb b/spec/pigeon/draft_spec.rb index c0b624a..f900b59 100644 --- a/spec/pigeon/draft_spec.rb +++ b/spec/pigeon/draft_spec.rb @@ -12,8 +12,8 @@ RSpec.describe Pigeon::Draft do db.new_draft(kind: "unit_test") logo = File.read("./logo.png") db.update_draft("a", "bar") - db.update_draft("b", db.put_blob(logo)) - db.current_draft + db.update_draft("b", db.add_blob(logo)) + db.get_draft end MSG = [ @@ -28,7 +28,7 @@ RSpec.describe Pigeon::Draft do ].join("\n") it "renders a message" do - pk = db.local_identity.multihash + pk = db.who_am_i.multihash actual = message.render_as_draft expected = MSG.gsub("___", pk) expect(actual).to start_with(expected) @@ -37,7 +37,7 @@ RSpec.describe Pigeon::Draft do it "creates a new message" do db.reset_draft db.new_draft(kind: "unit_test") - hash = db.put_blob(File.read("./logo.png")) + hash = db.add_blob(File.read("./logo.png")) expectations = { kind: "unit_test", body: { @@ -52,7 +52,7 @@ RSpec.describe Pigeon::Draft do expect(message.kind).to eq("unit_test") expect(message.body).to eq(expectations.fetch(:body)) expectations.map do |k, v| - left = db.current_draft.send(k) + left = db.get_draft.send(k) expect(left).to eq(v) end end diff --git a/spec/pigeon/message_spec.rb b/spec/pigeon/message_spec.rb index e2936f1..9e57f6b 100644 --- a/spec/pigeon/message_spec.rb +++ b/spec/pigeon/message_spec.rb @@ -4,10 +4,10 @@ RSpec.describe Pigeon::Message do def reset_draft(params) db.reset_draft db.new_draft(kind: "unit_test", body: params) - db.current_draft + db.get_draft end - def create_message(params) + def add_message(params) draft = reset_draft(params) db.publish_draft(draft) end @@ -19,11 +19,11 @@ RSpec.describe Pigeon::Message do end 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 }) end - let(:templated_message) { create_message({ "a" => "b" }) } + let(:templated_message) { add_message({ "a" => "b" }) } let (:template) do Pigeon::MessageSerializer.new(templated_message) @@ -31,12 +31,12 @@ RSpec.describe Pigeon::Message do it "discards a draft after signing" do 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 it "creates a single message" do 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.depth).to eq(0) expect(message.kind).to eq("unit_test") @@ -79,10 +79,10 @@ RSpec.describe Pigeon::Message do end it "verifies accuracy of hash chain" do - m1 = create_message({ "a" => "b" }) - m2 = create_message({ "c" => "d" }) - m3 = create_message({ "e" => "f" }) - m4 = create_message({ "g" => "h" }) + m1 = add_message({ "a" => "b" }) + m2 = add_message({ "c" => "d" }) + m3 = add_message({ "e" => "f" }) + m4 = add_message({ "g" => "h" }) expect(m1.prev).to eq(Pigeon::NOTHING) expect(m2.prev).to be @@ -100,7 +100,7 @@ RSpec.describe Pigeon::Message do body[SecureRandom.hex(6)] = SecureRandom.hex(6) end expect do - create_message(body) + add_message(body) end.to raise_error(Pigeon::Helpers::MessageSizeError, error) end @@ -112,7 +112,7 @@ RSpec.describe Pigeon::Message do plaintext = template.render_without_signature # 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) sig1 = key1.sign(plaintext) diff --git a/spec/pigeon/parser_spec.rb b/spec/pigeon/parser_spec.rb index d5f45bc..5d19512 100644 --- a/spec/pigeon/parser_spec.rb +++ b/spec/pigeon/parser_spec.rb @@ -30,7 +30,7 @@ RSpec.describe Pigeon::Lexer do end 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.map(&:class).uniq).to eq([Pigeon::Message]) re_bundled = messages.map(&:render).join("\n\n") + "\n" diff --git a/spec/pigeon/storage_spec.rb b/spec/pigeon/storage_spec.rb index 0525a96..0058945 100644 --- a/spec/pigeon/storage_spec.rb +++ b/spec/pigeon/storage_spec.rb @@ -12,22 +12,22 @@ RSpec.describe Pigeon::Storage do end it "sets a config" do - db.set_config("FOO", "BAR") + db.add_config("FOO", "BAR") value = db.get_config("FOO") expect(value).to eq("BAR") - db.set_config("FOO", nil) + db.add_config("FOO", nil) value = db.get_config("FOO") expect(value).to eq(nil) end it "manages configs" do - db.set_config("FOO", "BAR") + db.add_config("FOO", "BAR") value = db.get_config("FOO") expect(value).to eq("BAR") end 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) end @@ -48,27 +48,27 @@ RSpec.describe Pigeon::Storage do end 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 - actual_messages = db.find_all_messages(author) - search_results = db.find_all_messages(author) + actual_messages = db.all_messages(author) + search_results = db.all_messages(author) end it "finds all messages" do msgs = [ - db.create_message("strings", { + db.add_message("strings", { "example_1.1" => "This is a string.", "example=_." => "A second string.", }), - db.create_message("d", { - "e" => db.put_blob(File.read("./logo.png")), + db.add_message("d", { + "e" => db.add_blob(File.read("./logo.png")), }), - db.create_message("g", { - "me_myself_and_i" => db.local_identity.multihash, + db.add_message("g", { + "me_myself_and_i" => db.who_am_i.multihash, }), ] - me = db.local_identity.multihash - results = db.find_all_messages(me) + me = db.who_am_i.multihash + results = db.all_messages(me) expect(results.length).to eq(3) expect(msgs[0].multihash).to eq(results[0]) expect(msgs[1].multihash).to eq(results[1]) diff --git a/tutorial.rb b/tutorial.rb index 52ffb22..00f0319 100644 --- a/tutorial.rb +++ b/tutorial.rb @@ -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" - -db = Pigeon::Database.new(path: "my.db") - -db.reset_draft -db.current_draft -db.reset_draft -db.publish_draft -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 +files = %w(a.gif b.gif c.gif) +body = { "what" => "A simple bundle with a few blobs" } +db = Pigeon::Database.new(path: "new.db") +db.add_message("description", body) +files.map { |file| db.add_blob(file) } +binding.pry +db.save_bundle("./spec/fixtures/has_blobs")