WIP. TODO: Make sure client is ingesting blobs in a bundle
This commit is contained in:
parent
e087888e94
commit
8fed4dc0bc
|
@ -0,0 +1,60 @@
|
||||||
|
=> [32m#<Pigeon::Database:0x0000559bd1590cc8[0m
|
||||||
|
@who_am_i[32m=[0m[32m#<Pigeon::LocalIdentity:0x0000559bd15d1890[0m @seed[32m=[0m[31m[1;31m"[0m[31m[1;35m\x1F[0m[31mL^9[1;35m\x90[0m[31me[1;35m\xF8[0m[31mg[1;35m\xF2[0m[31m[1;35m\x83[0m[31m[1;35m\xB4[0m[31m[1;35m\xC4[0m[31m>c[1;35m\x85[0m[31m[1;35m\xAE[0m[31m2w[1;35m\xBA[0m[31m&,@[1;35m\xD3[0m[31m[1;35m\x96[0m[31m[1;35m\xCA[0m[31mlO*[1;35m\xB9[0m[31m[1;35m\x8D[0m[31mkX[1;31m"[0m[31m[0m, @signing_key[32m=[0m[32m#<Ed25519::SigningKey:0x0000559bd15d17c8>[0m[32m>[0m,
|
||||||
|
@store[32m=[0m
|
||||||
|
[32m#<Pigeon::Storage:0x0000559bd15909f8[0m
|
||||||
|
@path[32m=[0m[31m[1;31m"[0m[31mold.db[1;31m"[0m[31m[0m,
|
||||||
|
@store[32m=[0m
|
||||||
|
[32m#<PStore:0x0000559bd1590458[0m
|
||||||
|
@abort[32m=[0m[1;36mfalse[0m,
|
||||||
|
@filename[32m=[0m[31m[1;31m"[0m[31mpigeon.db[1;31m"[0m[31m[0m,
|
||||||
|
@lock[32m=[0m[32m#<Thread::Mutex:0x0000559bd1597988[0m[32m>[0m,
|
||||||
|
@rdonly[32m=[0m[1;36mtrue[0m,
|
||||||
|
@table[32m=[0m
|
||||||
|
{[31m[1;31m"[0m[31mblocked[1;31m"[0m[31m[0m=>[32m#<Set: {[0m}>,
|
||||||
|
[31m[1;31m"[0m[31mconf[1;31m"[0m[31m[0m=>{[31m[1;31m"[0m[31mSEED[1;31m"[0m[31m[0m=>[31m[1;31m"[0m[31m[1;35m\x1F[0m[31mL^9[1;35m\x90[0m[31me[1;35m\xF8[0m[31mg[1;35m\xF2[0m[31m[1;35m\x83[0m[31m[1;35m\xB4[0m[31m[1;35m\xC4[0m[31m>c[1;35m\x85[0m[31m[1;35m\xAE[0m[31m2w[1;35m\xBA[0m[31m&,@[1;35m\xD3[0m[31m[1;35m\x96[0m[31m[1;35m\xCA[0m[31mlO*[1;35m\xB9[0m[31m[1;35m\x8D[0m[31mkX[1;31m"[0m[31m[0m, [31m[1;31m"[0m[31mHEAD.draft[1;31m"[0m[31m[0m=>[1;36mnil[0m},
|
||||||
|
[31m[1;31m"[0m[31mmessages.count[1;31m"[0m[31m[0m=>{[31m[1;31m"[0m[31m@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519[1;31m"[0m[31m[0m=>[1;34m4[0m},
|
||||||
|
[31m[1;31m"[0m[31mmessages[1;31m"[0m[31m[0m=>
|
||||||
|
{[31m[1;31m"[0m[31m%8STBRYR0WYJJRSD8DRA9RT6RF6QD6AKARCDYV17X8REGACHZ41W0.sha256[1;31m"[0m[31m[0m=>
|
||||||
|
[32m#<Pigeon::Message:0x0000559bd15eb448[0m
|
||||||
|
@author[32m=[0m[32m#<Pigeon::RemoteIdentity:0x0000559bd15ea4d0[0m @multihash[32m=[0m[31m[1;31m"[0m[31m@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519[1;31m"[0m[31m[0m[32m>[0m,
|
||||||
|
@body[32m=[0m{[31m[1;31m"[0m[31ma[1;31m"[0m[31m[0m=>[31m[1;31m"[0m[31m[1;35m\"[0m[31mb[1;35m\"[0m[31m[1;31m"[0m[31m[0m},
|
||||||
|
@depth[32m=[0m[1;34m0[0m,
|
||||||
|
@kind[32m=[0m[31m[1;31m"[0m[31munit_test[1;31m"[0m[31m[0m,
|
||||||
|
@lipmaa[32m=[0m[1;34m0[0m,
|
||||||
|
@prev[32m=[0m[31m[1;31m"[0m[31mNONE[1;31m"[0m[31m[0m,
|
||||||
|
@signature[32m=[0m[31m[1;31m"[0m[31m8581280WEPNQGJ4DA6K0M7W726YVK1QGW5T7EPGZ61V4HV2GD1RKAB5AN8FXREW0NZKYKFANHW64H3YT0RSMMY30T8TBDJJSR0G9E0G.sig.ed25519[1;31m"[0m[31m[0m[32m>[0m,
|
||||||
|
[31m[1;31m"[0m[31m%T88VZKCWN33CVD0TFBRPJ13NJHXF19TFRWP8NFJ1JGE5RB5ETC0G.sha256[1;31m"[0m[31m[0m=>
|
||||||
|
[32m#<Pigeon::Message:0x0000559bd160cb98[0m
|
||||||
|
@author[32m=[0m[32m#<Pigeon::RemoteIdentity:0x0000559bd160c7d8[0m @multihash[32m=[0m[31m[1;31m"[0m[31m@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519[1;31m"[0m[31m[0m[32m>[0m,
|
||||||
|
@body[32m=[0m{[31m[1;31m"[0m[31mc[1;31m"[0m[31m[0m=>[31m[1;31m"[0m[31m[1;35m\"[0m[31md[1;35m\"[0m[31m[1;31m"[0m[31m[0m},
|
||||||
|
@depth[32m=[0m[1;34m1[0m,
|
||||||
|
@kind[32m=[0m[31m[1;31m"[0m[31munit_test[1;31m"[0m[31m[0m,
|
||||||
|
@lipmaa[32m=[0m[1;34m0[0m,
|
||||||
|
@prev[32m=[0m[31m[1;31m"[0m[31m%8STBRYR0WYJJRSD8DRA9RT6RF6QD6AKARCDYV17X8REGACHZ41W0.sha256[1;31m"[0m[31m[0m,
|
||||||
|
@signature[32m=[0m[31m[1;31m"[0m[31m60R873HBC5GHGVFWBC3RZBHXTQW0240GNF20JYBR71V4B1Z57HHXJ6N39Y4QZZPD34PQGZEQVMSAXTC71PATXAMWBVDCF2S9S45KM1G.sig.ed25519[1;31m"[0m[31m[0m[32m>[0m,
|
||||||
|
[31m[1;31m"[0m[31m%JD4BETS4YH4ZA7CMP4ZHG0R62T5B0EAFDYHNM5S12M04SAF9AJ4G.sha256[1;31m"[0m[31m[0m=>
|
||||||
|
[32m#<Pigeon::Message:0x0000559bd16165a8[0m
|
||||||
|
@author[32m=[0m[32m#<Pigeon::RemoteIdentity:0x0000559bd1616300[0m @multihash[32m=[0m[31m[1;31m"[0m[31m@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519[1;31m"[0m[31m[0m[32m>[0m,
|
||||||
|
@body[32m=[0m{[31m[1;31m"[0m[31me[1;31m"[0m[31m[0m=>[31m[1;31m"[0m[31m[1;35m\"[0m[31mf[1;35m\"[0m[31m[1;31m"[0m[31m[0m},
|
||||||
|
@depth[32m=[0m[1;34m2[0m,
|
||||||
|
@kind[32m=[0m[31m[1;31m"[0m[31munit_test[1;31m"[0m[31m[0m,
|
||||||
|
@lipmaa[32m=[0m[1;34m1[0m,
|
||||||
|
@prev[32m=[0m[31m[1;31m"[0m[31m%T88VZKCWN33CVD0TFBRPJ13NJHXF19TFRWP8NFJ1JGE5RB5ETC0G.sha256[1;31m"[0m[31m[0m,
|
||||||
|
@signature[32m=[0m[31m[1;31m"[0m[31m7DH9ZXMVT6RJEX31BPNSJ3XRA3AMPV97A1CPWW4BV0N99FW2JEPSCVQNJP7SZWA1N7BT560Y9EAK4N7AWFHDEFZV9AJ7PS81CVRF600.sig.ed25519[1;31m"[0m[31m[0m[32m>[0m,
|
||||||
|
[31m[1;31m"[0m[31m%WTRSWSVA84DK2QMX5FDSNCVSAKQ4AFNPBW6VE93X4SJ1R60WDYMG.sha256[1;31m"[0m[31m[0m=>
|
||||||
|
[32m#<Pigeon::Message:0x0000559bd1638978[0m
|
||||||
|
@author[32m=[0m[32m#<Pigeon::RemoteIdentity:0x0000559bd1638590[0m @multihash[32m=[0m[31m[1;31m"[0m[31m@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519[1;31m"[0m[31m[0m[32m>[0m,
|
||||||
|
@body[32m=[0m{[31m[1;31m"[0m[31mg[1;31m"[0m[31m[0m=>[31m[1;31m"[0m[31m[1;35m\"[0m[31mh[1;35m\"[0m[31m[1;31m"[0m[31m[0m},
|
||||||
|
@depth[32m=[0m[1;34m3[0m,
|
||||||
|
@kind[32m=[0m[31m[1;31m"[0m[31munit_test[1;31m"[0m[31m[0m,
|
||||||
|
@lipmaa[32m=[0m[1;34m2[0m,
|
||||||
|
@prev[32m=[0m[31m[1;31m"[0m[31m%JD4BETS4YH4ZA7CMP4ZHG0R62T5B0EAFDYHNM5S12M04SAF9AJ4G.sha256[1;31m"[0m[31m[0m,
|
||||||
|
@signature[32m=[0m[31m[1;31m"[0m[31m6KZZ2816J8V28QZG5EFM1BZAB2TF1HC87YTCQRSN1Q7395K91C9E7KE7DATT99N7XGQEJ5MRCNDS7354C5KN7763C1XVARKWRDG4T1R.sig.ed25519[1;31m"[0m[31m[0m[32m>[0m},
|
||||||
|
[31m[1;31m"[0m[31mmessages.by_depth[1;31m"[0m[31m[0m=>
|
||||||
|
{[31m[1;31m"[0m[31m@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519.0[1;31m"[0m[31m[0m=>[31m[1;31m"[0m[31m%8STBRYR0WYJJRSD8DRA9RT6RF6QD6AKARCDYV17X8REGACHZ41W0.sha256[1;31m"[0m[31m[0m,
|
||||||
|
[31m[1;31m"[0m[31m@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519.1[1;31m"[0m[31m[0m=>[31m[1;31m"[0m[31m%T88VZKCWN33CVD0TFBRPJ13NJHXF19TFRWP8NFJ1JGE5RB5ETC0G.sha256[1;31m"[0m[31m[0m,
|
||||||
|
[31m[1;31m"[0m[31m@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519.2[1;31m"[0m[31m[0m=>[31m[1;31m"[0m[31m%JD4BETS4YH4ZA7CMP4ZHG0R62T5B0EAFDYHNM5S12M04SAF9AJ4G.sha256[1;31m"[0m[31m[0m,
|
||||||
|
[31m[1;31m"[0m[31m@Y4ZFMFQPWCX0S5KD4C4NMFSRCRCT92FY410M4ACFBK3P24RH9MD0.ed25519.3[1;31m"[0m[31m[0m=>[31m[1;31m"[0m[31m%WTRSWSVA84DK2QMX5FDSNCVSAKQ4AFNPBW6VE93X4SJ1R60WDYMG.sha256[1;31m"[0m[31m[0m},
|
||||||
|
[31m[1;31m"[0m[31mpeers[1;31m"[0m[31m[0m=>[32m#<Set: {[0m}>},
|
||||||
|
@thread_safe[32m=[0m[1;36mfalse[0m,
|
||||||
|
@ultra_safe[32m=[0m[1;36mtrue[0m[32m>[0m[32m>[0m[32m>[0m
|
|
@ -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
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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])
|
||||||
|
|
65
tutorial.rb
65
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"
|
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
|
|
||||||
|
|
Loading…
Reference in New Issue