· 5 years ago · Jun 22, 2020, 06:28 PM
1/******************************************************************************
2 MESSAGE FORMAT (and description)
3******************************************************************************/
4const letter = { message, signature }
5// => signature: hash message + encrypt hash with skey of `from`
6const message = { flow: `${count}:${from}[:${into}]`, data, cite, seal }
7// => seal: encrypt `data` with `password` and encrypt `key` with `psealkey`
8// so it is possible to later release `ssealkey` to decrypt `key`
9// additionally, also `cite` can be encrypted
10// => count: is a `nonce` to prevent replay attacks
11// => from: is pkey or ID representing pkey of sender (e.g. maybe anonymous new sender)
12// => into: is pkey or ID of recipient (can be middle man), where encrypted DATA
13// contains additional message to forward it to real recipient onion style
14// => data: arbitrary unencrypted or encrypted data to deliver
15// => cite: flows which represent earlier messages
16const data = { key, value }
17// => data: e.g. letter FOR FORWARDING/RELAYING
18const [nonce, from, into] = flow.split(':')
19
20/******************************************************************************
21 DEFINITION: polkadot.js
22******************************************************************************/
23const TYPES = require('./types')
24module.exports = datdotchain
25datdotchain.TYPES = TYPES
26function datdotchain () { return { send, on } }
27const peers = new Map()
28function on (query, respond) { peers.set(query, peers.get(query).concat(response)) }
29
30// EXAMPLE
31// const data = { key: `request/hosting/start`, value: {} }
32// const message = { flow: `${ID}:1:datdot`, data }
33// const letter = { message, signature, proof }
34
35
36function send (letter, done) {
37 const { message, signature } = letter
38 const { flow, data: { key, value }, cite, seal } = message
39 const [ from, nonce, into ] = flow.split(':')
40 const ID = from
41 try {
42 // -------------------------------------------------
43 // const account = {
44 // make : make_account, // OK
45 // give : give_to_account // @TODO 2
46 // }
47 // const feed = {
48 // register : register_feed, // OK
49 // }
50 // const service = {
51 // offer : offer_service, // @TODO 1
52 // provide : provide_service, // @TODO 3
53 // request : request_service, // @TODO LESEZEICHEN
54 // }
55 // const API = { batch, account, feed, service }
56 //
57 // batch => { key, value: message }
58 // make => { key, value: undefined }
59 // give => { key, value: ??? }
60 // update => { key, value: feed } // feed = { id, feedkey, swarmkey, merkleroot }
61 // follow => { key, value: feed } // feed = { id: feed_id, swarmkeys, versions }
62 // register => { key, value: feed } // feed = { id, feedkey, swarmkey, merkleroot }
63 // offer => { key, value: ??? }
64 // request => { key, value: plan } // key = 'request/hosting/start'
65 const { id, ...data } = plan
66 const base_id = await ledger.get(`/plan/${id}/feed_id`)
67 // provide => { key, value: ??? }
68 // -------------------------------------------------
69 // @TODO: use INPUT TYPES to check before send
70 const datdotchain = require('datdot-chain')
71 const XXX = datdotchain.XXX
72 const msg = { ID, key, value }
73
74 console.log(key) // => `send/request/hosting/start`
75 console.log(key.split('/')) // => ['send', 'request', 'hosting', 'start']
76
77 // NAMING (list function types + params checker)
78 const check = XXX
79 const EXTRINSICS = XXX
80 const TYPES = XXX
81
82 // WISHLIST
83 console.log(XXX.messageTypes)
84 // [
85 // 'listen/on/hosting/start',
86 // 'event/hosting',
87 // 'listen/on/hosting/start',
88 //
89 // 'send/request/hosting/start',
90 // 'send/request/hosting/change',
91 // 'send/request/hosting/stop',
92 // 'send/request/encoding/start',
93 // 'send/make/encoding/start',
94 // ...
95 // ]
96 // --------------------------------------------------------------
97 console.log(XXX(message))
98 console.log(XXX)
99 console.log()
100 const key = XXX.keys[5] // 'send/request/hosting/start'
101 const plan = {}
102
103 // EXAMPLE
104 const message = { key, value: plan }
105 const check = XXX(key)
106
107 const response = check(message)
108
109 console.log(response) // 'invalid config'
110 // {}
111 const o = {
112
113 }
114
115 // const example = TYPES.examples(key)
116 // --------------------------------------------------------------
117
118 const plan = {}
119 const extrinsic = { key: 'send/request/hosting/stop' , value: plan }
120 chain.send(extrinsic)
121
122
123 // ....
124 // e.g. input = example.schedules , type = spec.schedules
125 const type = spec.schedules
126 const input = example.schedules = [{ duration : '', delay : '', interval : '', repeat : '', config }]
127 // schedules([foo, bar, baz])
128 // schedules(foo, 0)
129
130
131 check(type, input) // @TODO: ???
132
133
134
135 // 1. @TODO: verify `format` of message
136 const invalidFormat = check('format', data) // type
137 // ....
138
139 // 2. @TODO: verify `content` of message (= check in ledger)
140 // e.g. plan id that doesnt exist
141 // e.g. change plan id of a plan that doesnt belong to account ID
142 const invalidContent = check('content', ledger, data) // in given context
143 if (invalidFormat) return console.error(invalidFormat)
144 // ....
145
146 // ... everything is fine here
147
148 // -------------------------------------------------
149 } catch (e) { return console.error(e) }
150 on(letter, done)
151 outgoing(letter)
152 incoming(letter => peers.get(letter)(letter))
153}
154/*****************************************************************************/
155/*****************************************************************************/
156/*****************************************************************************/
157// @TODO: update stuff below
158
159const substrate = require('datdot-node')
160const check = require('datdot-node/datdot-types')
161const websocket = require('ws')
162const colors = require('colors/safe')
163const NAME = __filename.split('/').pop().split('.')[0].toUpperCase()
164function LOG (...msgs) {
165 msgs = [`[${NAME}] `, ...msgs].map(msg => colors.orange(msg))
166 console.log(...msgs)
167}
168var ready = false, queue = [], accounts = {}, waitlist = {}
169
170const chain = new websocket('ws://localhost:8080')
171chain.on('message', receive)
172chain.on('open', err => {
173 ready = true
174 queue.forEach(done => err ? done(err) : done(null, send))
175 for (var i = 0; i < queue.length; i++) queue[i] = null
176})
177
178module.exports = datdotchain
179
180datdotchain.check = check
181
182function datdotchain (opts, done) {
183 // @TODO: maybe do custom handshake with `chain` to check it's `datdot`
184 if (!ready) return (queue.push(done), void 0)
185 done(null, send)
186 // function on (name, handler) { }
187}
188function receive (message) {
189 const { type, ID, data } = message
190 const account = type === 'event: new account' ? data.pkey : ID
191 const callback = waitlist[account][data.nonce]
192 if (!callback) return LOG('error - unexpected message', message)
193 delete waitlist[account][data.nonce]
194 if (type.indexOf('error:') !== -1) return callback(message)
195 callback(null, data)
196}
197function send (message, done) {
198 const { type, ID, data } = message
199 const invalid = check(message, type)
200 if (invalid) return done(invalid)
201 const account = ID || data.pkey
202 // if `pkey`, save `ID` and remember `pkey` to verify future messages
203 // => but can't verify `ID` where `pkey` is unknown
204 // => so ask `chain` for `pkey` to verify
205 // => to not send crap messages
206 waitlist[account][data.nonce] = done
207 chain.send(JSON.stringify(message))
208}