README updates

This commit is contained in:
Netscape Navigator 2020-04-09 08:13:23 -05:00
commit d54b04bdaf
6 changed files with 66 additions and 54 deletions

View File

@ -50,7 +50,12 @@ Eg: `pigeon identity show` becomes `./pigeon-cli show`.
- [X] Fix diagram in spec doc
- [X] refactor `Bundle.create` to use `message find-all`.
- [X] Rename `message find` to `message read`, since other finders return a multihash.
<<<<<<< HEAD
- [ ] Move stuff involving `LocalIdentity` out of `Message` class and into `Draft` class (re-use lexer logic)?
=======
- [ ] Message.ingest should be the only code path to message authoring.
- [ ] Make all methods private except those required for the CLI.
>>>>>>> draft_refactor
- [ ] Don't allow any type of whitespace in `kind` or `string` keys. Write a test for this.
- [ ] Add Lipmaa links like the Bamboo folks do.
- [ ] Create regexes in ::Lexer using strings and Regexp.new() for cleaner regexes.
@ -71,6 +76,11 @@ Eg: `pigeon identity show` becomes `./pigeon-cli show`.
- [ ] Update spec document CLI usage examples to reflect API changes in 2020.
- [ ] Performance benchmarks (Do this second to last!)
- [ ] Performance tuning (Do this last!)
- [ ] Set a max message size of 4k
# Do this later
- [ ] Interest and Disinterest Signalling for document routing: Create a `$gossip` message to express `blob.have`, `blob.want` and to note last message received of a peer. This can steer bundle creation and an eventual `--for` flag at bundle creation time.
# Idea Bin
- [ ] Map/reduce plugin support for custom indices?

2
dist/pigeon.rb vendored
View File

@ -111,7 +111,7 @@ module Pigeon
def self.create_message(kind, params)
draft = Pigeon::Draft.create(kind: kind)
params.map { |(k, v)| draft[k] = v }
Pigeon::Message.publish(draft)
draft.publish
end
def self.verify_string(identity, string_signature, string)

30
dist/pigeon/draft.rb vendored
View File

@ -2,7 +2,8 @@ require "digest"
module Pigeon
class Draft
attr_reader :kind, :body, :internal_id
attr_reader :signature, :prev, :kind, :internal_id,
:depth, :body, :author
def self.create(kind:, body: {})
self.new(kind: kind, body: body).save
@ -23,8 +24,12 @@ module Pigeon
end
def initialize(kind:, body: {})
@signature = Pigeon::EMPTY_MESSAGE
@prev = Pigeon::EMPTY_MESSAGE
@kind = kind
@depth = -1
@body = body
@author = Pigeon::EMPTY_MESSAGE
@internal_id = SecureRandom.uuid
end
@ -49,12 +54,35 @@ module Pigeon
end
def save
puts "Rename to `save_as_draft` to avoid confusion"
Pigeon::Storage.current.set_config(CURRENT_DRAFT, self)
self
end
# Author a new message.
def publish
template = MessageSerializer.new(self)
@author = LocalIdentity.current
@depth = store.get_message_count_for(author.multihash)
@prev = store.get_message_by_depth(author.multihash, @depth - 1)
@signature = author.sign(template.render_without_signature)
candidate = template.render
tokens = Lexer.tokenize(candidate)
message = Parser.parse(tokens)[0]
self.discard
message
end
def render
puts "Rename to `render_as_draft` to avoid confusion."
puts "Do we even need DraftSerializer any more?"
DraftSerializer.new(self).render
end
def store
Pigeon::Storage.current
end
end
end

View File

@ -7,23 +7,6 @@ module Pigeon
class VerificationError < StandardError; end
VERFIY_ERROR = "Expected field `%s` to equal %s, got: %s"
# Author a new message.
def self.publish(draft)
author = LocalIdentity.current
depth = Pigeon::Storage
.current
.get_message_count_for(author.multihash)
count = store.get_message_count_for(author.multihash)
prev = store.get_message_by_depth(author.multihash, count - 1)
msg = self.new(author: author,
kind: draft.kind,
body: draft.body,
depth: depth,
prev: prev)
msg.save!
draft.discard
msg
end
# Store a message that someone (not the LocalIdentity)
# has authored.
@ -33,7 +16,7 @@ module Pigeon
body: body,
prev: prev,
signature: signature,
depth: depth)
depth: depth).save!
end
def render
@ -41,13 +24,15 @@ module Pigeon
end
def multihash
sha256 = Helpers.b32_encode(Digest::SHA256.digest(self.render))
tpl = self.render
digest = Digest::SHA256.digest(tpl)
sha256 = Helpers.b32_encode(digest)
"#{MESSAGE_SIGIL}#{sha256}#{BLOB_FOOTER}"
end
def save!
puts "TODO: Make this method private."
return store.read_message(multihash) if store.message?(multihash)
calculate_signature
verify_depth_prev_and_depth
verify_signature
self.freeze
@ -86,22 +71,12 @@ module Pigeon
@signature = signature
end
def calculate_signature
return if @signature
#TODO: Verify that the author is Pigeon::LocalIdentity.current?
@signature = author.sign(template.render_without_signature)
end
def template
MessageSerializer.new(self)
end
def self.store
Pigeon::Storage.current
end
def store
self.class.store
Pigeon::Storage.current
end
end
end

View File

@ -108,7 +108,7 @@ RSpec.describe Pigeon::Lexer do
let(:message) do
draft = Pigeon::Draft.create(kind: "unit_test")
draft["foo"] = "bar"
Pigeon::Message.publish(draft)
draft.publish
end
before(:each) do

View File

@ -14,7 +14,7 @@ RSpec.describe Pigeon::Message do
def create_message(params)
draft = create_draft(params)
Pigeon::Message.publish(draft)
draft.publish
end
let(:draft) do
@ -29,13 +29,13 @@ RSpec.describe Pigeon::Message do
it "discards a draft after signing" do
expect(draft.internal_id).to eq(Pigeon::Draft.current.internal_id)
Pigeon::Message.publish(draft)
draft.publish
expect { Pigeon::Draft.current }.to raise_error("NO DRAFT FOUND")
end
it "creates a single message" do
message = Pigeon::Message.publish(draft)
expect(message.author).to eq(Pigeon::LocalIdentity.current)
message = draft.publish
expect(message.author.multihash).to eq(Pigeon::LocalIdentity.current.multihash)
expect(message.body).to eq(draft.body)
expect(message.depth).to eq(0)
expect(message.kind).to eq("unit_test")
@ -64,7 +64,7 @@ RSpec.describe Pigeon::Message do
0.upto(4) do |expected_depth|
draft1 = Pigeon::Draft.create(kind: "unit_test")
draft1["description"] = "Message number #{expected_depth}"
message = Pigeon::Message.publish(draft1)
message = draft1.publish
all.push(message)
expect(message.depth).to eq(expected_depth)
if expected_depth == 0
@ -120,18 +120,19 @@ RSpec.describe Pigeon::Message do
end
it "crashes on forged fields" do
msg = Pigeon::Parser.parse([
[:AUTHOR, "@DYdgK1KUInVtG3lS45hA1HZ-jTuvfLKsxDpXPFCve04=.ed25519"],
[:KIND, "invalid"],
[:PREV, "NONE"],
[:DEPTH, 10],
[:HEADER_END],
[:BODY_ENTRY, "duplicate", "This key is a duplicate."],
[:SIGNATURE, "DN7yPTE-m433ND3jBL4oM23XGxBKafjq0Dp9ArBQa_TIGU7DmCxTumieuPBN-NKxlx_0N7-c5zjLb5XXVHYPCQ==.sig.ed25519"],
[:MESSAGE_END],
])
m = "Expected field `depth` to equal 0, got: 10"
expect { msg.first.save! }.to raise_error(Pigeon::Message::VerificationError, m)
expect do
Pigeon::Parser.parse([
[:AUTHOR, "@DYdgK1KUInVtG3lS45hA1HZ-jTuvfLKsxDpXPFCve04=.ed25519"],
[:KIND, "invalid"],
[:PREV, "NONE"],
[:DEPTH, 10],
[:HEADER_END],
[:BODY_ENTRY, "duplicate", "This key is a duplicate."],
[:SIGNATURE, "DN7yPTE-m433ND3jBL4oM23XGxBKafjq0Dp9ArBQa_TIGU7DmCxTumieuPBN-NKxlx_0N7-c5zjLb5XXVHYPCQ==.sig.ed25519"],
[:MESSAGE_END],
]).first.save!
end.to raise_error(Pigeon::Message::VerificationError, m)
end
# Every ASCII character that is not a letter:
@ -143,8 +144,7 @@ RSpec.describe Pigeon::Message do
kind[rand(0...8)] = n
draft = Pigeon::Draft.create(kind: kind)
draft["body"] = "empty"
tpl = Pigeon::Message.publish(draft).render
boom = ->() { Pigeon::Lexer.tokenize(tpl) }
boom = ->() { Pigeon::Lexer.tokenize(draft.publish.render) }
expect(boom).to raise_error(Pigeon::Lexer::LexError)
end
end
@ -155,8 +155,7 @@ RSpec.describe Pigeon::Message do
key = SecureRandom.alphanumeric(8)
key[rand(0...8)] = n
draft[key] = "should crash"
tpl = Pigeon::Message.publish(draft).render
boom = ->() { Pigeon::Lexer.tokenize(tpl) }
boom = ->() { Pigeon::Lexer.tokenize(draft.publish.render) }
expect(boom).to raise_error(Pigeon::Lexer::LexError)
end
end