From c10b809193975fd73c402adcaecb256e289eaf18 Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Tue, 2 Jun 2020 08:53:42 -0500 Subject: [PATCH] TODO: Continue removing footer / renaming sigils. 33 examples, 17 failures --- lib/pigeon.rb | 13 +++-------- lib/pigeon/draft.rb | 2 +- lib/pigeon/lexer.rb | 4 ++-- lib/pigeon/local_identity.rb | 5 ++-- lib/pigeon/message.rb | 2 +- lib/pigeon/storage.rb | 2 +- .../WMG051B/1QW5SXM/N2RQHF2/AND6J8V.GPG | Bin .../DBHTZJ5/JVVP5TC/KP0605W/WXYJG4V.MRG | Bin .../VVT9DXM/CHE0XJW/BZHT2CQ/29S5SEP.CSG | Bin .../has_blobs/messages.pgn | 0 .../normal/messages.pgn | 0 .../{fixtures => old_fixtures}/x/messages.pgn | 0 spec/pigeon/bundle_spec.rb | 2 +- spec/pigeon/draft_spec.rb | 7 ++---- spec/pigeon/lexer_spec.rb | 22 +++++++++--------- spec/pigeon/local_identity_spec.rb | 9 ++----- spec/pigeon/message_spec.rb | 7 +++--- spec/pigeon/parser_spec.rb | 4 ++-- spec/pigeon/storage_spec.rb | 4 ++-- 19 files changed, 33 insertions(+), 50 deletions(-) rename spec/{fixtures => old_fixtures}/has_blobs/622PRNJ/7C0S05X/R2AHDPK/WMG051B/1QW5SXM/N2RQHF2/AND6J8V.GPG (100%) rename spec/{fixtures => old_fixtures}/has_blobs/FV0FJ0Y/ZADY7C5/JTTFYPK/DBHTZJ5/JVVP5TC/KP0605W/WXYJG4V.MRG (100%) rename spec/{fixtures => old_fixtures}/has_blobs/YPF11E5/N9JFVB6/KB1N1WD/VVT9DXM/CHE0XJW/BZHT2CQ/29S5SEP.CSG (100%) rename spec/{fixtures => old_fixtures}/has_blobs/messages.pgn (100%) rename spec/{fixtures => old_fixtures}/normal/messages.pgn (100%) rename spec/{fixtures => old_fixtures}/x/messages.pgn (100%) diff --git a/lib/pigeon.rb b/lib/pigeon.rb index 061f390..9c0d108 100644 --- a/lib/pigeon.rb +++ b/lib/pigeon.rb @@ -46,10 +46,8 @@ module Pigeon BLOB_SIGIL = "FILE." MESSAGE_SIGIL = "TEXT." - IDENTITY_SIGIL = "TEXT." + IDENTITY_SIGIL = "USER." STRING_SIGIL = "\"" - IDENTITY_FOOTER = ".ed25519" - SIG_FOOTER = ".sig.ed25519" # Error messages PREV_REQUIRES_SAVE = "Can't fetch `prev` on unsaved messages" @@ -61,8 +59,6 @@ module Pigeon RUNAWAY_LOOP = "RUNAWAY LOOP DETECTED" # Constants for internal use only: - FOOTERS_REGEX = Regexp.new("#{SIG_FOOTER}|#{IDENTITY_FOOTER}") - SIG_RANGE = (SIG_FOOTER.length * -1)..-1 BLOB_BYTE_LIMIT = 360_000 class Helpers @@ -270,11 +266,8 @@ module Pigeon end def self.decode_multihash(string) - if string[SIG_RANGE] == SIG_FOOTER - return b32_decode(string.gsub(SIG_FOOTER, "")) - else - return b32_decode(string[1..].gsub(FOOTERS_REGEX, "")) - end + # "FEED.", "FILE.", "USER." etc.. + return b32_decode(string[5..]) end end end diff --git a/lib/pigeon/draft.rb b/lib/pigeon/draft.rb index 799163d..2f3d4af 100644 --- a/lib/pigeon/draft.rb +++ b/lib/pigeon/draft.rb @@ -23,7 +23,7 @@ module Pigeon def []=(key, value) raise STRING_KEYS_ONLY unless key.is_a?(String) - case value[0] + case value[0..4] when BLOB_SIGIL, MESSAGE_SIGIL, IDENTITY_SIGIL, STRING_SIGIL body[key] = value else diff --git a/lib/pigeon/lexer.rb b/lib/pigeon/lexer.rb index 145630d..6fe1dbc 100644 --- a/lib/pigeon/lexer.rb +++ b/lib/pigeon/lexer.rb @@ -58,7 +58,7 @@ module Pigeon # TODO: Create regexes using string and Regexp.new() for cleaner regexes. NUMERIC = /\d{1,7}/ NULL_VALUE = /NONE/ - FEED_VALUE = /FEED.{52}/ + FEED_VALUE = /USER.{52}/ MESG_VALUE = /TEXT.{52}/ BLOB_VALUE = /FILE.{52}/ STRG_VALUE = /".{1,128}"/ @@ -80,7 +80,7 @@ module Pigeon PREV = /prev (#{MESG_VALUE}|#{NULL_VALUE})\n/ KIND = /kind #{ALPHANUMERICISH}\n/ BODY_ENTRY = /#{ALPHANUMERICISH}:#{ANY_VALUE}\n/ - FOOTER_ENTRY = /signature .*{103}\.sig\.ed25519\n?/ + FOOTER_ENTRY = /signature .*{103}\n?/ LEXER_STATES = [HEADER = :header, BODY = :body, FOOTER = :footer] diff --git a/lib/pigeon/local_identity.rb b/lib/pigeon/local_identity.rb index 29b3bb2..341f7c6 100644 --- a/lib/pigeon/local_identity.rb +++ b/lib/pigeon/local_identity.rb @@ -21,13 +21,12 @@ module Pigeon bytes = @signing_key.verify_key.to_bytes b64 = Helpers.b32_encode(bytes) - @multihash ||= [IDENTITY_SIGIL, b64, IDENTITY_FOOTER].join("") + @multihash ||= [IDENTITY_SIGIL, b64].join("") end def sign(string) hex = @signing_key.sign(string) - b64 = Helpers.b32_encode(hex) - b64 + SIG_FOOTER + Helpers.b32_encode(hex) end end end diff --git a/lib/pigeon/message.rb b/lib/pigeon/message.rb index 111f755..19aa224 100644 --- a/lib/pigeon/message.rb +++ b/lib/pigeon/message.rb @@ -12,7 +12,7 @@ module Pigeon tpl = render digest = Digest::SHA256.digest(tpl) sha256 = Helpers.b32_encode(digest) - "#{MESSAGE_SIGIL}#{sha256}#{BLOB_FOOTER}" + "#{MESSAGE_SIGIL}#{sha256}" end def initialize(author:, diff --git a/lib/pigeon/storage.rb b/lib/pigeon/storage.rb index b0fa22a..97cebd7 100644 --- a/lib/pigeon/storage.rb +++ b/lib/pigeon/storage.rb @@ -60,7 +60,7 @@ module Pigeon raw_digest = Digest::SHA256.digest(data) b32_hash = Helpers.b32_encode(raw_digest) - multihash = [BLOB_SIGIL, b32_hash, BLOB_FOOTER].join("") + multihash = "#{BLOB_SIGIL}#{b32_hash}" write_to_disk(multihash, data) multihash end diff --git a/spec/fixtures/has_blobs/622PRNJ/7C0S05X/R2AHDPK/WMG051B/1QW5SXM/N2RQHF2/AND6J8V.GPG b/spec/old_fixtures/has_blobs/622PRNJ/7C0S05X/R2AHDPK/WMG051B/1QW5SXM/N2RQHF2/AND6J8V.GPG similarity index 100% rename from spec/fixtures/has_blobs/622PRNJ/7C0S05X/R2AHDPK/WMG051B/1QW5SXM/N2RQHF2/AND6J8V.GPG rename to spec/old_fixtures/has_blobs/622PRNJ/7C0S05X/R2AHDPK/WMG051B/1QW5SXM/N2RQHF2/AND6J8V.GPG diff --git a/spec/fixtures/has_blobs/FV0FJ0Y/ZADY7C5/JTTFYPK/DBHTZJ5/JVVP5TC/KP0605W/WXYJG4V.MRG b/spec/old_fixtures/has_blobs/FV0FJ0Y/ZADY7C5/JTTFYPK/DBHTZJ5/JVVP5TC/KP0605W/WXYJG4V.MRG similarity index 100% rename from spec/fixtures/has_blobs/FV0FJ0Y/ZADY7C5/JTTFYPK/DBHTZJ5/JVVP5TC/KP0605W/WXYJG4V.MRG rename to spec/old_fixtures/has_blobs/FV0FJ0Y/ZADY7C5/JTTFYPK/DBHTZJ5/JVVP5TC/KP0605W/WXYJG4V.MRG diff --git a/spec/fixtures/has_blobs/YPF11E5/N9JFVB6/KB1N1WD/VVT9DXM/CHE0XJW/BZHT2CQ/29S5SEP.CSG b/spec/old_fixtures/has_blobs/YPF11E5/N9JFVB6/KB1N1WD/VVT9DXM/CHE0XJW/BZHT2CQ/29S5SEP.CSG similarity index 100% rename from spec/fixtures/has_blobs/YPF11E5/N9JFVB6/KB1N1WD/VVT9DXM/CHE0XJW/BZHT2CQ/29S5SEP.CSG rename to spec/old_fixtures/has_blobs/YPF11E5/N9JFVB6/KB1N1WD/VVT9DXM/CHE0XJW/BZHT2CQ/29S5SEP.CSG diff --git a/spec/fixtures/has_blobs/messages.pgn b/spec/old_fixtures/has_blobs/messages.pgn similarity index 100% rename from spec/fixtures/has_blobs/messages.pgn rename to spec/old_fixtures/has_blobs/messages.pgn diff --git a/spec/fixtures/normal/messages.pgn b/spec/old_fixtures/normal/messages.pgn similarity index 100% rename from spec/fixtures/normal/messages.pgn rename to spec/old_fixtures/normal/messages.pgn diff --git a/spec/fixtures/x/messages.pgn b/spec/old_fixtures/x/messages.pgn similarity index 100% rename from spec/fixtures/x/messages.pgn rename to spec/old_fixtures/x/messages.pgn diff --git a/spec/pigeon/bundle_spec.rb b/spec/pigeon/bundle_spec.rb index 58bd8cc..d60bdae 100644 --- a/spec/pigeon/bundle_spec.rb +++ b/spec/pigeon/bundle_spec.rb @@ -40,7 +40,7 @@ RSpec.describe Pigeon::Message do it "does not ingest messages from blocked peers" do db.reset_database - antagonist = "TEXT.YDVX7JWTVNRFEVYC8E8DS9MVWW9KB66F1XQYMNB2FQ6QBPXKAQX0.ed25519" + antagonist = "TEXT.YDVX7JWTVNRFEVYC8E8DS9MVWW9KB66F1XQYMNB2FQ6QBPXKAQX0" db.block_peer(antagonist) db.import_bundle(BLOCKED_PEER_FIXTURE_PATH) expect(db.all_messages.count).to eq(0) diff --git a/spec/pigeon/draft_spec.rb b/spec/pigeon/draft_spec.rb index 0baa6e6..2faa83a 100644 --- a/spec/pigeon/draft_spec.rb +++ b/spec/pigeon/draft_spec.rb @@ -23,7 +23,7 @@ RSpec.describe Pigeon::Draft do "lipmaa DRAFT", "prev DRAFT", "\na:\"bar\"", - "b:&CHHABX8Q9D9Q0BY2BBZ6FA7SMAFNE9GGMSDTZVZZC9TK2N9F15QG.sha256", + "b:FILE.CHHABX8Q9D9Q0BY2BBZ6FA7SMAFNE9GGMSDTZVZZC9TK2N9F15QG", "\n", ].join("\n") @@ -40,10 +40,7 @@ RSpec.describe Pigeon::Draft do hash = db.add_blob(File.read("./logo.png")) expectations = { kind: "unit_test", - body: { - "a" => "bar".to_json, - "b" => hash, - }, + body: { "a" => "bar".to_json, "b" => hash }, } db.update_draft("a", "bar") db.update_draft("b", hash) diff --git a/spec/pigeon/lexer_spec.rb b/spec/pigeon/lexer_spec.rb index e7a7004..9209bb3 100644 --- a/spec/pigeon/lexer_spec.rb +++ b/spec/pigeon/lexer_spec.rb @@ -2,7 +2,7 @@ require "spec_helper" RSpec.describe Pigeon::Lexer do EXPECTED_TOKENS1 = [ - [:AUTHOR, "TEXT.3DWXGXHXCB02WV1TEA47J43HHTTBNMM496ANME7FZ2SYPGA9KTZG.ed25519", 69], + [:AUTHOR, "TEXT.3DWXGXHXCB02WV1TEA47J43HHTTBNMM496ANME7FZ2SYPGA9KTZG", 69], [:DEPTH, 0, 77], [:KIND, "unit_test1", 93], [:LIPMAA, "NONE", 105], @@ -10,32 +10,32 @@ RSpec.describe Pigeon::Lexer do [:HEADER_END, 116], [:BODY_ENTRY, "foo", "\"bar\"", 126], [:BODY_END, 127], - [:SIGNATURE, "2BTX69F6E30BBDNQ0XTT20NCG8C0B393SGQSW5M00G8KF33CAE1YB1MPT760KSTRV2ZJCCNJ883JXEWTTTEEJ8JBHNWEJQFSZ035P0R.sig.ed25519", 253], + [:SIGNATURE, "2BTX69F6E30BBDNQ0XTT20NCG8C0B393SGQSW5M00G8KF33CAE1YB1MPT760KSTRV2ZJCCNJ883JXEWTTTEEJ8JBHNWEJQFSZ035P0R", 253], [:MESSAGE_DELIM, 254], - [:AUTHOR, "TEXT.3DWXGXHXCB02WV1TEA47J43HHTTBNMM496ANME7FZ2SYPGA9KTZG.ed25519", 323], + [:AUTHOR, "TEXT.3DWXGXHXCB02WV1TEA47J43HHTTBNMM496ANME7FZ2SYPGA9KTZG", 323], [:DEPTH, 1, 331], [:KIND, "unit_test2", 347], [:LIPMAA, "NONE", 359], - [:PREV, "TEXT.RW61BRVRAAM31RFPQ8W6MTYBN840Y898MQ2GTDRSMQES84RPJKHG.sha256", 425], + [:PREV, "TEXT.RW61BRVRAAM31RFPQ8W6MTYBN840Y898MQ2GTDRSMQES84RPJKHG", 425], [:HEADER_END, 426], [:BODY_ENTRY, "bar", "\"baz\"", 436], [:BODY_END, 437], - [:SIGNATURE, "TXC15FZZVK30Q5ZRERFR9VXAJ8KKE58ZGF1JEBNETJN1MHN9EGRQJP7PX99NBZMX177XZWE3M2PCPPF4VBN4J93W2H5FTNJ7K7VG818.sig.ed25519", 563], + [:SIGNATURE, "TXC15FZZVK30Q5ZRERFR9VXAJ8KKE58ZGF1JEBNETJN1MHN9EGRQJP7PX99NBZMX177XZWE3M2PCPPF4VBN4J93W2H5FTNJ7K7VG818", 563], [:MESSAGE_DELIM, 564], - [:AUTHOR, "TEXT.3DWXGXHXCB02WV1TEA47J43HHTTBNMM496ANME7FZ2SYPGA9KTZG.ed25519", 633], + [:AUTHOR, "TEXT.3DWXGXHXCB02WV1TEA47J43HHTTBNMM496ANME7FZ2SYPGA9KTZG", 633], [:DEPTH, 2, 641], [:KIND, "unit_test3", 657], [:LIPMAA, "NONE", 669], - [:PREV, "TEXT.CSX0CDPY96DGTGT9V0TNZJ4S84JTSK4AYNE193VXF8AH9ZJHT82G.sha256", 735], + [:PREV, "TEXT.CSX0CDPY96DGTGT9V0TNZJ4S84JTSK4AYNE193VXF8AH9ZJHT82G", 735], [:HEADER_END, 736], [:BODY_ENTRY, "cats", "\"meow\"", 748], [:BODY_END, 749], - [:SIGNATURE, "91TBR3H90720KGA8FPSSEPHB1R6QGZ0YGTC2T6RT1GBWV9TNR95CWHF0KB4P57RMJQPSC6EA6D5FDN5PC8VM7V8BC32F17V9R9VDR0G.sig.ed25519", 875], + [:SIGNATURE, "91TBR3H90720KGA8FPSSEPHB1R6QGZ0YGTC2T6RT1GBWV9TNR95CWHF0KB4P57RMJQPSC6EA6D5FDN5PC8VM7V8BC32F17V9R9VDR0G", 875], [:MESSAGE_DELIM, 875], ].freeze MESSAGE_LINES = [ - "author @VG44QCHKA38E7754RQ5DAFBMMD2CCZQRZ8BR2J4MRHHGVTHGW670.ed25519", + "author @VG44QCHKA38E7754RQ5DAFBMMD2CCZQRZ8BR2J4MRHHGVTHGW670", "depth 0", "kind unit_test", "lipmaa NONE", @@ -43,7 +43,7 @@ RSpec.describe Pigeon::Lexer do "", "foo:\"bar\"", "", - "signature hHvhdvUcrabhFPz52GSGa9_iuudOsGEEE7S0o0WJLqjQyhLfgUy72yppHXsG6T4E21p6EEI6B3yRcjfurxegCA==.sig.ed25519", + "signature hHvhdvUcrabhFPz52GSGa9_iuudOsGEEE7S0o0WJLqjQyhLfgUy72yppHXsG6T4E21p6EEI6B3yRcjfurxegCA==", ].freeze let(:db) do @@ -86,7 +86,7 @@ RSpec.describe Pigeon::Lexer do expect(hash[:DEPTH]).to eq(message.depth) expect(hash[:KIND]).to eq(message.kind) expect(hash[:PREV]).to eq Pigeon::NOTHING - expect(hash[:SIGNATURE]).to eq(message.signature) + expect(hash[:SIGNATURE]).to eq(messagenature) end it "catches syntax errors" do diff --git a/spec/pigeon/local_identity_spec.rb b/spec/pigeon/local_identity_spec.rb index d75bdce..5edb722 100644 --- a/spec/pigeon/local_identity_spec.rb +++ b/spec/pigeon/local_identity_spec.rb @@ -9,14 +9,13 @@ RSpec.describe Pigeon::LocalIdentity do HELLO_SIGNATURE = [ "FARSW9ENM9DK1JD4M9ES1D4WWVG5SXT8Z6VXT6HXRV17M4Q9X5W2", "T5Y7ZZC0C5JYBTMBQ2HAQBRGWGAK42PK3BHQXAX1FPTKBFJQJ1R", - ".sig.ed25519", ].join("") it "signs arbitrary data" do expect(kp.sign("hello")).to eq(HELLO_SIGNATURE) end it "generates a pair from a seed" do - x = "TEXT.XSZY1ME6QMA5BBSJ8QSDJCSG6EVDTCKYNMV221SB7B2NZR5K09J0.ed25519" + x = "USER.XSZY1ME6QMA5BBSJ8QSDJCSG6EVDTCKYNMV221SB7B2NZR5K09J0" expect(kp.multihash).to eq(x) y = "2PRTG7F13HWF1HPW9FF9NDSYGSQS5VXQ2WMZY0A510J64AE9G840" expect(kp.private_key).to eq(y) @@ -24,11 +23,7 @@ RSpec.describe Pigeon::LocalIdentity do it "strips headers" do whatever = "af697f3063d46fe9546f651c08c378f8" - example = [ - Pigeon::IDENTITY_SIGIL, - whatever, - Pigeon::IDENTITY_FOOTER, - ].join("") + example = [Pigeon::IDENTITY_SIGIL, whatever].join("") result = Pigeon::Helpers.decode_multihash(example) expect(result).to eq(Pigeon::Helpers.b32_decode(whatever)) end diff --git a/spec/pigeon/message_spec.rb b/spec/pigeon/message_spec.rb index 1f14a2f..5130984 100644 --- a/spec/pigeon/message_spec.rb +++ b/spec/pigeon/message_spec.rb @@ -42,7 +42,6 @@ RSpec.describe Pigeon::Message do expect(message.depth).to eq(0) expect(message.kind).to eq("unit_test") expect(message.prev).to eq(Pigeon::NOTHING) - expect(message.signature.include?(Pigeon::SIG_FOOTER)).to eq(true) expect(message.signature.length).to be > 99 actual = message.render expected = [ @@ -124,8 +123,8 @@ RSpec.describe Pigeon::Message do combinations = [[key1, sig1], [key1, sig2], [key2, sig1], [key2, sig2]] combinations.map { |(key, sig)| key.verify_key.verify(sig, plaintext) } - sig1_b64 = Pigeon::Helpers.b32_encode(sig1) + Pigeon::SIG_FOOTER - sig2_b64 = Pigeon::Helpers.b32_encode(sig2) + Pigeon::SIG_FOOTER + sig1_b64 = Pigeon::Helpers.b32_encode(sig1) + sig2_b64 = Pigeon::Helpers.b32_encode(sig2) expect(message.signature).to eq(sig1_b64) expect(message.signature).to eq(sig2_b64) end @@ -139,7 +138,7 @@ RSpec.describe Pigeon::Message do [:LIPMAA, "TEXT.4PE7S4XCCAYPQ42S98K730CEW6ME5HRWJKHHEGYVYPFHSJWXEY1G"], [:HEADER_END], [:BODY_ENTRY, "duplicate", "This key is a duplicate."], - [:SIGNATURE, "DN7yPTE-m433ND3jBL4oM23XGxBKafjq0Dp9ArBQa_TIGU7DmCxTumieuPBN-NKxlx_0N7-c5zjLb5XXVHYPCQ==.sig.ed25519"], + [:SIGNATURE, "DN7yPTE-m433ND3jBL4oM23XGxBKafjq0Dp9ArBQa_TIGU7DmCxTumieuPBN-NKxlx_0N7-c5zjLb5XXVHYPCQ=="], [:MESSAGE_DELIM], ] e = Pigeon::Helpers::VerificationError diff --git a/spec/pigeon/parser_spec.rb b/spec/pigeon/parser_spec.rb index 35a6e7a..534a49d 100644 --- a/spec/pigeon/parser_spec.rb +++ b/spec/pigeon/parser_spec.rb @@ -10,7 +10,7 @@ RSpec.describe Pigeon::Lexer do let(:tokens) { Pigeon::Lexer.tokenize(example_bundle) } BAD_TOKENS = [ - [:AUTHOR, "TEXT.DYdgK1KUInVtG3lS45hA1HZ-jTuvfLKsxDpXPFCve04=.ed25519"], + [:AUTHOR, "FEED.DYdgK1KUInVtG3lS45hA1HZ-jTuvfLKsxDpXPFCve04="], [:KIND, "invalid"], [:PREV, "NONE"], [:DEPTH, 0], @@ -18,7 +18,7 @@ RSpec.describe Pigeon::Lexer do [:HEADER_END], [:BODY_ENTRY, "duplicate", "Pigeon does not allow duplicate keys."], [:BODY_ENTRY, "duplicate", "This key is a duplicate."], - [:SIGNATURE, "DN7yPTE-m433ND3jBL4oM23XGxBKafjq0Dp9ArBQa_TIGU7DmCxTumieuPBN-NKxlx_0N7-c5zjLb5XXVHYPCQ==.sig.ed25519"], + [:SIGNATURE, "DN7yPTE-m433ND3jBL4oM23XGxBKafjq0Dp9ArBQa_TIGU7DmCxTumieuPBN-NKxlx_0N7-c5zjLb5XXVHYPCQ=="], [:MESSAGE_DELIM], ].freeze diff --git a/spec/pigeon/storage_spec.rb b/spec/pigeon/storage_spec.rb index b0b576e..621deff 100644 --- a/spec/pigeon/storage_spec.rb +++ b/spec/pigeon/storage_spec.rb @@ -2,8 +2,8 @@ require "spec_helper" RSpec.describe Pigeon::Storage do LOGO_BLOB = File.read("./logo.png") - IDS = %w[@ZMWM5PSXRN7RFRMSWW1E3V5DNGC4XGGJTHKCAGB48SNRG4XXE5NG.ed25519 - @VF0Q4KXQNY6WCAXF17GAZGDPAX8XKM70SB8N7V0NSD1H370ZCJBG.ed25519].freeze + IDS = %w[USER.ZMWM5PSXRN7RFRMSWW1E3V5DNGC4XGGJTHKCAGB48SNRG4XXE5NG + USER.VF0Q4KXQNY6WCAXF17GAZGDPAX8XKM70SB8N7V0NSD1H370ZCJBG].freeze let(:db) do db = Pigeon::Database.new