diff --git a/bootstrap/deploy-actions.sh b/bootstrap/deploy-actions.sh new file mode 100755 index 00000000..63c97d55 --- /dev/null +++ b/bootstrap/deploy-actions.sh @@ -0,0 +1,126 @@ +#!/bin/bash + +deployFiles() { + WAITPID="" + while read -r t;do + ./deploy "$t" + # shellcheck disable=SC2030 + WAITPID="$WAITPID $!" + done |tee -a log/deployment.log 2>&1 + # shellcheck disable=SC2031,SC2086 + wait $WAITPID + echo "$ME: done status $?" +} + +get_type_value() { + head -n1 | sed ' + s/.*\[// + s/\(.*\)].*/\1/ + s/[\t "]*//g + s/,/ /g + s/[\t ][\t ]*/ /g + ' +} + +get_type_from_type_value() { + sed ' + s/:[^ ]*//g + s/[\t ][\t ]*/ /g + ' +} + +get_value_from_type_value() { + t=$(cat -) + for i in $t;do + blah=$(sed 's/^[^:][^:]*://' <<< "$i") + if [ -z "$blah" ];then + blah="\"\"" + fi + echo -n "$blah " + done +} + +get_var() { + head -n 2|tail -n 1|sed ' + s/.*\[// + s/\(.*\)].*/\1/ + s/[\t ]*//g + s/,/ /g + s/[\t ][\t ]*/ /g + ' +} + +make_field() { + v=$(echo "$2"|cut -d' ' -f "$1") + t=$(echo "$3"|cut -d' ' -f "$1") + l=$(echo "$4"|cut -d' ' -f "$1") + if [ "$l" = "\"\"" ];then unset l;fi + if [ -z "$t" ];then t="string";fi + echo "\"$v\": { \"type\": \"$t\", \"value\": \"$l\" }" +} + +createAction() { + type_value=$(get_type_value < "$1") + var=$(get_var < "$1") + + type=$(echo "$type_value"|get_type_from_type_value) + val=$(echo "$type_value"|get_value_from_type_value) + + echo "type_value=$type_value" >&2 + echo "var=$var" >&2 + echo "type=$type" >&2 + echo "val=$val" >&2 + + unset fields + if [ -n "$var" ];then + len=$(echo "$var"|tr ' ' '\n'|wc -l) + len=$((len+1)) + if [ $len -gt 1 ];then + fields=$(make_field 1 "$var" "$type" "$val") + for (( i=2; i/tmp/actions/"$(basename "$1")" +} + +rm -rf /tmp/actions +mkdir /tmp/actions + +for i in ../src/actions/*.rho;do + createAction "$i" +done + +ls /tmp/actions/*.rho|deployFiles diff --git a/bootstrap/listMasterURI.rho b/bootstrap/listMasterURI.rho index f8d580c1..15ed3b85 100644 --- a/bootstrap/listMasterURI.rho +++ b/bootstrap/listMasterURI.rho @@ -7,6 +7,17 @@ in { { stdout!(["read", *read]) | deployerId!(["read", *read]) | read!(*mapCh) + | for (map <- mapCh) + { stdout!(*map.keys().toList()) + | deployerId!(["read", *read]) + | stdout!(*map) + | deployerId!(*map) + } + } | + for(@{"read": *read, ..._} <<- @[*deployerId, "ActionDictionary"]) + { stdout!(["read", *read]) + | deployerId!(["read", *read]) + | read!(*mapCh) | for (map <- mapCh) { stdout!(*map.keys().toList()) | deployerId!(["read", *read]) diff --git a/bootstrap/master-contract-directory b/bootstrap/master-contract-directory index 070e3343..c9d2f188 100755 --- a/bootstrap/master-contract-directory +++ b/bootstrap/master-contract-directory @@ -22,6 +22,7 @@ new ,lookCh ,insertCh ,caps + ,a_caps ,lastUri EOF @@ -37,9 +38,13 @@ in { | for (Dir <- lookCh) { Dir!(*caps) | for (@{"read": read, "write": write, "grant": grant} <- caps) { - + Dir!(*a_caps) | + for (@{"read": a_read, "write": a_write, "grant": a_grant} <- a_caps) { + @write!("ActionDictionary", a_read, *stdout) + | @[*deployerId, "ActionDictionary"]!({"read": a_read, "write": a_write, "grant": a_grant}) + } // Create a global reference to the master contract directory - @[*deployerId, "MasterContractAdmin"]!({"read": read, "write": write, "grant": grant}) + | @[*deployerId, "MasterContractAdmin"]!({"read": read, "write": write, "grant": grant}) | insertArbitrary!(read, *insertCh) | for (URI <- insertCh) { stdout!({ "ReadcapURI": *URI}) diff --git a/src/actions/addGroupToIssue.rho b/src/actions/addGroupToIssue.rho index 6c0f3947..de6d1375 100644 --- a/src/actions/addGroupToIssue.rho +++ b/src/actions/addGroupToIssue.rho @@ -1,4 +1,4 @@ -match ["inbox", "", ""] { +match ["string:inbox", "", ""] { [lockerTag, group, issue] => { new stdout(`rho:io:stdout`), @@ -8,7 +8,7 @@ match ["inbox", "", ""] { in { for(@{"peek": *peek, "URI": uri ..._} <<- @[*deployerId, lockerTag]) { deployId!({"URI": uri}) | - new lockerCh, ret, ret1, ret2, ret3, loop in { + new lockerCh, ret, ret1, ret2, ret3, loop in { peek!("Group", group, *ret) | peek!("issue", issue, *ret1) | for ( @[{"read": *read, ..._}, ..._] <- ret; @[{"admin": *admin, ..._}, ..._] <- ret1 ) { @@ -38,5 +38,5 @@ match ["inbox", "", ""] { } } } - + }} // end of match diff --git a/src/actions/addMember.rho b/src/actions/addMember.rho index e2015049..75888595 100644 --- a/src/actions/addMember.rho +++ b/src/actions/addMember.rho @@ -1,4 +1,4 @@ -match ["?", "?", "?", "?", "inbox"] { +match ["", "", "", "", "string:inbox"] { [name, revAddress, themBoxReg, group, lockerTag] => { new deployId(`rho:rchain:deployId`), diff --git a/src/actions/addVoterToIssue.rho b/src/actions/addVoterToIssue.rho index b30fbec7..d26352e2 100644 --- a/src/actions/addVoterToIssue.rho +++ b/src/actions/addVoterToIssue.rho @@ -1,4 +1,4 @@ -match ["$inbox", `$voterURI`, "$issue"] { +match ["string:inbox", "uri:`voterURI`", "string:issue"] { [lockerTag, toInboxURI, issue] => { new return(`rho:rchain:deployId`), diff --git a/src/actions/checkBalance.rho b/src/actions/checkBalance.rho index d52184d8..a4ad0ea4 100644 --- a/src/actions/checkBalance.rho +++ b/src/actions/checkBalance.rho @@ -1,4 +1,4 @@ -match ["$addr"] { +match ["walletRevAddr"] { [myGovRevAddr] => { new // use Explore to see result at return return, @@ -15,7 +15,7 @@ match ["$addr"] { for (@balance <- balanceCh) { return!(["#define", "$myBalance", balance])| return!("${rev}.${fraction}" %% { - "rev": balance/100000000, + "rev": balance/100000000, "fraction": ("${num}"%%{ "num": balance%100000000+100000000}).slice(1,9) } @@ -23,5 +23,5 @@ match ["$addr"] { } } } - } + } }} // end of match diff --git a/src/actions/createURI.rho b/src/actions/createURI.rho index d733cb9c..0e21adf4 100644 --- a/src/actions/createURI.rho +++ b/src/actions/createURI.rho @@ -1,15 +1,15 @@ -match ["value"] { +match ["string:value"] { [value] => { new return(`rho:rchain:deployId`), - insert(`rho:registry:insertArbitrary`), + insert(`rho:registry:insertArbitrary`), stdout(`rho:io:stdout`), uriCh in { insert!( - + value // enter value above or replace value here with longer rholang - + , *uriCh) | for (@URI <- uriCh) { stdout!([ "URI", URI, "Obj", value]) | diff --git a/src/actions/newinbox.rho b/src/actions/newinbox.rho index 7be38687..310086fd 100644 --- a/src/actions/newinbox.rho +++ b/src/actions/newinbox.rho @@ -1,4 +1,4 @@ -match [`$masterURI`] { +match [`MasterURI:$masterURI`] { [ReadcapURI] => { new stdout(`rho:io:stdout`), diff --git a/src/participate.js b/src/participate.js index d33337dd..3763b2af 100644 --- a/src/participate.js +++ b/src/participate.js @@ -11,7 +11,16 @@ import { listenAtDeployId, RhoExpr, } from 'rchain-api'; -import { actions } from './actions.js'; + + +/** + * @typedef {{ rholang?: string, fields?: Record }} ActionSpec + * @typedef {{ type: 'MasterURI' | 'number' | 'string' | 'set' | 'uri' | 'walletRevAddr' | 'MasterURI', value?: string }} FieldSpec + * @type {Record} + */ +let actions; + +// import { actions } from './actions.js'; import { RholangGrammar } from './prism-rholang'; // TODO(#185): stop pretending MasterURI is a design-time constant. @@ -215,7 +224,7 @@ function rhoBody(tmp) { * @typedef {{[refID: string]: { shortDesc: string, docLink?: string, yesAddr: string, noAddr: string, abstainAddr: string }}} QAs * @typedef {{label: string, info?: any, rest?: any[], timestamp?: number }} LogEvent */ -export function buildUI({ +export async function buildUI({ html, formValue, busy, @@ -230,7 +239,6 @@ export function buildUI({ updateHighlight, }) { const rnode = RNode(fetch); - let action = '_select_an_action_'; let network = netFromHost(hostname); /** @type {{ MasterURI: string, observer: Observer, validator: Validator, admin: import('rchain-api/src/rnode').RNodeAdmin }} shard */ let shard; @@ -287,23 +295,16 @@ export function buildUI({ async setAction(value) { if (typeof value !== 'string') return; action = value; - const { fields = {}, filename } = actions[action]; + const { fields = {}, rholang } = actions[action]; const init = fromEntries( entries(fields).map(([name, { value }]) => [name, value || '']), ); state.fields = init; matchBody = ''; - if (filename) { + if (rholang) { term = null; - await busy( - '#deploy', - fetch(filename).then((reply) => - reply.text().then((text) => { - matchBody = rhoBody(text); - state.fields = init; // redraw - }), - ), - ); + matchBody = rhoBody(rholang) + state.fields = init; // redraw } }, get fields() { @@ -394,32 +395,41 @@ export function buildUI({ }); }, }; + state.network = network; // set up shard of initial network + + mount('#netControl', networkControl(state, { html })); + + let rControl = runControl(state, { + html, + formValue, + busy, + clock, + getEthProvider, + setTimeout, + }); + + let aControl = await actionControl(state, { + html, + getEthProvider, + codeTextArea, + updateHighlight, + }, + rControl.explore, + ); + let action = 'checkBalance.rho'; state.setAction(action); // compute initial term - state.network = network; // set up shard of initial network mount( '#actionControl', - actionControl(state, { - html, - getEthProvider, - codeTextArea, - updateHighlight, - }), + aControl ); - mount('#netControl', networkControl(state, { html })); mount( '#runControl', - runControl(state, { - html, - formValue, - busy, - clock, - getEthProvider, - setTimeout, - }), + rControl, ); + mount('#groupControl', groupControl(state, { html })); mount('#signIn', signIn(state, { html, formValue, busy, getEthProvider })); mount('#exploreControl', ballotControl(state, { html, formValue, busy })); @@ -457,26 +467,46 @@ function fixIndent(code) { } /** + * shard: { observer: Observer, validator: Validator, admin: import('rchain-api/src/rnode').RNodeAdmin }, + * * @param {{ * action: string, * setAction: (a: string) => Promise, * fields: Record, * term: string?, - * shard: { MasterURI: string }, + * results: RhoExpr[], + * shard: { MasterURI: string, observer: Observer }, * }} state * @param {HTMLBuilder & EthSignAccess & { codeTextArea: HTMLElement, updateHighlight: (text: string | null) => void }} io + * @param {(term: string?) => Promise} explore */ -function actionControl( +async function actionControl( state, { html, getEthProvider, codeTextArea, updateHighlight }, + explore, ) { + const obs = state.shard.observer; + try { + const term = `new ret, ret2, lookup(\`rho:registry:lookup\`), lch in { lookup!(${state.shard.MasterURI}, *lch)|for (l<-lch){l!("ActionDictionary", *ret2)|for(r<-ret2){r!(*ret)}}}`; + console.log('explore...'); + console.log('term:' + term); + let { expr, block} = await obs.exploratoryDeploy(term); + actions = RhoExpr.parse(expr[0]); + entries(actions).forEach(([k, v]) => { + actions[k].rholang = v.rholang.replace(/\\"/g,"\""); + }); + console.log('... explore done.'); + console.log('state.results: ' + state.results); + } catch (err) { + console.log('error ' + err.message); + } const options = (/** @type {string[]} */ ids) => - ids.map( - (id) => + ids.map( + (id) => html``, - ); + ); const metaMaskP = getEthProvider().then((ethereum) => MetaMaskAccount(ethereum), @@ -538,7 +568,7 @@ function actionControl( /* Not sure this should be in the Mithril view pattern. The element for code editing used to be created here. It's been moved to participate.html and enhanced with syntax - highlighting, so this is the obvious place to update with new action data. + highlighting, so this still seems the obvious place to update with new action data. */ codeTextArea.value = state.term; updateHighlight(state.term); @@ -604,7 +634,7 @@ function runControl( obs.exploratoryDeploy(term), ); console.log('... explore done.'); - state.results = expr; + state.results = await expr; } catch (err) { state.problem = err.message; } @@ -682,6 +712,7 @@ function runControl( } return freeze({ + explore: explore, view() { return html`