diff --git a/convex-core/src/main/cvx/convex/registry.cvx b/convex-core/src/main/cvx/convex/registry.cvx index 5be318015..a85fc8800 100644 --- a/convex-core/src/main/cvx/convex/registry.cvx +++ b/convex-core/src/main/cvx/convex/registry.cvx @@ -23,7 +23,7 @@ (def trust ^{:private true} - ;; Address of the `convex.trust`, it is deployed right after this account, hence it is predictable. + ;; Address of `convex.trust`, it is deployed right after this account, hence it is predictable. (address (inc (long *address*)))) ;;;;;;;;;; Address metadata registry @@ -52,14 +52,20 @@ ;; CNS root reference, i.e. this registry with an empty vector key (def root [~*address* []]) -;; Map of `node key` -> `segment symbol` -> `[path trust-monitor meta]` +;; Map of `node key` -> `segment symbol` -> `[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 +;; 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"] +;; ;; Node key is implementation defined in general, but for main registry uses: ;; Empty vector for CNS root ;; vector of segment strings for child paths (def cns-database ^{:private? true} - {[] {"init" [#1 #1 nil]}}) + {[] {"init" [#1 #1 nil nil]}}) ;; Controllers for each CNS node managed under this actor ;; Default root is controlled by INIT account @@ -71,7 +77,7 @@ {[] #1}) (defn read ^{ - :doc {:description "Reads a CNS record as a [addr controller metadata] vector, or nil if record does not exist." + :doc {:description "Reads a CNS record as a [value controller metadata child] vector, or nil if record does not exist." :examples [{:code "(*registry*/resolve 'my.actor.name)"}] :signature [{:params [sym]}]}} ([sym] diff --git a/convex-core/src/main/cvx/convex/user.cvx b/convex-core/src/main/cvx/convex/user.cvx new file mode 100644 index 000000000..240a1f0d7 --- /dev/null +++ b/convex-core/src/main/cvx/convex/user.cvx @@ -0,0 +1,3 @@ +;; CNS implementation and registry for `user.xxxx` names + +'user \ No newline at end of file diff --git a/convex-core/src/main/java/convex/core/Constants.java b/convex-core/src/main/java/convex/core/Constants.java index 0ead00a8b..5088f82e3 100644 --- a/convex-core/src/main/java/convex/core/Constants.java +++ b/convex-core/src/main/java/convex/core/Constants.java @@ -47,17 +47,18 @@ public class Constants { public static final long INITIAL_MEMORY_POOL = 1000000L; /** - * Initial memory price per byte + * Initial memory price per byte 0.001 Convex Gold */ public static final long INITIAL_MEMORY_PRICE = 1000000L; /** - * Memory Pool of growth increment 1mn + * Memory Pool of growth increment 1mb */ public static final long MEMORY_POOL_GROWTH = 1000000L; /** - * Memory Pool of growth interval (once per day) + * Memory Pool of growth interval (once per day). + * This means regular price drops in memory pool */ public static final long MEMORY_POOL_GROWTH_INTERVAL = 1000L*24*3600; diff --git a/convex-core/src/main/java/convex/core/data/AccountKey.java b/convex-core/src/main/java/convex/core/data/AccountKey.java index 5216e21ff..518144f9a 100644 --- a/convex-core/src/main/java/convex/core/data/AccountKey.java +++ b/convex-core/src/main/java/convex/core/data/AccountKey.java @@ -24,6 +24,11 @@ public class AccountKey extends AArrayBlob { public static final int LENGTH_BITS = LENGTH * 8; + /** + * A null Account Key + */ + public static final AccountKey NULL = null; + private AccountKey(byte[] data, int offset, int length) { super(data, offset, length); this.memorySize=0; diff --git a/convex-core/src/main/java/convex/core/data/AccountStatus.java b/convex-core/src/main/java/convex/core/data/AccountStatus.java index 8bf8cb3f7..0b835f2f8 100644 --- a/convex-core/src/main/java/convex/core/data/AccountStatus.java +++ b/convex-core/src/main/java/convex/core/data/AccountStatus.java @@ -73,7 +73,7 @@ private AccountStatus(long sequence, AccountKey publicKey, long balance, } /** - * Create a regular account, with the specified balance and zero allowance + * Create a regular account, with the specified balance and zero memory allowance * * @param sequence Sequence number * @param balance Convex Coin balance of Account @@ -84,16 +84,6 @@ public static AccountStatus create(long sequence, long balance, AccountKey key) return new AccountStatus(sequence, key, balance, 0L,null,null,null,null,null); } - /** - * Create a governance account. - * - * @param balance Balance for governance account - * @return New governance AccountStatus - */ - public static AccountStatus createGovernance(long balance) { - return new AccountStatus(Constants.INITIAL_SEQUENCE, null, balance, 0L,null,null,null,null,null); - } - public static AccountStatus createActor() { return new AccountStatus(Constants.INITIAL_SEQUENCE, null, 0L,0L,null,null,null,null,null); } 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 79d0534d9..6e9881b7b 100644 --- a/convex-core/src/main/java/convex/core/init/Init.java +++ b/convex-core/src/main/java/convex/core/init/Init.java @@ -54,7 +54,7 @@ public class Init { // Controller for genesis peer address public static final Address GENESIS_PEER_ADDRESS = Address.create(12); - // First user of Protonet + // First user of Protonet, i.e. @mikera public static final Address FIRST_USER_ADDRESS = Address.create(13); // Constants @@ -68,68 +68,107 @@ public class Init { * @return Base genesis state */ public static State createBaseState(List genesisKeys) { + AccountKey genesisKey=genesisKeys.get(0); + // accumulators for initial state maps Index peers = EMPTY_PEERS; AVector accts = Vectors.empty(); long supply = Constants.MAX_SUPPLY; - // Initial accounts - accts = addGovernanceAccount(accts, NULL_ADDRESS, Coin.ZERO); // Null account - accts = addGovernanceAccount(accts, INIT_ADDRESS, Coin.ZERO); // Initialisation Account - - // Foundation fund for startup - long foundation = 1*Coin.EMERALD; - accts = addGovernanceAccount(accts, FOUNDATION_ADDRESS, foundation); // 75% for investors - supply-=foundation; + // Null account, cannot ever be used by anyone + { + AccountStatus nullAccount=AccountStatus.create(Coin.ZERO,AccountKey.NULL); + accts=accts.conj(nullAccount); + } - // Foundation reserve fund (rest of foundation 25%) - long reserve = 248*Coin.EMERALD; - accts = addGovernanceAccount(accts, RESERVE_ADDRESS, reserve); // 24% Foundation - supply -= reserve; - - // Reserve for distribution via release curve - long rootFund = 740 * Coin.EMERALD; - accts = addGovernanceAccount(accts, UNRELEASED_ADDRESS, rootFund); - supply -= rootFund; + // "init" Account, used only for network setup and update. Doesn't need coins because we run state updates directly + { + AccountStatus initAccount=AccountStatus.create(Coin.ZERO,AccountKey.NULL); + accts = addAccount(accts, INIT_ADDRESS, initAccount); + } + + // Foundation fund for initial operations and fallback governance + { + long foundationFund = 1*Coin.EMERALD; + AccountStatus foundationAccount=AccountStatus.create(foundationFund,genesisKey); + accts = addAccount(accts, FOUNDATION_ADDRESS, foundationAccount); + supply-=foundationFund; + } - // Initial account for release curve distribution - long mainPool = 10 * Coin.EMERALD; - accts = addGovernanceAccount(accts, DISTRIBUTION_ADDRESS, mainPool); - supply -= mainPool; + // Foundation reserve fund (rest of foundation 25%, controlled by foundation account) + { + long reserve = 248*Coin.EMERALD; + AccountStatus reserveAccount=AccountStatus.create(reserve,AccountKey.NULL); + reserveAccount=reserveAccount.withController(FOUNDATION_ADDRESS); + accts = addAccount(accts, RESERVE_ADDRESS, reserveAccount); // 24% Foundation + supply -= reserve; + } + + // Reserve for distribution via release curve - 74% for coin purchasers + { + long releaseCurveFund = 740 * Coin.EMERALD; + AccountStatus releaseCurveAccount=AccountStatus.create(releaseCurveFund,AccountKey.NULL); + releaseCurveAccount=releaseCurveAccount.withController(FOUNDATION_ADDRESS); + accts = addAccount(accts, UNRELEASED_ADDRESS, releaseCurveAccount); + supply -= releaseCurveFund; + } + + // Initial account for release curve distribution - 1% for initial coin purchasers + { + long distributionFund = 10 * Coin.EMERALD; + AccountStatus releaseCurveAccount=AccountStatus.create(distributionFund,AccountKey.NULL); + releaseCurveAccount=releaseCurveAccount.withController(FOUNDATION_ADDRESS); + accts = addAccount(accts, DISTRIBUTION_ADDRESS, releaseCurveAccount); + supply -= distributionFund; + } - long govern = 1 * Coin.DIAMOND; - accts = addGovernanceAccount(accts, GOVERNANCE_ADDRESS, govern); - supply -= govern; + // Governance Address, used to manage key network operations e.g. CNS root changes + { + long governFund = 1 * Coin.DIAMOND; + AccountStatus governanceAccount=AccountStatus.create(governFund,AccountKey.NULL); + governanceAccount=governanceAccount.withController(FOUNDATION_ADDRESS); + accts = addAccount(accts, GOVERNANCE_ADDRESS, governanceAccount); + supply -= governFund; + } - long admin = 1 * Coin.DIAMOND; - accts = addGovernanceAccount(accts, ADMIN_ADDRESS, admin ); - supply -= admin; + // Admin address, used for non-critical operations + { + long admin = 1 * Coin.DIAMOND; + AccountStatus governanceAccount=AccountStatus.create(admin,genesisKey); + governanceAccount=governanceAccount.withController(FOUNDATION_ADDRESS); + accts = addAccount(accts, ADMIN_ADDRESS, governanceAccount); + supply -= admin; + } + + // Core library at static address: CORE_ADDRESS + accts = addCoreLibrary(accts); + // Core Account should now be fully initialised + // BASE_USER_ADDRESS = accts.size(); + // Always have at least one user and one peer setup int keyCount = genesisKeys.size(); assert(keyCount > 0); - // Core library at static address: CORE_ADDRESS - accts = addCoreLibrary(accts, CORE_ADDRESS); - // Core Account should now be fully initialised - // BASE_USER_ADDRESS = accts.size(); // Build globals AVector globals = Constants.INITIAL_GLOBALS; - // Create the initial state + // Create the initial state with static libraries and memory allowances State s = State.create(accts, peers, globals, EMPTY_SCHEDULE); - supply-=s.getGlobalMemoryValue().longValue(); - - // There should be at least 100,000 Convex Gold for genesis to succeed, to be distributed to genesis account(s) - assert(supply>100000*Coin.GOLD); - - // Add the static defined libraries at addresses: TRUST_ADDRESS, REGISTRY_ADDRESS - s = addStaticLibraries(s); - - // Reload accounts with the libraries - accts = s.getAccounts(); + { + supply-=s.getGlobalMemoryValue().longValue(); + + // There should be at least 100,000 Convex Gold for genesis to succeed, to be distributed to genesis account(s) + assert(supply>100000*Coin.GOLD); + + // Add the static defined libraries at addresses: TRUST_ADDRESS, REGISTRY_ADDRESS + s = addStaticLibraries(s); + + // Reload accounts with the libraries + accts = s.getAccounts(); + } // Set up initial user accounts, one for each genesis key. assert(accts.count() == GENESIS_ADDRESS.longValue()); @@ -175,7 +214,6 @@ public static State createBaseState(List genesisKeys) { assert(peerFunds == 0L); } - // Add the new accounts to the State s = s.withAccounts(accts); // Add peers to the State @@ -266,25 +304,24 @@ private static State addStandardLibraries(State s) { s = doActorDeploy(s, "convex/trust/whitelist.cvx"); s = doActorDeploy(s, "convex/trust/monitors.cvx"); s = doActorDeploy(s, "convex/governance.cvx"); + // s = doActorDeploy(s, "convex/user.cvx"); return s; } private static State addCNSTree(State s) { Context ctx=Context.createFake(s, INIT_ADDRESS); - ctx=ctx.eval(Reader.read("(do (*registry*/create 'user.init))")); - ctx.getResult(); + //ctx=ctx.eval(Reader.read("(do (*registry*/create 'user.init))")); + //ctx.getResult(); + // check we can get access to general trust monitors + //ctx=ctx.eval(Reader.read("(import convex.trust.monitors :as mon)")); + //ctx.getResult(); - ctx=ctx.eval(Reader.read("(import convex.trust.monitors :as mon)")); - ctx.getResult(); - - ctx=ctx.eval(Reader.read("(def tmon (mon/permit-actions :create))")); - ctx.getResult(); - - - ctx=ctx.eval(Reader.read("(do ("+TRUST_ADDRESS+"/change-control [*registry* [\"user\"]] tmon))")); - ctx.getResult(); + //ctx=ctx.eval(Reader.read("(def tmon (mon/permit-actions :create))")); + //ctx.getResult(); + //ctx=ctx.eval(Reader.read("(do ("+TRUST_ADDRESS+"/change-control [*registry* [\"user\"]] tmon))")); + //ctx.getResult(); s=ctx.getState(); return s; @@ -375,17 +412,16 @@ private static Index addPeer(Index addGovernanceAccount(AVector accts, Address a, long balance) { - long num=a.longValue(); - if (accts.count() != num) throw new Error("Incorrect initialisation address: " + a); - AccountStatus as = AccountStatus.createGovernance(balance); - accts = accts.conj(as); + + private static AVector addAccount(AVector accts, Address address, AccountStatus account) { + long num=address.longValue(); + if (accts.count() != num) throw new Error("Incorrect initialisation address: " + address); + accts = accts.conj(account); return accts; } - private static AVector addCoreLibrary(AVector accts, Address a) { - if (accts.count() != a.longValue()) throw new Error("Incorrect core library address: " + a); + private static AVector addCoreLibrary(AVector accts) { + if (accts.count() != CORE_ADDRESS.longValue()) throw new Error("Incorrect core library address: " + accts.count()); AccountStatus as = AccountStatus.createActor(); as=as.withEnvironment(Core.ENVIRONMENT); diff --git a/convex-core/src/test/java/convex/lib/CNSTest.java b/convex-core/src/test/java/convex/lib/CNSTest.java index 98e992f4d..7c9289c05 100644 --- a/convex-core/src/test/java/convex/lib/CNSTest.java +++ b/convex-core/src/test/java/convex/lib/CNSTest.java @@ -35,7 +35,7 @@ public class CNSTest extends ACVMTest { Address init=eval("(*registry*/resolve 'init)"); assertEquals(Init.INIT_ADDRESS,init); - assertEquals(eval("[#1 #1 nil]"), eval("(*registry*/read 'init)")); + assertEquals(eval("[#1 #1 nil nil]"), eval("(*registry*/read 'init)")); } @Test public void testCreateNestedFromTop() { diff --git a/convex-gui/src/main/java/convex/gui/components/account/AccountsPanel.java b/convex-gui/src/main/java/convex/gui/components/account/AccountsPanel.java index 0df6681fe..8f597161f 100644 --- a/convex-gui/src/main/java/convex/gui/components/account/AccountsPanel.java +++ b/convex-gui/src/main/java/convex/gui/components/account/AccountsPanel.java @@ -98,7 +98,7 @@ public AccountsPanel(Convex convex,StateModel model) { CellRenderer cr=new CellRenderer(JLabel.RIGHT); cr.setToolTipText("Sequence number of the account. This is the total number of user transactions executed."); table.getColumnModel().getColumn(2).setCellRenderer(cr); - table.getColumnModel().getColumn(2).setPreferredWidth(70); + table.getColumnModel().getColumn(2).setPreferredWidth(60); } { @@ -132,7 +132,7 @@ public AccountsPanel(Convex convex,StateModel model) { { // Account public key AccountKeyRenderer cr=new AccountKeyRenderer(); cr.setToolTipText("Public key of the account. Used to validate transactions from users."); - table.getColumnModel().getColumn(7).setPreferredWidth(200); + table.getColumnModel().getColumn(7).setPreferredWidth(150); table.getColumnModel().getColumn(7).setCellRenderer(cr); }