Sig service redesign (#126)

This commit is contained in:
Pavel 2022-02-04 22:39:41 +03:00 committed by GitHub
parent 0c5fecac40
commit 976cd0435c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 4100 additions and 635 deletions

View File

@ -27,7 +27,7 @@ jobs:
### Publish to NPM registry
- uses: actions/setup-node@v1
with:
node-version: '15'
node-version: '16'
registry-url: 'https://registry.npmjs.org'
- run: cat package.json

View File

@ -27,7 +27,7 @@ jobs:
### Publish to NPM registry
- uses: actions/setup-node@v1
with:
node-version: '14'
node-version: '16'
registry-url: 'https://registry.npmjs.org'
- run: npm i

35
aqua/src/services.aqua Normal file
View File

@ -0,0 +1,35 @@
-- import SignResult, Sig from "@fluencelabs/aqua-lib/builtin.aqua"
-- export SignResult, Sig
-- TODO:: fix this issue: https://github.com/fluencelabs/aqua-lib/issues/12
-- and remove copy-paste
data SignResult:
-- Was call successful or not
success: bool
-- Error message. Will be null if the call is successful
error: ?string
-- Signature as byte array. Will be null if the call is not successful
signature: ?[]u8
-- Available only on FluenceJS peers
-- The service can also be resolved by it's host peer id
service Sig("sig"):
-- Signs data with the service's private key.
-- Depending on implementation the service might check call params to restrict usage for security reasons.
-- By default it is only allowed to be used on the same peer the particle was initiated
-- and accepts data only from the following sources:
-- trust-graph.get_trust_bytes
-- trust-graph.get_revocation_bytes
-- registry.get_key_bytes
-- registry.get_record_bytes
-- registry.get_host_record_bytes
-- Argument: data - byte array to sign
-- Returns: signature as SignResult structure
sign(data: []u8) -> SignResult
-- Given the data and signature both as byte arrays, returns true if the signature is correct, false otherwise.
verify(signature: []u8, data: []u8) -> bool
-- Gets service's public key.
get_pub_key() -> string

11
aqua/tests/sig-tests.aqua Normal file
View File

@ -0,0 +1,11 @@
import SignResult, Sig from "../src/services.aqua"
export Sig
service DataProvider("data"):
provide_data() -> []u8
func callSig(sigId: string) -> SignResult:
data <- DataProvider.provide_data()
Sig sigId
signature <- Sig.sign(data)
<- signature

File diff suppressed because one or more lines are too long

View File

@ -100,6 +100,7 @@
<section class="tsd-index-section ">
<h3>Methods</h3>
<ul class="tsd-index-list">
<li class="tsd-kind-method tsd-parent-kind-class"><a href="FluencePeer.html#getServices" class="tsd-kind-icon">get<wbr>Services</a></li>
<li class="tsd-kind-method tsd-parent-kind-class"><a href="FluencePeer.html#getStatus" class="tsd-kind-icon">get<wbr>Status</a></li>
<li class="tsd-kind-method tsd-parent-kind-class"><a href="FluencePeer.html#start" class="tsd-kind-icon">start</a></li>
<li class="tsd-kind-method tsd-parent-kind-class"><a href="FluencePeer.html#stop" class="tsd-kind-icon">stop</a></li>
@ -121,7 +122,7 @@
<li class="tsd-description">
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/FluencePeer.ts#L138">internal/FluencePeer.ts:138</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L140">internal/FluencePeer.ts:140</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -146,7 +147,7 @@
<li class="tsd-description">
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/FluencePeer.ts#L243">internal/FluencePeer.ts:243</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L257">internal/FluencePeer.ts:257</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -315,6 +316,28 @@
</section>
<section class="tsd-panel-group tsd-member-group ">
<h2>Methods</h2>
<section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class">
<a name="getServices" class="tsd-anchor"></a>
<h3>get<wbr>Services</h3>
<ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class">
<li class="tsd-signature tsd-kind-icon">get<wbr>Services<span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">{ </span>sig<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Sig</span><span class="tsd-signature-symbol"> }</span></li>
</ul>
<ul class="tsd-descriptions">
<li class="tsd-description">
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L229">internal/FluencePeer.ts:229</a></li>
</ul>
</aside>
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-symbol">{ </span>sig<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Sig</span><span class="tsd-signature-symbol"> }</span></h4>
<ul class="tsd-parameters">
<li class="tsd-parameter">
<h5>sig<span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">Sig</span></h5>
</li>
</ul>
</li>
</ul>
</section>
<section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class">
<a name="getStatus" class="tsd-anchor"></a>
<h3>get<wbr>Status</h3>
@ -325,7 +348,7 @@
<li class="tsd-description">
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/FluencePeer.ts#L156">internal/FluencePeer.ts:156</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L158">internal/FluencePeer.ts:158</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -347,7 +370,7 @@
<li class="tsd-description">
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/FluencePeer.ts#L172">internal/FluencePeer.ts:172</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L174">internal/FluencePeer.ts:174</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -379,7 +402,7 @@
<li class="tsd-description">
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/FluencePeer.ts#L225">internal/FluencePeer.ts:225</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L239">internal/FluencePeer.ts:239</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -402,7 +425,7 @@
<li class="tsd-description">
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/FluencePeer.ts#L145">internal/FluencePeer.ts:145</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L147">internal/FluencePeer.ts:147</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -447,6 +470,9 @@
<li class=" tsd-kind-get-signature tsd-parent-kind-class">
<a href="FluencePeer.html#internals" class="tsd-kind-icon">internals</a>
</li>
<li class=" tsd-kind-method tsd-parent-kind-class">
<a href="FluencePeer.html#getServices" class="tsd-kind-icon">get<wbr>Services</a>
</li>
<li class=" tsd-kind-method tsd-parent-kind-class">
<a href="FluencePeer.html#getStatus" class="tsd-kind-icon">get<wbr>Status</a>
</li>

View File

@ -93,6 +93,7 @@
<h3>Methods</h3>
<ul class="tsd-index-list">
<li class="tsd-kind-method tsd-parent-kind-class"><a href="KeyPair.html#signBytes" class="tsd-kind-icon">sign<wbr>Bytes</a></li>
<li class="tsd-kind-method tsd-parent-kind-class"><a href="KeyPair.html#toB58String" class="tsd-kind-icon">to<wbr>B58<wbr>String</a></li>
<li class="tsd-kind-method tsd-parent-kind-class"><a href="KeyPair.html#toEd25519PrivateKey" class="tsd-kind-icon">to<wbr>Ed25519<wbr>Private<wbr>Key</a></li>
<li class="tsd-kind-method tsd-parent-kind-class"><a href="KeyPair.html#verify" class="tsd-kind-icon">verify</a></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-static"><a href="KeyPair.html#fromEd25519SK" class="tsd-kind-icon">from<wbr>Ed25519SK</a></li>
@ -114,7 +115,7 @@
<li class="tsd-description">
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/KeyPair.ts#L26">internal/KeyPair.ts:26</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/KeyPair.ts#L26">internal/KeyPair.ts:26</a></li>
</ul>
</aside>
<h4 class="tsd-parameters-title">Parameters</h4>
@ -136,7 +137,7 @@
<div class="tsd-signature tsd-kind-icon">Libp2p<wbr>Peer<wbr>Id<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">PeerId</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/KeyPair.ts#L24">internal/KeyPair.ts:24</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/KeyPair.ts#L24">internal/KeyPair.ts:24</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -158,7 +159,7 @@
<li class="tsd-description">
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/KeyPair.ts#L58">internal/KeyPair.ts:58</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/KeyPair.ts#L62">internal/KeyPair.ts:62</a></li>
</ul>
</aside>
<h4 class="tsd-parameters-title">Parameters</h4>
@ -171,6 +172,23 @@
</li>
</ul>
</section>
<section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class">
<a name="toB58String" class="tsd-anchor"></a>
<h3>to<wbr>B58<wbr>String</h3>
<ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class">
<li class="tsd-signature tsd-kind-icon">to<wbr>B58<wbr>String<span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">string</span></li>
</ul>
<ul class="tsd-descriptions">
<li class="tsd-description">
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/KeyPair.ts#L51">internal/KeyPair.ts:51</a></li>
</ul>
</aside>
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">string</span></h4>
</li>
</ul>
</section>
<section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class">
<a name="toEd25519PrivateKey" class="tsd-anchor"></a>
<h3>to<wbr>Ed25519<wbr>Private<wbr>Key</h3>
@ -181,7 +199,7 @@
<li class="tsd-description">
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/KeyPair.ts#L54">internal/KeyPair.ts:54</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/KeyPair.ts#L58">internal/KeyPair.ts:58</a></li>
</ul>
</aside>
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Uint8Array</span></h4>
@ -199,7 +217,7 @@
<li class="tsd-description">
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/KeyPair.ts#L62">internal/KeyPair.ts:62</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/KeyPair.ts#L66">internal/KeyPair.ts:66</a></li>
</ul>
</aside>
<h4 class="tsd-parameters-title">Parameters</h4>
@ -225,7 +243,7 @@
<li class="tsd-description">
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/KeyPair.ts#L35">internal/KeyPair.ts:35</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/KeyPair.ts#L35">internal/KeyPair.ts:35</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -256,7 +274,7 @@
<li class="tsd-description">
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/KeyPair.ts#L46">internal/KeyPair.ts:46</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/KeyPair.ts#L46">internal/KeyPair.ts:46</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -300,6 +318,9 @@
<li class=" tsd-kind-method tsd-parent-kind-class">
<a href="KeyPair.html#signBytes" class="tsd-kind-icon">sign<wbr>Bytes</a>
</li>
<li class=" tsd-kind-method tsd-parent-kind-class">
<a href="KeyPair.html#toB58String" class="tsd-kind-icon">to<wbr>B58<wbr>String</a>
</li>
<li class=" tsd-kind-method tsd-parent-kind-class">
<a href="KeyPair.html#toEd25519PrivateKey" class="tsd-kind-icon">to<wbr>Ed25519<wbr>Private<wbr>Key</a>
</li>

View File

@ -118,7 +118,7 @@
<div class="tsd-signature tsd-kind-icon">init<wbr>Peer<wbr>Id<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/commonTypes.ts#L37">internal/commonTypes.ts:37</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/commonTypes.ts#L37">internal/commonTypes.ts:37</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -133,7 +133,7 @@
<div class="tsd-signature tsd-kind-icon">particle<wbr>Id<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/commonTypes.ts#L32">internal/commonTypes.ts:32</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/commonTypes.ts#L32">internal/commonTypes.ts:32</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -148,7 +148,7 @@
<div class="tsd-signature tsd-kind-icon">signature<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/commonTypes.ts#L52">internal/commonTypes.ts:52</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/commonTypes.ts#L52">internal/commonTypes.ts:52</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -163,7 +163,7 @@
<div class="tsd-signature tsd-kind-icon">tetraplets<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">{</span><span class="tsd-signature-symbol">[ </span><span class="tsd-signature-type">key</span><span class="tsd-signature-symbol"> in </span><span class="tsd-signature-type">string</span><span class="tsd-signature-symbol">]</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">SecurityTetraplet</span><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol"> }</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/commonTypes.ts#L57">internal/commonTypes.ts:57</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/commonTypes.ts#L57">internal/commonTypes.ts:57</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -178,7 +178,7 @@
<div class="tsd-signature tsd-kind-icon">timestamp<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/commonTypes.ts#L42">internal/commonTypes.ts:42</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/commonTypes.ts#L42">internal/commonTypes.ts:42</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -193,7 +193,7 @@
<div class="tsd-signature tsd-kind-icon">ttl<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/commonTypes.ts#L47">internal/commonTypes.ts:47</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/commonTypes.ts#L47">internal/commonTypes.ts:47</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">

View File

@ -108,7 +108,7 @@
<div class="tsd-signature tsd-kind-icon">Key<wbr>Pair<span class="tsd-signature-symbol">:</span> <a href="../classes/KeyPair.html" class="tsd-signature-type" data-tsd-kind="Class">KeyPair</a></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/FluencePeer.ts#L71">internal/FluencePeer.ts:71</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L73">internal/FluencePeer.ts:73</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -124,7 +124,7 @@
<div class="tsd-signature tsd-kind-icon">avm<wbr>Log<wbr>Level<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">LogLevel</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/FluencePeer.ts#L65">internal/FluencePeer.ts:65</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L67">internal/FluencePeer.ts:67</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -139,7 +139,7 @@
<div class="tsd-signature tsd-kind-icon">avm<wbr>Runner<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">AvmRunner</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/FluencePeer.ts#L102">internal/FluencePeer.ts:102</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L104">internal/FluencePeer.ts:104</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -154,7 +154,7 @@
<div class="tsd-signature tsd-kind-icon">check<wbr>Connection<wbr>Timeout<wbr>Ms<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/FluencePeer.ts#L78">internal/FluencePeer.ts:78</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L80">internal/FluencePeer.ts:80</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -171,7 +171,7 @@
<div class="tsd-signature tsd-kind-icon">connect<wbr>To<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">Multiaddr</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">Node</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/FluencePeer.ts#L60">internal/FluencePeer.ts:60</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L62">internal/FluencePeer.ts:62</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -193,7 +193,7 @@
<div class="tsd-signature tsd-kind-icon">default<wbr>Ttl<wbr>Ms<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/FluencePeer.ts#L97">internal/FluencePeer.ts:97</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L99">internal/FluencePeer.ts:99</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -210,7 +210,7 @@
<div class="tsd-signature tsd-kind-icon">dial<wbr>Timeout<wbr>Ms<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/FluencePeer.ts#L90">internal/FluencePeer.ts:90</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L92">internal/FluencePeer.ts:92</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -225,7 +225,7 @@
<div class="tsd-signature tsd-kind-icon">skip<wbr>Check<wbr>Connection<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">boolean</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/FluencePeer.ts#L85">internal/FluencePeer.ts:85</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L87">internal/FluencePeer.ts:87</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">

View File

@ -104,7 +104,7 @@
<div class="tsd-signature tsd-kind-icon">is<wbr>Connected<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Boolean</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/FluencePeer.ts#L117">internal/FluencePeer.ts:117</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L119">internal/FluencePeer.ts:119</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -119,7 +119,7 @@
<div class="tsd-signature tsd-kind-icon">is<wbr>Initialized<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Boolean</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/FluencePeer.ts#L112">internal/FluencePeer.ts:112</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L114">internal/FluencePeer.ts:114</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -134,7 +134,7 @@
<div class="tsd-signature tsd-kind-icon">peer<wbr>Id<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/FluencePeer.ts#L122">internal/FluencePeer.ts:122</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L124">internal/FluencePeer.ts:124</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -149,7 +149,7 @@
<div class="tsd-signature tsd-kind-icon">relay<wbr>Peer<wbr>Id<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/FluencePeer.ts#L127">internal/FluencePeer.ts:127</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L129">internal/FluencePeer.ts:129</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">

View File

@ -106,7 +106,7 @@
<div class="tsd-signature tsd-kind-icon">Avm<wbr>Loglevel<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">LogLevel</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/FluencePeer.ts#L44">internal/FluencePeer.ts:44</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/FluencePeer.ts#L46">internal/FluencePeer.ts:46</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -122,7 +122,7 @@
<div class="tsd-signature tsd-kind-icon">Peer<wbr>IdB58<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/internal/commonTypes.ts#L22">internal/commonTypes.ts:22</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/internal/commonTypes.ts#L22">internal/commonTypes.ts:22</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -140,7 +140,7 @@
<div class="tsd-signature tsd-kind-icon">Fluence<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">{ </span>getPeer<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> =&gt; </span><a href="classes/FluencePeer.html" class="tsd-signature-type" data-tsd-kind="Class">FluencePeer</a><span class="tsd-signature-symbol">; </span>getStatus<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> =&gt; </span><a href="interfaces/PeerStatus.html" class="tsd-signature-type" data-tsd-kind="Interface">PeerStatus</a><span class="tsd-signature-symbol">; </span>start<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span>config<span class="tsd-signature-symbol">?: </span><a href="interfaces/PeerConfig.html" class="tsd-signature-type" data-tsd-kind="Interface">PeerConfig</a><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> =&gt; </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">; </span>stop<span class="tsd-signature-symbol">: </span><span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol"> =&gt; </span><span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol"> }</span><span class="tsd-signature-symbol"> = ...</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/index.ts#L36">index.ts:36</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/index.ts#L36">index.ts:36</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
@ -260,7 +260,7 @@
<li class="tsd-description">
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/c3512fd/src/index.ts#L25">index.ts:25</a></li>
<li>Defined in <a href="https://github.com/fluencelabs/fluence-js/blob/1508a12/src/index.ts#L25">index.ts:25</a></li>
</ul>
</aside>
<h4 class="tsd-parameters-title">Parameters</h4>

3465
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,9 @@
"main": "./dist/index.js",
"typings": "./dist/index.d.ts",
"scripts": {
"compile-aqua": "npm run compile-aqua:src && npm run compile-aqua:test",
"compile-aqua:src": "aqua -i ./aqua/src/ -o ./src/internal/_aqua",
"compile-aqua:test": "aqua -i ./aqua/tests/ -o ./src/__test__/_aqua",
"test": "jest --watch",
"test:all": "jest",
"test:unit": "jest --testPathPattern=src/__test__/unit",
@ -40,6 +43,8 @@
"uuid": "8.3.0"
},
"devDependencies": {
"@fluencelabs/aqua": "^0.5.3-258",
"@fluencelabs/aqua-lib": "^0.3.4",
"@types/jest": "^26.0.22",
"jest": "^26.6.3",
"js-base64": "^3.7.2",

View File

@ -0,0 +1,161 @@
/**
*
* This file is auto-generated. Do not edit manually: changes may be erased.
* Generated by Aqua compiler: https://github.com/fluencelabs/aqua/.
* If you find any bugs, please write an issue on GitHub: https://github.com/fluencelabs/aqua/issues
* Aqua version: 0.5.3-258
*
*/
import { Fluence, FluencePeer } from '../../';
import { CallParams, callFunction, registerService } from '../../internal/compilerSupport/v2';
// Services
export interface DataProviderDef {
provide_data: (callParams: CallParams<null>) => number[] | Promise<number[]>;
}
export function registerDataProvider(service: DataProviderDef): void;
export function registerDataProvider(serviceId: string, service: DataProviderDef): void;
export function registerDataProvider(peer: FluencePeer, service: DataProviderDef): void;
export function registerDataProvider(peer: FluencePeer, serviceId: string, service: DataProviderDef): void;
export function registerDataProvider(...args: any) {
registerService(args, {
defaultServiceId: 'data',
functions: [
{
functionName: 'provide_data',
argDefs: [],
returnType: {
tag: 'primitive',
},
},
],
});
}
export interface SigDef {
get_pub_key: (callParams: CallParams<null>) => string | Promise<string>;
sign: (
data: number[],
callParams: CallParams<'data'>,
) =>
| { error: string | null; signature: number[] | null; success: boolean }
| Promise<{ error: string | null; signature: number[] | null; success: boolean }>;
verify: (
signature: number[],
data: number[],
callParams: CallParams<'signature' | 'data'>,
) => boolean | Promise<boolean>;
}
export function registerSig(service: SigDef): void;
export function registerSig(serviceId: string, service: SigDef): void;
export function registerSig(peer: FluencePeer, service: SigDef): void;
export function registerSig(peer: FluencePeer, serviceId: string, service: SigDef): void;
export function registerSig(...args: any) {
registerService(args, {
defaultServiceId: 'sig',
functions: [
{
functionName: 'get_pub_key',
argDefs: [],
returnType: {
tag: 'primitive',
},
},
{
functionName: 'sign',
argDefs: [
{
name: 'data',
argType: {
tag: 'primitive',
},
},
],
returnType: {
tag: 'primitive',
},
},
{
functionName: 'verify',
argDefs: [
{
name: 'signature',
argType: {
tag: 'primitive',
},
},
{
name: 'data',
argType: {
tag: 'primitive',
},
},
],
returnType: {
tag: 'primitive',
},
},
],
});
}
// Functions
export type CallSigResult = { error: string | null; signature: number[] | null; success: boolean };
export function callSig(sigId: string, config?: { ttl?: number }): Promise<CallSigResult>;
export function callSig(peer: FluencePeer, sigId: string, config?: { ttl?: number }): Promise<CallSigResult>;
export function callSig(...args: any) {
let script = `
(xor
(seq
(seq
(seq
(seq
(call %init_peer_id% ("getDataSrv" "-relay-") [] -relay-)
(call %init_peer_id% ("getDataSrv" "sigId") [] sigId)
)
(call %init_peer_id% ("data" "provide_data") [] data)
)
(call %init_peer_id% (sigId "sign") [data] signature)
)
(xor
(call %init_peer_id% ("callbackSrv" "response") [signature])
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 1])
)
)
(call %init_peer_id% ("errorHandlingSrv" "error") [%last_error% 2])
)
`;
return callFunction(
args,
{
functionName: 'callSig',
returnType: {
tag: 'primitive',
},
argDefs: [
{
name: 'sigId',
argType: {
tag: 'primitive',
},
},
],
names: {
relay: '-relay-',
getDataSrv: 'getDataSrv',
callbackSrv: 'callbackSrv',
responseSrv: 'callbackSrv',
responseFnName: 'response',
errorHandlingSrv: 'errorHandlingSrv',
errorFnName: 'error',
},
},
script,
);
}

View File

@ -0,0 +1,87 @@
import { Fluence, FluencePeer, KeyPair, setLogLevel } from '../../index';
import { allowServiceFn, Sig } from '../../services';
import { registerSig, registerDataProvider, callSig } from '../_aqua/sig-tests';
let peer: FluencePeer;
describe('Sig service test suite', () => {
afterEach(async () => {
if (peer) {
await peer.stop();
}
});
beforeEach(async () => {
peer = new FluencePeer();
await peer.start();
});
it('Use custom sig service, success path', async () => {
const customKeyPair = await KeyPair.randomEd25519();
const customSig = new Sig(customKeyPair);
const data = [1, 2, 3, 4, 5];
registerSig(peer, 'CustomSig', customSig);
registerDataProvider(peer, {
provide_data: () => {
return data;
},
});
customSig.securityGuard = allowServiceFn('data', 'provide_data');
const result = await callSig(peer, 'CustomSig');
expect(result.success).toBe(true);
const isSigCorrect = await customSig.verify(result.signature, data);
expect(isSigCorrect).toBe(true);
});
it('Use custom sig service, fail path', async () => {
const customKeyPair = await KeyPair.randomEd25519();
const customSig = new Sig(customKeyPair);
const data = [1, 2, 3, 4, 5];
registerSig(peer, 'CustomSig', customSig);
registerDataProvider(peer, {
provide_data: () => {
return data;
},
});
customSig.securityGuard = allowServiceFn('wrong', 'wrong');
const result = await callSig(peer, 'CustomSig');
});
it('Default sig service should be resolvable by peer id', async () => {
const sig = peer.getServices().sig;
const data = [1, 2, 3, 4, 5];
registerDataProvider(peer, {
provide_data: () => {
return data;
},
});
const callAsSigRes = await callSig(peer, 'sig');
const callAsPeerIdRes = await callSig(peer, peer.getStatus().peerId);
expect(callAsSigRes.success).toBe(false);
expect(callAsPeerIdRes.success).toBe(false);
sig.securityGuard = () => true;
const callAsSigResAfterGuardChange = await callSig(peer, 'sig');
const callAsPeerIdResAfterGuardChange = await callSig(peer, peer.getStatus().peerId);
expect(callAsSigResAfterGuardChange.success).toBe(true);
expect(callAsPeerIdResAfterGuardChange.success).toBe(true);
const isValid = await sig.verify(callAsSigResAfterGuardChange.signature, data);
expect(isValid).toBe(true);
});
});

View File

@ -1,37 +1,10 @@
import { CallServiceData } from '../../internal/commonTypes';
import { CallParams, CallServiceData } from '../../internal/commonTypes';
import each from 'jest-each';
import { BuiltInServiceContext, builtInServices } from '../../internal/builtInServices';
import { builtInServices } from '../../internal/builtins/common';
import { KeyPair } from '../../internal/KeyPair';
import { Sig, defaultSigGuard, allowServiceFn } from '../../internal/builtins/Sig';
import { toUint8Array } from 'js-base64';
const key = '+cmeYlZKj+MfSa9dpHV+BmLPm6wq4inGlsPlQ1GvtPk=';
const context = (async () => {
const keyBytes = toUint8Array(key);
const kp = await KeyPair.fromEd25519SK(keyBytes);
const res: BuiltInServiceContext = {
peerKeyPair: kp,
peerId: kp.Libp2pPeerId.toB58String(),
};
return res;
})();
const testData = [1, 2, 3, 4, 5, 6, 7, 9, 10];
// signature produced by KeyPair created from key above (`key` variable)
const testDataSig = [
224, 104, 245, 206, 140, 248, 27, 72, 68, 133, 111, 10, 164, 197, 242, 132, 107, 77, 224, 67, 99, 106, 76, 29, 144,
121, 122, 169, 36, 173, 58, 80, 170, 102, 137, 253, 157, 247, 168, 87, 162, 223, 188, 214, 203, 220, 52, 246, 29,
86, 77, 71, 224, 248, 16, 213, 254, 75, 78, 239, 243, 222, 241, 15,
];
// signature produced by KeyPair created from some random KeyPair
const testDataWrongSig = [
116, 247, 189, 118, 236, 53, 147, 123, 219, 75, 176, 105, 101, 108, 233, 137, 97, 14, 146, 132, 252, 70, 51, 153,
237, 167, 156, 150, 36, 90, 229, 108, 166, 231, 255, 137, 8, 246, 125, 0, 213, 150, 83, 196, 237, 221, 131, 159,
157, 159, 25, 109, 95, 160, 181, 65, 254, 238, 47, 156, 240, 151, 58, 14,
];
describe('Tests for default handler', () => {
// prettier-ignore
each`
@ -65,11 +38,7 @@ describe('Tests for default handler', () => {
${'peer'} | ${'timeout'} | ${[200, ['test']]} | ${0} | ${['test']}}
${'peer'} | ${'timeout'} | ${[]} | ${1} | ${'timeout accepts exactly two arguments: timeout duration in ms and a message string'}}
${'peer'} | ${'timeout'} | ${[200, 'test', 1]} | ${1} | ${'timeout accepts exactly two arguments: timeout duration in ms and a message string'}}
${'sig'} | ${'verify'} | ${[testData, testDataSig]} | ${0} | ${true}}
${'sig'} | ${'verify'} | ${[testData, testDataWrongSig]} | ${0} | ${false}}
${'sig'} | ${'sign'} | ${[]} | ${1} | ${'sign accepts exactly one argument: data be signed in format of u8 array of bytes'}}
${'sig'} | ${'verify'} | ${[testData]} | ${1} | ${'verify accepts exactly two arguments: data and signature, both in format of u8 array of bytes'}}
`.test(
//
'$fnName with $args expected retcode: $retCode and result: $result',
@ -90,7 +59,7 @@ describe('Tests for default handler', () => {
};
// act
const fn = builtInServices(await context)[req.serviceId][req.fnName];
const fn = builtInServices[req.serviceId][req.fnName];
const res = await fn(req);
// assert
@ -118,7 +87,7 @@ describe('Tests for default handler', () => {
};
// act
const fn = builtInServices(await context)[req.serviceId][req.fnName];
const fn = builtInServices[req.serviceId][req.fnName];
const res = await fn(req);
// assert
@ -127,166 +96,140 @@ describe('Tests for default handler', () => {
result: 'The JS implementation of Peer does not support identify',
});
});
});
it('sig.sign should create the correct signature', async () => {
// arrange
const ctx = await context;
const req: CallServiceData = {
serviceId: 'sig',
fnName: 'sign',
args: [testData],
tetraplets: [
[
{
function_name: 'get_trust_bytes',
json_path: '',
peer_pk: '',
service_id: 'trust-graph',
},
],
const key = '+cmeYlZKj+MfSa9dpHV+BmLPm6wq4inGlsPlQ1GvtPk=';
const context = (async () => {
const keyBytes = toUint8Array(key);
const kp = await KeyPair.fromEd25519SK(keyBytes);
const res = {
peerKeyPair: kp,
peerId: kp.Libp2pPeerId.toB58String(),
};
return res;
})();
const testData = [1, 2, 3, 4, 5, 6, 7, 9, 10];
// signature produced by KeyPair created from key above (`key` variable)
const testDataSig = [
224, 104, 245, 206, 140, 248, 27, 72, 68, 133, 111, 10, 164, 197, 242, 132, 107, 77, 224, 67, 99, 106, 76, 29, 144,
121, 122, 169, 36, 173, 58, 80, 170, 102, 137, 253, 157, 247, 168, 87, 162, 223, 188, 214, 203, 220, 52, 246, 29,
86, 77, 71, 224, 248, 16, 213, 254, 75, 78, 239, 243, 222, 241, 15,
];
// signature produced by KeyPair created from some random KeyPair
const testDataWrongSig = [
116, 247, 189, 118, 236, 53, 147, 123, 219, 75, 176, 105, 101, 108, 233, 137, 97, 14, 146, 132, 252, 70, 51, 153,
237, 167, 156, 150, 36, 90, 229, 108, 166, 231, 255, 137, 8, 246, 125, 0, 213, 150, 83, 196, 237, 221, 131, 159,
157, 159, 25, 109, 95, 160, 181, 65, 254, 238, 47, 156, 240, 151, 58, 14,
];
const makeTetraplet = (initPeerId: string, serviceId?: string, fnName?: string): CallParams<'data'> => {
return {
initPeerId: initPeerId,
tetraplets: {
data: [
{
function_name: fnName,
service_id: serviceId,
},
],
particleContext: {
particleId: 'some',
initPeerId: ctx.peerId,
timestamp: 595951200,
ttl: 595961200,
signature: 'sig',
},
};
},
} as any;
};
// act
const fn = builtInServices(ctx)[req.serviceId][req.fnName];
const res = await fn(req);
describe('Sig service tests', () => {
it('sig.sign should create the correct signature', async () => {
const ctx = await context;
const sig = new Sig(ctx.peerKeyPair);
// assert
expect(res).toMatchObject({
retCode: 0,
result: testDataSig,
});
const res = await sig.sign(testData, makeTetraplet(ctx.peerId));
expect(res.success).toBe(true);
expect(res.signature).toStrictEqual(testDataSig);
});
it('sig.verify should return true for the correct signature', async () => {
const ctx = await context;
const sig = new Sig(ctx.peerKeyPair);
const res = await sig.verify(testDataSig, testData);
expect(res).toBe(true);
});
it('sig.verify should return false for the incorrect signature', async () => {
const ctx = await context;
const sig = new Sig(ctx.peerKeyPair);
const res = await sig.verify(testDataWrongSig, testData);
expect(res).toBe(false);
});
it('sign-verify call chain should work', async () => {
const ctx = await context;
const signReq: CallServiceData = {
serviceId: 'sig',
fnName: 'sign',
args: [testData],
tetraplets: [
[
{
function_name: 'get_trust_bytes',
json_path: '',
peer_pk: '',
service_id: 'trust-graph',
},
],
],
particleContext: {
particleId: 'some',
initPeerId: ctx.peerId,
timestamp: 595951200,
ttl: 595961200,
signature: 'sig',
},
};
const sig = new Sig(ctx.peerKeyPair);
const signFn = builtInServices(ctx)[signReq.serviceId][signReq.fnName];
const signRes = await signFn(signReq);
const signature = await sig.sign(testData, makeTetraplet(ctx.peerId));
const res = await sig.verify(signature.signature, testData);
const verifyReq: CallServiceData = {
serviceId: 'sig',
fnName: 'verify',
args: [testData, signRes.result],
tetraplets: [],
particleContext: {
particleId: 'some',
initPeerId: ctx.peerId,
timestamp: 595951200,
ttl: 595961200,
signature: 'sig',
},
};
const verifyFn = builtInServices(ctx)[verifyReq.serviceId][verifyReq.fnName];
const verifyRes = await verifyFn(verifyReq);
expect(verifyRes).toMatchObject({
retCode: 0,
result: true,
});
expect(res).toBe(true);
});
it('sig.sign should not allow data from incorrect services', async () => {
// arrange
it('sig.sign with defaultSigGuard should work for correct callParams', async () => {
const ctx = await context;
const req: CallServiceData = {
serviceId: 'sig',
fnName: 'sign',
args: [testData],
tetraplets: [
[
{
function_name: 'some-other-fn',
json_path: '',
peer_pk: '',
service_id: 'cool-service',
},
],
],
particleContext: {
particleId: 'some',
initPeerId: ctx.peerId,
timestamp: 595951200,
ttl: 595961200,
signature: 'sig',
},
};
const sig = new Sig(ctx.peerKeyPair);
sig.securityGuard = defaultSigGuard(ctx.peerId);
// act
const fn = builtInServices(ctx)[req.serviceId][req.fnName];
const res = await fn(req);
const signature = await sig.sign(testData, makeTetraplet(ctx.peerId, 'registry', 'get_key_bytes'));
// assert
expect(res).toMatchObject({
retCode: 1,
result: expect.stringContaining("Only data from the following services is allowed to be signed:"),
});
await expect(signature).toBeDefined();
});
it('sig.sign should not allow particles initiated from other peers', async () => {
// arrange
it('sig.sign with defaultSigGuard should not allow particles initiated from incorrect service', async () => {
const ctx = await context;
const req: CallServiceData = {
serviceId: 'sig',
fnName: 'sign',
args: [testData],
tetraplets: [
[
{
function_name: 'some-other-fn',
json_path: '',
peer_pk: '',
service_id: 'cool-service',
},
],
],
particleContext: {
particleId: 'some',
initPeerId: (await KeyPair.randomEd25519()).Libp2pPeerId.toB58String(),
timestamp: 595951200,
ttl: 595961200,
signature: 'sig',
},
};
const sig = new Sig(ctx.peerKeyPair);
sig.securityGuard = defaultSigGuard(ctx.peerId);
// act
const fn = builtInServices(ctx)[req.serviceId][req.fnName];
const res = await fn(req);
const res = await sig.sign(testData, makeTetraplet(ctx.peerId, 'other_service', 'other_fn'));
// assert
expect(res).toMatchObject({
retCode: 1,
result: 'sign is only allowed to be called on the same peer the particle was initiated from',
});
await expect(res.success).toBe(false);
await expect(res.error).toBe('Security guard validation failed');
});
it('sig.sign with defaultSigGuard should not allow particles initiated from other peers', async () => {
const ctx = await context;
const sig = new Sig(ctx.peerKeyPair);
sig.securityGuard = defaultSigGuard(ctx.peerId);
const res = await sig.sign(
testData,
makeTetraplet((await KeyPair.randomEd25519()).toB58String(), 'registry', 'get_key_bytes'),
);
await expect(res.success).toBe(false);
await expect(res.error).toBe('Security guard validation failed');
});
it('changing securityGuard should work', async () => {
const ctx = await context;
const sig = new Sig(ctx.peerKeyPair);
sig.securityGuard = allowServiceFn('test', 'test');
const successful1 = await sig.sign(testData, makeTetraplet(ctx.peerId, 'test', 'test'));
const unSuccessful1 = await sig.sign(testData, makeTetraplet(ctx.peerId, 'wrong', 'wrong'));
sig.securityGuard = allowServiceFn('wrong', 'wrong');
const successful2 = await sig.sign(testData, makeTetraplet(ctx.peerId, 'wrong', 'wrong'));
const unSuccessful2 = await sig.sign(testData, makeTetraplet(ctx.peerId, 'test', 'test'));
expect(successful1.success).toBe(true);
expect(successful2.success).toBe(true);
expect(unSuccessful1.success).toBe(false);
expect(unSuccessful2.success).toBe(false);
});
});

View File

@ -25,9 +25,11 @@ import { dataToString, jsonify } from './utils';
import { concatMap, filter, pipe, Subject, tap } from 'rxjs';
import { RequestFlow } from './compilerSupport/v1';
import log from 'loglevel';
import { BuiltInServiceContext, builtInServices } from './builtInServices';
import { builtInServices } from './builtins/common';
import { AvmRunner, InterpreterResult, LogLevel } from '@fluencelabs/avm-runner-interface';
import { AvmRunnerBackground } from '@fluencelabs/avm-runner-background';
import { defaultSigGuard, Sig } from './builtins/Sig';
import { registerSig } from './_aqua/services';
/**
* Node of the Fluence network specified as a pair of node's multiaddr and it's peer id
@ -210,14 +212,24 @@ export class FluencePeer {
}
this._legacyCallServiceHandler = new LegacyCallServiceHandler();
registerDefaultServices(this, {
peerKeyPair: this._keyPair,
peerId: this.getStatus().peerId,
});
registerDefaultServices(this);
this._classServices = {
sig: new Sig(this._keyPair),
};
this._classServices.sig.securityGuard = defaultSigGuard(this.getStatus().peerId);
registerSig(this, this._classServices.sig);
registerSig(this, this.getStatus().peerId, this._classServices.sig);
this._startParticleProcessing();
}
getServices() {
return {
...this._classServices,
};
}
/**
* Un-initializes the peer: stops all the underlying workflows, stops the Aqua VM
* and disconnects from the Fluence network
@ -358,6 +370,10 @@ export class FluencePeer {
private _particleSpecificHandlers = new Map<string, Map<string, GenericCallServiceHandler>>();
private _commonHandlers = new Map<string, GenericCallServiceHandler>();
private _classServices: {
sig: Sig;
};
// Internal peer state
private _defaultTTL: number;
@ -615,11 +631,10 @@ function serviceFnKey(serviceId: string, fnName: string) {
return `${serviceId}/${fnName}`;
}
function registerDefaultServices(peer: FluencePeer, context: BuiltInServiceContext) {
const ctx = builtInServices(context);
for (let serviceId in ctx) {
for (let fnName in ctx[serviceId]) {
const h = ctx[serviceId][fnName];
function registerDefaultServices(peer: FluencePeer) {
for (let serviceId in builtInServices) {
for (let fnName in builtInServices[serviceId]) {
const h = builtInServices[serviceId][fnName];
peer.internals.regHandler.common(serviceId, fnName, h);
}
}

View File

@ -48,6 +48,10 @@ export class KeyPair {
return new KeyPair(lib2p2Pid);
}
toB58String(): string {
return this.Libp2pPeerId.toB58String();
}
/**
* @returns 32 byte private key
*/

View File

@ -0,0 +1,82 @@
/**
*
* This file is auto-generated. Do not edit manually: changes may be erased.
* Generated by Aqua compiler: https://github.com/fluencelabs/aqua/.
* If you find any bugs, please write an issue on GitHub: https://github.com/fluencelabs/aqua/issues
* Aqua version: 0.5.3-258
*
*/
import { Fluence, FluencePeer } from '../../';
import { CallParams, callFunction, registerService } from '../../internal/compilerSupport/v2';
// Services
export interface SigDef {
get_pub_key: (callParams: CallParams<null>) => string | Promise<string>;
sign: (
data: number[],
callParams: CallParams<'data'>,
) =>
| { error: string | null; signature: number[] | null; success: boolean }
| Promise<{ error: string | null; signature: number[] | null; success: boolean }>;
verify: (
signature: number[],
data: number[],
callParams: CallParams<'signature' | 'data'>,
) => boolean | Promise<boolean>;
}
export function registerSig(service: SigDef): void;
export function registerSig(serviceId: string, service: SigDef): void;
export function registerSig(peer: FluencePeer, service: SigDef): void;
export function registerSig(peer: FluencePeer, serviceId: string, service: SigDef): void;
export function registerSig(...args: any) {
registerService(args, {
defaultServiceId: 'sig',
functions: [
{
functionName: 'get_pub_key',
argDefs: [],
returnType: {
tag: 'primitive',
},
},
{
functionName: 'sign',
argDefs: [
{
name: 'data',
argType: {
tag: 'primitive',
},
},
],
returnType: {
tag: 'primitive',
},
},
{
functionName: 'verify',
argDefs: [
{
name: 'signature',
argType: {
tag: 'primitive',
},
},
{
name: 'data',
argType: {
tag: 'primitive',
},
},
],
returnType: {
tag: 'primitive',
},
},
],
});
}
// Functions

View File

@ -1,175 +0,0 @@
/*
* Copyright 2021 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { CallServiceResult } from '@fluencelabs/avm-runner-interface';
import { encode, decode } from 'bs58';
import { PeerIdB58 } from 'src';
import { GenericCallServiceHandler, ResultCodes } from './commonTypes';
import { KeyPair } from './KeyPair';
const success = (result: any): CallServiceResult => {
return {
result: result,
retCode: ResultCodes.success,
};
};
const error = (error: string): CallServiceResult => {
return {
result: error,
retCode: ResultCodes.error,
};
};
export interface BuiltInServiceContext {
peerKeyPair: KeyPair;
peerId: PeerIdB58;
}
export function builtInServices(context: BuiltInServiceContext): {
[serviceId in string]: { [fnName in string]: GenericCallServiceHandler };
} {
return {
op: {
noop: (req) => {
return success({});
},
array: (req) => {
return success(req.args);
},
identity: (req) => {
if (req.args.length > 1) {
return error(`identity accepts up to 1 arguments, received ${req.args.length} arguments`);
} else {
return success(req.args.length === 0 ? {} : req.args[0]);
}
},
concat: (req) => {
const incorrectArgIndices = req.args //
.map((x, i) => [Array.isArray(x), i])
.filter(([isArray, _]) => !isArray)
.map(([_, index]) => index);
if (incorrectArgIndices.length > 0) {
const str = incorrectArgIndices.join(', ');
return error(`All arguments of 'concat' must be arrays: arguments ${str} are not`);
} else {
return success([].concat.apply([], req.args));
}
},
string_to_b58: (req) => {
if (req.args.length !== 1) {
return error('string_to_b58 accepts only one string argument');
} else {
return success(encode(new TextEncoder().encode(req.args[0])));
}
},
string_from_b58: (req) => {
if (req.args.length !== 1) {
return error('string_from_b58 accepts only one string argument');
} else {
return success(new TextDecoder().decode(decode(req.args[0])));
}
},
bytes_to_b58: (req) => {
if (req.args.length !== 1 || !Array.isArray(req.args[0])) {
return error('bytes_to_b58 accepts only single argument: array of numbers');
} else {
const argumentArray = req.args[0] as number[];
return success(encode(new Uint8Array(argumentArray)));
}
},
bytes_from_b58: (req) => {
if (req.args.length !== 1) {
return error('bytes_from_b58 accepts only one string argument');
} else {
return success(Array.from(decode(req.args[0])));
}
},
},
peer: {
timeout: (req) => {
if (req.args.length !== 2) {
return error('timeout accepts exactly two arguments: timeout duration in ms and a message string');
}
const durationMs = req.args[0];
const message = req.args[1];
return new Promise((resolve) => {
setTimeout(() => {
const res = success(message);
resolve(res);
}, durationMs);
});
},
identify: (req) => {
return error('The JS implementation of Peer does not support identify');
},
},
sig: {
sign: async (req) => {
if (req.args.length !== 1) {
return error('sign accepts exactly one argument: data be signed in format of u8 array of bytes');
}
if (req.particleContext.initPeerId !== context.peerId) {
return error('sign is only allowed to be called on the same peer the particle was initiated from');
}
const t = req.tetraplets[0][0];
const serviceFnPair = `${t.service_id}.${t.function_name}`;
const allowedServices = [
'trust-graph.get_trust_bytes',
'trust-graph.get_revocation_bytes',
'registry.get_key_bytes',
'registry.get_record_bytes',
];
if (allowedServices.indexOf(serviceFnPair) === -1) {
return error(
'Only data from the following services is allowed to be signed: ' + allowedServices.join(', '),
);
}
const [data] = req.args;
const signedData = await context.peerKeyPair.signBytes(Uint8Array.from(data));
return success(Array.from(signedData));
},
verify: async (req) => {
if (req.args.length !== 2) {
return error(
'verify accepts exactly two arguments: data and signature, both in format of u8 array of bytes',
);
}
const [data, signature] = req.args;
const result = await context.peerKeyPair.verify(Uint8Array.from(data), Uint8Array.from(signature));
return success(result);
},
},
};
}

View File

@ -0,0 +1,128 @@
import { SecurityTetraplet } from '@fluencelabs/avm-runner-interface';
import { CallParams, PeerIdB58 } from '../commonTypes';
import { KeyPair } from '../KeyPair';
import { SigDef } from '../_aqua/services';
/**
* A predicate of call params for sig service's sign method which determines whether signing operation is allowed or not
*/
export type SigSecurityGuard = (params: CallParams<'data'>) => boolean;
/**
* Only allow calls when tetraplet for 'data' argument satisfies the predicate
*/
export const allowTetraplet = (pred: (tetraplet: SecurityTetraplet) => boolean): SigSecurityGuard => {
return (params) => {
const t = params.tetraplets.data[0];
return pred(t);
};
};
/**
* Only allow data which comes from the specified serviceId and fnName
*/
export const allowServiceFn = (serviceId: string, fnName: string): SigSecurityGuard => {
return allowTetraplet((t) => {
return t.service_id === serviceId && t.function_name === fnName;
});
};
/**
* Only allow data originated from the specified json_path
*/
export const allowExactJsonPath = (jsonPath: string): SigSecurityGuard => {
return allowTetraplet((t) => {
return t.json_path === jsonPath;
});
};
/**
* Only allow signing when particle is initiated at the specified peer
*/
export const allowOnlyParticleOriginatedAt = (peerId: PeerIdB58): SigSecurityGuard => {
return (params) => {
return params.initPeerId === peerId;
};
};
/**
* Only allow signing when all of the predicates are satisfied.
* Useful for predicates reuse
*/
export const and = (...predicates: SigSecurityGuard[]): SigSecurityGuard => {
return (params) => predicates.every((x) => x(params));
};
/**
* Only allow signing when any of the predicates are satisfied.
* Useful for predicates reuse
*/
export const or = (...predicates: SigSecurityGuard[]): SigSecurityGuard => {
return (params) => predicates.some((x) => x(params));
};
export const defaultSigGuard = (peerId: PeerIdB58) => {
return and(
allowOnlyParticleOriginatedAt(peerId),
or(
allowServiceFn('trust-graph', 'get_trust_bytes'),
allowServiceFn('trust-graph', 'get_revocation_bytes'),
allowServiceFn('registry', 'get_key_bytes'),
allowServiceFn('registry', 'get_record_bytes'),
allowServiceFn('registry', 'get_host_record_bytes'),
),
);
};
export class Sig implements SigDef {
private _keyPair: KeyPair;
constructor(keyPair: KeyPair) {
this._keyPair = keyPair;
}
/**
*
*/
securityGuard: SigSecurityGuard = (params) => {
return true;
};
/**
* Gets the public key of KeyPair. Required by aqua
*/
get_pub_key() {
return this._keyPair.toB58String();
}
/**
* Signs the data using key pair's private key. Required by aqua
*/
async sign(
data: number[],
callParams: CallParams<'data'>,
): Promise<{ error: string | null; signature: number[] | null; success: boolean }> {
if (!this.securityGuard(callParams)) {
return {
success: false,
error: 'Security guard validation failed',
signature: null,
};
}
const signedData = await this._keyPair.signBytes(Uint8Array.from(data));
return {
success: true,
error: null,
signature: Array.from(signedData),
};
}
/**
* Verifies the signature. Required by aqua
*/
verify(signature: number[], data: number[]): Promise<boolean> {
return this._keyPair.verify(Uint8Array.from(data), Uint8Array.from(signature));
}
}

View File

@ -0,0 +1,123 @@
/*
* Copyright 2021 Fluence Labs Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { CallServiceResult } from '@fluencelabs/avm-runner-interface';
import { encode, decode } from 'bs58';
import { PeerIdB58 } from 'src';
import { GenericCallServiceHandler, ResultCodes } from '../commonTypes';
import { KeyPair } from '../KeyPair';
const success = (result: any): CallServiceResult => {
return {
result: result,
retCode: ResultCodes.success,
};
};
const error = (error: string): CallServiceResult => {
return {
result: error,
retCode: ResultCodes.error,
};
};
export const builtInServices = {
op: {
noop: (req) => {
return success({});
},
array: (req) => {
return success(req.args);
},
identity: (req) => {
if (req.args.length > 1) {
return error(`identity accepts up to 1 arguments, received ${req.args.length} arguments`);
} else {
return success(req.args.length === 0 ? {} : req.args[0]);
}
},
concat: (req) => {
const incorrectArgIndices = req.args //
.map((x, i) => [Array.isArray(x), i])
.filter(([isArray, _]) => !isArray)
.map(([_, index]) => index);
if (incorrectArgIndices.length > 0) {
const str = incorrectArgIndices.join(', ');
return error(`All arguments of 'concat' must be arrays: arguments ${str} are not`);
} else {
return success([].concat.apply([], req.args));
}
},
string_to_b58: (req) => {
if (req.args.length !== 1) {
return error('string_to_b58 accepts only one string argument');
} else {
return success(encode(new TextEncoder().encode(req.args[0])));
}
},
string_from_b58: (req) => {
if (req.args.length !== 1) {
return error('string_from_b58 accepts only one string argument');
} else {
return success(new TextDecoder().decode(decode(req.args[0])));
}
},
bytes_to_b58: (req) => {
if (req.args.length !== 1 || !Array.isArray(req.args[0])) {
return error('bytes_to_b58 accepts only single argument: array of numbers');
} else {
const argumentArray = req.args[0] as number[];
return success(encode(new Uint8Array(argumentArray)));
}
},
bytes_from_b58: (req) => {
if (req.args.length !== 1) {
return error('bytes_from_b58 accepts only one string argument');
} else {
return success(Array.from(decode(req.args[0])));
}
},
},
peer: {
timeout: (req) => {
if (req.args.length !== 2) {
return error('timeout accepts exactly two arguments: timeout duration in ms and a message string');
}
const durationMs = req.args[0];
const message = req.args[1];
return new Promise((resolve) => {
setTimeout(() => {
const res = success(message);
resolve(res);
}, durationMs);
});
},
identify: (req) => {
return error('The JS implementation of Peer does not support identify');
},
},
};

2
src/services.ts Normal file
View File

@ -0,0 +1,2 @@
export * from './internal/builtins/Sig';
export { registerSig } from './internal/_aqua/services';