diff --git a/convex-core/src/main/cvx/convex/core/core.cvx b/convex-core/src/main/cvx/convex/core/core.cvx index 124784c2f..aa45bd2bf 100644 --- a/convex-core/src/main/cvx/convex/core/core.cvx +++ b/convex-core/src/main/cvx/convex/core/core.cvx @@ -593,10 +593,7 @@ :examples [{:code "(resolve convex.asset)"}] :signature [{:params [& args]}]}} [sym] - `(call* *registry* - 0 - 'cns-resolve - (quote ~sym))) + `(~*registry*/resolve (quote ~sym))) (defmacro import ^{:doc {:description ["Imports a library for use in the current environment." diff --git a/convex-core/src/main/cvx/convex/core/registry.cvx b/convex-core/src/main/cvx/convex/core/registry.cvx index 9eb4b6b24..7971501e9 100644 --- a/convex-core/src/main/cvx/convex/core/registry.cvx +++ b/convex-core/src/main/cvx/convex/core/registry.cvx @@ -53,10 +53,13 @@ ;; Map of `path vector` -> `segment name` -> `[value trust-monitor meta child]` ;; Where: ;; value = Target value for CNS resolution, usually an address or scoped address -;; trust-monitor = controller for this CNS entry +;; trust-monitor = controller for this CNS record ;; meta = metadata field ;; child = child CNS node, may be nil. Usually a scoped address defining an actor and a path key e.g. [#5675 "bob"] -;; +;; +;; Trust monitor may be called with following actions: +;; :update - Update CNS record +;; ;; Node key is implementation defined in general, but for main registry uses: ;; Empty vector for CNS root ;; Vector of segment strings for paths @@ -78,6 +81,14 @@ (split (name sym) \.) (fail :ARGUMENT "CNS name must be a Symbol"))) +(defn -check-values [values] + (cond + (vector? values) + (cond + (= 4 (count values)) :OK + (fail :ARGUMENT "CNS record must have 4 elements")) + (fail :ARGUMENT "CNS record values must be a Vymbol"))) + ;; ======================================================== ;; CNS User API - See CAD014 @@ -117,15 +128,17 @@ (get (read sym) 0)) (defn create ^{ - :doc {:description "Creates a CNS entry with given reference, controller and metadata" + :doc {:description "Creates a CNS entry with given data [value, controller, metadata, child]" :examples [{:code "(*registry*/create 'my.actor.name target *address* {:some :metadata})"}] - :signature [{:params [sym]}]}} - ([sym] (recur sym nil *address* nil nil)) - ([sym addr] (recur sym addr *address* nil nil)) - ([sym addr cont] (recur sym addr cont nil nil)) - ([sym addr cont meta] (recur sym addr cont meta nil)) - ([sym addr cont meta child] - (let [path (-check sym) + :signature [{:params [sym]} + {:params [sym value]} + {:params [sym value cont]} + {:params [sym value cont meta]} + {:params [sym value cont meta child]}]}} + ([sym & vals] + (let [nv (count vals) + _ (cond (> nv 4) (fail :ARITY "Too many CNS record values")) + path (-check sym) n (count path)] (cond (zero? n) (fail :ARGUMENT "CNS path must have at least one segment")) (loop [i 0 @@ -135,109 +148,83 @@ (nil? ref) (fail :STATE (str "No CNS child path at: " (slice path 0 i))) - ;; are we at end of path? if so perform write at current position + ;; are we at end of path? if so, perform write at current position (>= (inc i) n) - (call ref (cns-write pname addr cont meta child) ) - - (if-let [rec (call ref (cns-read pname))] - (recur (inc i) (first rec)) + (let [rec (cond (< nv 4) + (let [evs (call ref (cns-read pname)) + evs (or evs [nil *address* nil nil])] + (concat vals (slice evs nv 4))) + vals) ] + (call ref (cns-write pname rec))) + + (let [rec (call ref (cns-read pname))] + (if-let [child (get rec 3)] + (recur (inc i) child) - ;; need to construct a new (empty) intermediate CNS child node here - (let [nref (call ref (cns-create-node pname cont))] - (call ref (cns-write pname nil cont nil nref) ) - (recur (inc i) nref))) + ;; need to construct a new (empty) intermediate CNS child node here + (let [cont (or (get vals 1) *address*) ;; controller for intermediate node + nref (call ref (cns-create-node pname cont)) + rec (cond rec + (assoc rec 3 nref) ;; update existing child node link + [nil cont nil nref])] + (call ref (cns-write pname rec)) + (recur (inc i) nref)))) )) ) ;; TODO: Not clear what default return value should be? [~*address* path]? ))) +(defn update + ^{:doc {:description "Updates a CNS entry with given value. Record must already exist." + :signature [{:params [sym value]}]}} + [sym value] + (if-let [rec (read sym)] + (apply create sym (assoc rec 0 value)) + (fail :STATE (str "CNS record to update does not exist: " sym)))) + (defn control + ^{:doc {:description "Change controller for a CNS node." + :signature [{:params [name controller]}]}} [sym cont] (if-let [rec (read sym)] - (let [[v c m child] rec] - (update sym v cont m child)) + (apply create sym (assoc rec 1 cont)) (fail :STATE "CNS record does not exist"))) - -(defn change-control - ^{:callable true - :doc {:description "Changes controller for a CNS node." - :examples [{:code "(call *registry* (cns-control 'my.actor trust-monitor-address)"}] - :signature [{:params [name addr]}]}} - [cont] - (let [owners cns-owners - own (get owners *scope*)] - (cond - (trust/trusted? own *caller* :control) - (set! cns-owners (assoc owners *scope* cont)) - (fail :TRUST "No control right for CNS node")))) - +;; private function to get controller for a node (defn -controller [path] (cond - (empty? *scope*) root-controller - (let [[& ps p] *scope*] + (empty? path) root-controller + (let [[& ps p] path] (get-in cns-database [ps p 1])))) ;; ============================================================================ ;; Standard CNS SPI - exprected to be callable by libraries / advanced users -(defn cns-control +(defn change-control ^{:callable true - :doc {:description "Updates a CNS name mapping to set a new controller. May only be performed by a current controller." + :doc {:description "Changes controller for a CNS node. May only be performed by a current controller." :examples [{:code "(call *registry* (cns-control 'my.actor trust-monitor-address)"}] :signature [{:params [name addr]}]}} - [sym controller] - (let [path (-check sym) - record (get cns-database path)] - (when (nil? record) - (fail :STATE "CNS record does not exist")) - (when (not (trust/trusted? (second record) *caller* :control)) - (fail :TRUST "Caller is not trusted with transferring control for that CNS record")) - (set-in! cns-database [path 1] controller))) - -(defn cns-resolve - ^{:callable true - :doc {:description "Resolves a name in the Convex Name Service." - :examples [{:code "(call *registry* (cns-resolve 'convex.registry)"}] - :signature [{:params [addr]}]}} - [sym] - (let [path (-check sym) - record (get cns-database path)] - (if record (first record) nil))) - -(defn cns-update - ^{:callable true - :doc {:description "Updates or adds a name mapping in the Convex Name Service. Only the owner of a CNS record may update the mapping for an existing name" - :examples [{:code "(call *registry* (cns-update 'my.actor addr)"}] - :signature [{:params [name addr]}]}} - ([sym addr] - (recur sym addr nil)) - ([sym addr meta] - (when-not (account addr) - (fail :NOBODY "Can only use an existing account")) - (let [path (-check sym) - record (get cns-database path) - monitor (if record (second record) *caller*)] ;; TODO limit ability to crteate top level CNS - (and record (not (trust/trusted? monitor *caller* :update)) - (fail :TRUST "Unauthorised update to CNS record")) - - (set! cns-database - (assoc cns-database - path - [addr monitor meta]))))) + [controller] + (let [path *scope*] + (when (not (trust/trusted? (get cns-owners path) *caller* :control)) + (fail :TRUST "Formbitten to change controller for CNS node")) + (set-in! cns-owners [path] controller))) (defn cns-create-node ^{:callable true - :doc {:description "Creates a child CNS node." + :doc {:description "Creates a child CNS node, if it does not yet exist. Returns child node scoped reference." :examples [{:code "(call parent-node (cns-create-node \\\"child-name\\\"))"}] :signature [{:params [sym]}]}} [pname owner] - (or (trust/trusted? (get cns-owners *scope*) *caller* :create pname) (fail :TRUST "No permission to create CNS node")) - (let [path (conj *scope* pname)] - (if (get cns-database path) (fail :STATE "CNS node already exists")) - (set-in! cns-owners [path] owner) - (set-in! cns-database [path] {}) - [~*address* path])) + (or (trust/trusted? (get cns-owners *scope*) *caller* :create pname) (fail :TRUST "Forbidden to create CNS node")) + (let [rec (get-in cns-database [*scope* pname]) + _ (if-let [existing (get rec 3)] (return existing)) + path (conj *scope* pname) + ref [~*address* path]] + (set-in! cns-owners [path] owner) ;; new node owner + (set-in! cns-database [path] {}) ;; new mapping to child records + ref)) (defn cns-read ^{:callable true @@ -252,18 +239,21 @@ :doc {:description "Writes a CNS record from this Actor. Assumes a path vector passed in *scope*." :examples [{:code "(call [cns-node cns-key] (cns-write \"my-name\" new-record))"}] :signature [{:params [sym]}]}} - [pname addr cont meta child] + [pname values] + (or (str? pname) (fail :ARGUMENT "CNS path element must be a String")) + (-check-values values) (let [sm (get cns-database *scope*)] - (or (str? pname) (fail :ARGUMENT "CNS path element must be a string")) (or sm (error :STATE "CNS Node key not valid")) (if-let [rec (get sm pname)] ;; This is an existing record, so check record controller - (or (trust/trusted? (get rec 1) *caller* :update) (fail :TRUST "No permission to update CNS record")) - ;; This is a new record, so check create permission TODO use per-node monitor? - (or (trust/trusted? (-controller *scope*) *caller* :create pname) (fail :TRUST "No permission to create CNS record"))) + (or (trust/trusted? (get rec 1) *caller* :update) (fail :TRUST "Forbidden to update CNS record")) + + ;; This is a new record, so check create permission + (or (trust/trusted? (-controller *scope*) *caller* :create pname) (fail :TRUST "Forbidden to create CNS record"))) ;; update record since at this point all required checks have passed - (set-in! cns-database [*scope* pname] [addr cont meta child]))) + (set-in! cns-database [*scope* pname] values) + values)) ;; ========================================= ;; Trust SPI diff --git a/convex-core/src/main/java/convex/core/init/Init.java b/convex-core/src/main/java/convex/core/init/Init.java index b4c708356..c1f642c77 100644 --- a/convex-core/src/main/java/convex/core/init/Init.java +++ b/convex-core/src/main/java/convex/core/init/Init.java @@ -32,7 +32,7 @@ public class Init { /** - * Number of special "goverance" accounts. These hold all unissued coins + * Number of special "governance" accounts. These hold all unissued coins */ public static final int NUM_GOVERNANCE_ACCOUNTS=8; @@ -178,8 +178,11 @@ public static State createBaseState(AccountKey governanceKey, AccountKey genesis // Add the static defined libraries at addresses: TRUST_ADDRESS, REGISTRY_ADDRESS s = addStaticLibraries(s); + + // Add the basic CNS tree + s=addCNSBaseTree(s); - // Reload accounts with the libraries + // Reload accounts with the base libraries accts = s.getAccounts(); } @@ -252,13 +255,11 @@ public static State createBaseState(AccountKey governanceKey, AccountKey genesis private static State addStaticLibraries(State s) { // At this point we have a raw initial State with no user or peer accounts - s = doActorDeploy(s, "/convex/core/registry.cvx"); - s = doActorDeploy(s, "/convex/core/trust.cvx"); + s = doActorDeploy(s, "/convex/core/registry.cvx",false); + s = doActorDeploy(s, "/convex/core/trust.cvx",false); { // Register core library now that registry exists - Context ctx = Context.create(s, INIT_ADDRESS); - ctx = ctx.eval(Reader.read("(call *registry* (cns-update 'convex.core " + CORE_ADDRESS + "))")); - + Context ctx = Context.create(s, INIT_ADDRESS); s = ctx.getState(); s = register(s, CORE_ADDRESS, "Convex Core Library", "Core utilities accessible by default in any account."); @@ -284,10 +285,9 @@ public static State createState(AccountKey genesisKey,List peerKeys) public static State createState(AccountKey governanceKey, AccountKey genesisKey,List peerKeys) { State s=createBaseState(governanceKey, genesisKey, peerKeys); - s = addCNSTree(s); s = addStandardLibraries(s); s = addTestingCurrencies(s); - + s = addCNSExtraTree(s); // Final funds check long finalTotal = s.computeTotalBalance(); @@ -339,9 +339,22 @@ private static State addStandardLibraries(State s) { return s; } - private static State addCNSTree(State s) { + private static State addCNSBaseTree(State s) { Context ctx=Context.create(s, GOVERNANCE_ADDRESS); - ctx=ctx.eval(Reader.read("(*registry*/create 'convex.cns *registry*)")); + ctx=ctx.eval(Reader.read("(*registry*/create 'convex)")); + ctx.getResult(); + + // convex.cns is alias to root cns namespace? + ctx=ctx.eval(Reader.read("(*registry*/create 'convex.cns "+REGISTRY_ADDRESS+" *address* nil [#9 []])")); + ctx.getResult(); + + ctx=ctx.eval(Reader.read("(*registry*/create 'convex.registry "+REGISTRY_ADDRESS+")")); + ctx.getResult(); + + ctx=ctx.eval(Reader.read("(*registry*/create 'convex.core "+CORE_ADDRESS+")")); + ctx.getResult(); + + ctx=ctx.eval(Reader.read("(*registry*/create 'convex.trust "+TRUST_ADDRESS+")")); ctx.getResult(); // check we can get access to general trust monitors @@ -357,6 +370,17 @@ private static State addCNSTree(State s) { s=ctx.getState(); return s; } + + private static State addCNSExtraTree(State s) { + Context ctx=Context.create(s, GOVERNANCE_ADDRESS); + + // ctx=ctx.eval(Reader.read("(*registry*/create 'zoo "+TRUST_ADDRESS+")")); + // ctx.getResult(); + + + s=ctx.getState(); + return s; + } public static Address calcPeerAddress(int userCount, int index) { return Address.create(GENESIS_ADDRESS.longValue() + userCount + index); @@ -365,12 +389,16 @@ public static Address calcPeerAddress(int userCount, int index) { public static Address calcUserAddress(int index) { return Address.create(GENESIS_ADDRESS.longValue() + index); } + + private static State doActorDeploy(State s, String resource) { + return doActorDeploy(s,resource,true); + } // A CVX file contains forms which must be wrapped in a `(do ...)` and deployed as an actor. // First form is the name that must be used when registering the actor. // - private static State doActorDeploy(State s, String resource) { - Context ctx = Context.create(s, INIT_ADDRESS); + private static State doActorDeploy(State s, String resource, boolean addCNS) { + Context ctx = Context.create(s, GOVERNANCE_ADDRESS); ACell ADD_NETWORK_GOVERNANCE=Reader.read("(set-controller "+GOVERNANCE_ADDRESS+")"); try { @@ -384,11 +412,13 @@ private static State doActorDeploy(State s, String resource) { if (ctx.isExceptional()) throw new Error("Error deploying actor: "+resource+"\n" + ctx.getValue()); Address addr=ctx.getResult(); - @SuppressWarnings("unchecked") - AList qsym=(AList) forms.get(0); - Symbol sym=qsym.get(1); - ctx = ctx.eval(Code.cnsUpdate(sym, addr)); - if (ctx.isExceptional()) throw new Error("Error while registering actor:" + ctx.getValue()); + if (addCNS) { + @SuppressWarnings("unchecked") + AList qsym=(AList) forms.get(0); + Symbol sym=qsym.get(1); + ctx = ctx.eval(Code.cnsUpdate(sym, addr,GOVERNANCE_ADDRESS)); + if (ctx.isExceptional()) throw new Error("Error while registering actor:" + ctx.getValue()); + } return ctx.getState(); } catch (IOException e) { @@ -432,7 +462,8 @@ private static State doCurrencyDeploy(State s, AVector row) { if (ctx.isExceptional()) throw new Error("Error adding market liquidity: " + ctx.getValue()); Symbol sym=Symbol.create("currency."+symName); - ctx = ctx.eval(Code.cnsUpdate(sym, addr)); + ctx = ctx.forkWithAddress(GOVERNANCE_ADDRESS); + ctx = ctx.eval(Code.cnsUpdate(sym, addr,GOVERNANCE_ADDRESS)); if (ctx.isExceptional()) throw new Error("Error registering currency in CNS: " + ctx.getValue()); return ctx.getState(); } diff --git a/convex-core/src/main/java/convex/core/lang/Code.java b/convex-core/src/main/java/convex/core/lang/Code.java index 45cf41dfc..6bf57b150 100644 --- a/convex-core/src/main/java/convex/core/lang/Code.java +++ b/convex-core/src/main/java/convex/core/lang/Code.java @@ -23,9 +23,10 @@ public class Code { * @param addr Address to associate with CNS record e.g. #123 * @return Code for CNS call */ - public static AList cnsUpdate(Symbol name, Address addr) { - AList cmd=List.of(Symbols.CNS_UPDATE, Code.quote(name), addr); - return List.of(Symbols.CALL, Init.REGISTRY_ADDRESS, cmd ); + public static AList cnsUpdate(Symbol name, Address addr, ACell controller) { + AList update=List.of(Symbols.LOOKUP,Init.REGISTRY_ADDRESS,Symbols.CREATE); + AList cmd=List.of(update, quote(name),addr, controller); + return cmd; } /** diff --git a/convex-core/src/main/java/convex/core/lang/Symbols.java b/convex-core/src/main/java/convex/core/lang/Symbols.java index 9375ec5e9..950abcead 100644 --- a/convex-core/src/main/java/convex/core/lang/Symbols.java +++ b/convex-core/src/main/java/convex/core/lang/Symbols.java @@ -340,6 +340,7 @@ public class Symbols { public static final Symbol MEMORY = intern("memory"); public static final Symbol MEMORY_VALUE = intern("memory-value"); public static final Symbol PROTOCOL = intern("protocol"); + public static final Symbol CREATE = intern("create"); diff --git a/convex-core/src/test/java/convex/actors/RegistryTest.java b/convex-core/src/test/java/convex/actors/RegistryTest.java index 4fbb3f01f..8741413e4 100644 --- a/convex-core/src/test/java/convex/actors/RegistryTest.java +++ b/convex-core/src/test/java/convex/actors/RegistryTest.java @@ -1,7 +1,7 @@ package convex.actors; import static convex.test.Assertions.assertArgumentError; -import static convex.test.Assertions.assertNobodyError; +import static convex.test.Assertions.assertStateError; import static convex.test.Assertions.assertTrustError; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; @@ -39,69 +39,62 @@ public void testRegistryContract() throws IOException { assertEquals(ddo, ctx.actorCall(REG, 0, "lookup", ctx.getAddress()).getResult()); } - @Test - public void testRegistryCNS() throws IOException { - Context ctx = context(); - - assertEquals(REG, eval(ctx, "(call *registry* (cns-resolve 'convex.registry))")); - } - @Test public void testRegistryCNSUpdate() throws IOException { - Context ctx = context(); + Context ctx = context().forkWithAddress(Init.GOVERNANCE_ADDRESS); + ctx=exec(ctx,"(def ^:static reg #9)"); - assertNull(eval(ctx, "(call *registry* (cns-resolve 'convex.test.foo))")); + assertNull(eval(ctx, "(resolve convex.test.foo)")); // Real Address we want for CNS mapping final Address badAddr = Samples.BAD_ADDRESS; - ctx = step(ctx, "(call *registry* (cns-update 'convex.test.foo " + badAddr + "))"); - assertNobodyError(ctx); + ctx = step(ctx, "(reg/update 'convex.test.foo " + badAddr + ")"); + assertStateError(ctx); // Should fail, not a Symbol - ctx = step(ctx, "(call *registry* (cns-update \"convex.test.foo\" #1))"); + ctx = step(ctx, "(reg/update \"convex.test.foo\" #1)"); assertArgumentError(ctx); final Address realAddr = Address.create(1); // Init address, FWIW - ctx = exec(ctx, "(call *registry* (cns-update 'convex.test.foo " + realAddr + "))"); + ctx = exec(ctx, "(reg/create 'convex.test.foo " + realAddr + ")"); - assertEquals(realAddr, eval(ctx, "(call *registry* (cns-resolve 'convex.test.foo))")); + assertEquals(realAddr, eval(ctx, "(reg/resolve 'convex.test.foo)")); { // Check VILLAIN can't steal CNS mapping Context c = ctx.forkWithAddress(VILLAIN); // VILLAIN shouldn't be able to use update on existing CNS mapping - assertTrustError(step(c, "(call *registry* (cns-update 'convex.test.foo *address*))")); + assertTrustError(step(c, "(#9/update 'convex.test.foo *address*)")); // original mapping should be held - assertEquals(realAddr, eval(c, "(call *registry* (cns-resolve 'convex.test.foo))")); + assertEquals(realAddr, eval(c, "(#9/resolve 'convex.test.foo)")); } { // Check Transfer of control to VILLAIN - Context c = exec(ctx, "(call *registry* (cns-control 'convex.test.foo " + VILLAIN + "))"); + Context c = exec(ctx, "(reg/control 'convex.test.foo " + VILLAIN + ")"); - // HERO shouldn't be able to use update or control any more - assertTrustError(step(c, "(call *registry* (cns-update 'convex.test.foo *address*))")); - assertTrustError(step(c, "(call *registry* (cns-control 'convex.test.foo *address*))")); + // This address shouldn't be able to use update or control any more + assertTrustError(step(c, "(reg/update 'convex.test.foo *address*)")); + assertTrustError(step(c, "(reg/control 'convex.test.foo *address*)")); // Switch to VILLAIN c = c.forkWithAddress(VILLAIN); // Change mapping - c = exec(c, "(call *registry* (cns-update 'convex.test.foo *address*))"); - assertEquals(VILLAIN, eval(c, "(call *registry* (cns-resolve 'convex.test.foo))")); + c = exec(c, "(*registry*/update 'convex.test.foo *address*)"); + assertEquals(VILLAIN, eval(c, "(*registry*/resolve 'convex.test.foo)")); } - { // Check VILLAIN can create new mapping - // TODO probably shouldn't be free-for-all? + { // Check VILLAIN can create new mapping ?? TODO: where?? - Context c = ctx.forkWithAddress(VILLAIN); + //Context c = ctx.forkWithAddress(VILLAIN); // VILLAIN shouldn't be able to use update on existing CNS mapping - c = exec(c, "(call *registry* (cns-update 'convex.villain *address*))"); + //c = exec(c, "(*registry*/create 'convex.villain *address*)"); // original mapping should be held - assertEquals(VILLAIN, eval(c, "(call *registry* (cns-resolve 'convex.villain))")); + // assertEquals(VILLAIN, eval(c, "(*registry*/resolve 'convex.villain)")); } } } diff --git a/convex-core/src/test/java/convex/core/init/InitTest.java b/convex-core/src/test/java/convex/core/init/InitTest.java index 81dffef5c..926e7c7d1 100644 --- a/convex-core/src/test/java/convex/core/init/InitTest.java +++ b/convex-core/src/test/java/convex/core/init/InitTest.java @@ -75,20 +75,20 @@ protected InitTest() { @Test public void testDeploy() { // CNS resolution for standard libraries - assertNotNull(evalA("(call *registry* (cns-resolve 'asset.box))")); - assertNotNull(evalA("(call *registry* (cns-resolve 'asset.box.actor))")); - assertNotNull(evalA("(call *registry* (cns-resolve 'asset.nft.simple))")); - assertNotNull(evalA("(call *registry* (cns-resolve 'asset.nft.tokens))")); - assertNotNull(evalA("(call *registry* (cns-resolve 'convex.asset))")); - assertNotNull(evalA("(call *registry* (cns-resolve 'convex.fungible))")); - assertNotNull(evalA("(call *registry* (cns-resolve 'convex.play))")); - assertNotNull(evalA("(call *registry* (cns-resolve 'convex.trusted-oracle.actor))")); - assertNotNull(evalA("(call *registry* (cns-resolve 'convex.oracle))")); - assertNotNull(evalA("(call *registry* (cns-resolve 'torus.exchange))")); - - assertEquals(Init.CORE_ADDRESS, eval("(call *registry* (cns-resolve 'convex.core))")); - assertEquals(Init.REGISTRY_ADDRESS, eval("(call *registry* (cns-resolve 'convex.registry))")); - assertEquals(Init.TRUST_ADDRESS, eval("(call *registry* (cns-resolve 'convex.trust))")); + assertNotNull(evalA("(resolve asset.box)")); + assertNotNull(evalA("(resolve asset.box.actor)")); + assertNotNull(evalA("(resolve asset.nft.simple)")); + assertNotNull(evalA("(resolve asset.nft.tokens)")); + assertNotNull(evalA("(resolve convex.asset)")); + assertNotNull(evalA("(resolve convex.fungible)")); + assertNotNull(evalA("(resolve convex.play)")); + assertNotNull(evalA("(resolve convex.trusted-oracle.actor)")); + assertNotNull(evalA("(resolve convex.oracle)")); + assertNotNull(evalA("(resolve torus.exchange)")); + + assertEquals(Init.CORE_ADDRESS, eval("(resolve convex.core)")); + assertEquals(Init.REGISTRY_ADDRESS, eval("(resolve convex.registry)")); + assertEquals(Init.TRUST_ADDRESS, eval("(resolve convex.trust)")); } @Test diff --git a/convex-core/src/test/java/convex/core/lang/CoreTest.java b/convex-core/src/test/java/convex/core/lang/CoreTest.java index f44f59259..fabfcb100 100644 --- a/convex-core/src/test/java/convex/core/lang/CoreTest.java +++ b/convex-core/src/test/java/convex/core/lang/CoreTest.java @@ -2592,7 +2592,7 @@ public void testImport() { } { // test deploy and CNS import in a single form. See #107 - Context ctx2=step(ctx,"(do (let [addr (deploy nil)] (call *registry* (cns-update 'foo addr)) (import foo :as foo2)))"); + Context ctx2=step(ctx,"(query-as #6 `(let [addr (deploy nil)] (*registry*/create 'foo addr) (import foo :as foo2)))"); assertNotError(ctx2); } diff --git a/convex-core/src/test/java/convex/lib/BoxTest.java b/convex-core/src/test/java/convex/lib/BoxTest.java index 9f834d75a..eb187b539 100644 --- a/convex-core/src/test/java/convex/lib/BoxTest.java +++ b/convex-core/src/test/java/convex/lib/BoxTest.java @@ -26,11 +26,11 @@ public class BoxTest extends ACVMTest { ctx=TestState.CONTEXT.fork(); // Import basic NFTs - ctx=step(ctx,"(import asset.box :as box)"); - ctx=step(ctx,"(import asset.box.actor :as box.actor)"); + ctx=exec(ctx,"(import asset.box :as box)"); + ctx=exec(ctx,"(import asset.box.actor :as box.actor)"); BOX=ctx.getResult(); - ctx=step(ctx,"(import convex.asset :as asset)"); + ctx=exec(ctx,"(import convex.asset :as asset)"); return ctx; } diff --git a/convex-core/src/test/java/convex/lib/CNSTest.java b/convex-core/src/test/java/convex/lib/CNSTest.java index 9075082a2..09fc7b98c 100644 --- a/convex-core/src/test/java/convex/lib/CNSTest.java +++ b/convex-core/src/test/java/convex/lib/CNSTest.java @@ -34,6 +34,7 @@ public class CNSTest extends ACVMTest { assertEquals(Init.REGISTRY_ADDRESS,eval("*registry*")); assertEquals(Init.REGISTRY_ADDRESS,eval("cns")); assertEquals(Init.REGISTRY_ADDRESS,eval("@convex.registry")); + assertEquals(Init.REGISTRY_ADDRESS,eval("(call cns (resolve 'convex.registry))")); // TODO: fix this // assertEquals(Init.REGISTRY_ADDRESS,eval("@cns")); @@ -67,16 +68,23 @@ public class CNSTest extends ACVMTest { assertNull(eval(ctx,"(*registry*/resolve 'foo.null.boo)")); } + /** + * What happens if we insert a bad CNS node that crashes? + */ + @Test public void testBadNode() { + // Context ctx=context(); + + } + @Test public void testCreateTopLevel() { // HERO shouldn't be able to create a top level CNS entry assertTrustError(step("(*registry*/create 'foo)")); // NEed governance address to be able to create a top level CNS entry Context ctx=context().forkWithAddress(Init.GOVERNANCE_ADDRESS); - ctx=step(ctx,"(import convex.trust :as trust)"); - ctx=(step(ctx,"(*registry*/create 'foo #17)")); - assertNotError(ctx); - ctx=step(ctx,"(def ref [*registry* [\"foo\"]])"); + ctx=exec(ctx,"(import convex.trust :as trust)"); + ctx=exec(ctx,"(*registry*/create 'foo #17)"); + ctx=exec(ctx,"(def ref [*registry* [\"foo\"]])"); AVector ref=ctx.getResult(); assertNotNull(ref); @@ -84,7 +92,7 @@ public class CNSTest extends ACVMTest { assertEquals(Address.create(17),eval(ctx,"(*registry*/resolve 'foo)")); - ctx=(step(ctx,"(*registry*/create 'foo #666)")); + ctx=exec(ctx,"(*registry*/create 'foo #666)"); assertEquals(Address.create(666),eval(ctx,"(*registry*/resolve 'foo)")); // HERO still shouldn't be able to update a top level CNS entry diff --git a/convex-core/src/test/java/convex/lib/TrustTest.java b/convex-core/src/test/java/convex/lib/TrustTest.java index 7a13cbdc2..43795db6f 100644 --- a/convex-core/src/test/java/convex/lib/TrustTest.java +++ b/convex-core/src/test/java/convex/lib/TrustTest.java @@ -18,6 +18,7 @@ import convex.core.data.Keywords; import convex.core.data.Vectors; import convex.core.init.BaseTest; +import convex.core.init.Init; import convex.core.lang.ACVMTest; import convex.core.lang.Context; import convex.test.Samples; @@ -30,7 +31,7 @@ protected TrustTest() throws IOException { } @Override protected Context buildContext(Context ctx) { - String importS = "(import convex.trust :as trust)"; + String importS = "(def trust "+Init.TRUST_ADDRESS+")"; ctx = exec(ctx, importS); trusted = (Address)ctx.getResult(); return ctx;