Session 7: NEAR Accounts and Key Registration Presentation by Sherif Abushadi & Matt Lockyer Transcript Provided by 4NTS Note: Some Parts Not Included Due To Sound or Conversation Watch The Full Video For Certainty and Quoting For Other Purposes Start: The account system for NEAR differs from Ethereum in the sense that it's not all about key pairs, it's about accounts. A lot of people coming from Ethereum are just coming from other blockchains, and think that its all about their master key pair, or the first key pair they created their NEAR account with. Maybe we just set an intention to reset these preconceived notions about how Keys are a flexible part of NEAR and how it’s really about your account and your account ID. If you are coming from Ethereum you might be thinking, I just need to deploy a contract and the account from the contract is going to be generated automatically for me from my externally owned accounts, public key, and the nonts that I am on, I will get the contract account generated automatically and that’s how it works. But on NEAR we are talking about having ENS baked into the protocol, so we have account names like matt.testnet or Sharif.testnet. And then you would choose whether or not you would want to deploy a contract to that account. Account names are not generated automatically for you. That is an important distinction to emphasize. In this sense you get a lot more control, and you have a lot more ability to reason about contract versioning over time, you basically just continue to version your contracts, by redeploying as long as you have permission to do that. So with full access permission keys. The biggest shift for anyone coming from Ethereum is going to be - how to reason about that, and we hope it will be easier for you to think through this and to use accounts on NEAR. Essentially there are accounts and subaccounts: you can create sub accounts, and have another account be the master account. So you would have already experienced this if you created an account on our testnet. Context: If you went to Wallet.testnet.near.org you would have created a subaccount of this .testnet top level account. That means that you after creating that name, can create accounts where the master account is porton2 (Example). So if you had created porton2 you could create a subaccount. The question is about deploying a contract using the subaccount of Porton2. Let’s say his app is called NEAR peers - subaccount for NEAR peers is nearpeers.proton2.testnet now. So basically, if you are to control this Sharif, and deploy a contract for the app NEAR peers to the subaccount and to long in and to control this contract using the CLI or using some JavaScript and talking to it through the NEAR API JS you would want to log into NEARpeers.proton2.testnet. Or is it sufficient to just log into Proton2.testnet? Sharif: What I am picking up from this question is that he made his master account Proton2.testnet - I can see this account exists and that it has got 6 full access keys which probably means he has logged in several times from the wallet authorizing applications. So he has got several of these full access keys there. The key question is, is the full contract name nearpeers.protoon2.testnet? The short answer is yes it could be. The account name can be any valid account on the network that you create. You can create it first, and then deploy a contract towards it, or you can create an account as part of a transaction - create an account and then deploy the contract. So it is possible that you deleted the private keys for some of these accounts. The fastest way to check is to go to wallet.testnet.near.org and open up your developer console and look at local storage. Maybe you have the keys in there. If you have the keys in there then you can copy them to your local file system and maybe start working that way. You can also log in with NEAR shell and authorize use of the account from NEAR CLM. High Level Introduction: To Accounts, Keys, and Naming A few differences to recognize with NEAR and Ethereum immediately. Ethereum you typically talk about two different types of accounts: A function call access key lets you call specific methods on a contract, If one is deployed on the account. That is the high level there. What is in an Account? There is this metadata about the account: How many tokens you got, measured in yoctoNEAR. How much of that is locked - the code hash is a fingerprint of a contract, and then a few other details. Then you have data related to the account which is the key value pair - that is the data under the account. This is the account - and then there may be a contract deployed to the account. We can see that it is a non-default value. If you type NEAR state, you will see that the code hash is all 1s. This means that there is no contract deployed to this account. As opposed to the first one, you will see that there is a contract deployed to it. Differences Between Data Captured Between NEAR Accounts and Ethereum Accounts: The ethereum account has a balance - nonce - storageroot, codeHash. NEAR also has a balance locked. It also has action receipts and storage receipts. Transactions that are still to do and transactions that are done are also stored on the account as well. One key difference here is that the Nonce - Because an Ethereum account is a key pair - you have the Nonce that is attached to the key pair and is the thing doing the signing. Basically on Ethereum the keys and the accounts are kind of the same thing. The Nonce on Ethereum is basically per key pair. On NEAR however, it is interesting because each key is going to maintain its own Nonce. Different Keys are doing different things. It is kind of cool that way. Little side note. Based on one account that contains many keys you can be calling different functions at the same time. The other one is Code hash: On NEAR it is similar to Ethereum - One account, one code hash. So you do not have to have a contract deployed as Sharif pointed out but it is 1 to 1. So you cannot have multiple contracts deployed to a single NEAR account. You can redeploy code - if you have full access keys this is the bit that is important: If you have full access keys - you can delete keys off of the account, then anybody. If there is a full access key on an account it basically means you can do anything with it. If there is no full access key - that doesn't necessarily mean that, that account is operating trustlessly. You can still have the code and the contract that does something a little bit sneaky. Unless you are reading the contract code - and unless there are no keys on that account - you are not being able to operate in a trustless environment. If there are no full access keys on a contract - then no other account will be able to deploy to that - even itself? What you would do is create an account, and people would create a multisig contract. What the multisig contract lets you do is what Sharif was saying : A contract with redeploy contract bites, add a full access key, etc. What you can do is burn away all of these full access keys and leave only the keys that are allowed to call the methods on the multisig. So when you remove your full access keys, you just need to make sure that you have at least two keys - you can have three keys to the account, but at least 2 keys to satisfy the two confirmations. You can make a multisig request - and you can add a request to the contract - that says, I messed up and I want a full access key now. So you can create a multisig request for that, so that will get stored in the contract, you can confirm with the same key that added the request - so that’s one out of two confirmations. And then you can use the other key pair, to confirm - to sign a transaction - that would confirm that same request. Once you have done that, the request is actually going to execute and the contract itself will churn away, and it will use the NEAR contract run time to add a key to your account, exactly the same way you would add a key using NEAR CLI if you were logged in with a full access key to that account. You can create those truly trustless contracts, and distribute a bunch of function call keys (limited access keys) to a bunch of participants out there on the inter web or crypto twitter, and you can give away all of this sort of granular control, and you can only call functions on the contract. But if enough people get together, they can kind of join up, and they can vote and confirm some sort of function on that contract, and they can sort of level up various peoples key pairs: you can delete and re-add the same key pair as a full access key. Lots of clever key tricks you can do. So if you guys think of a smart contract wallet on Ethereum that has many different keys, this is all possible on NEAR based on this primitive of keys. If You Are New: T he fastest way for you to get started building on NEAR is an MPM package called Create NEAR App. (29 min) As long as that data structure remains consistent, you can swap in and out the byte code or the generated binary of WASM on your account and then you can operate on that differently. You can upgrade contracts and redeploy. Upgrading is relatively easy in that sense, however you need to be conscious of what these prior data structures were. Mike Pervis - a team member - worked on an upgrade pattern where you are migrating values from an old data structure to a new data structure, saying perhaps you wanted to move all of this data from this data structure to the next data structure. You just need to have some kind of glue bridging code. Specifically around this idea of thinking of the contract code as an API of your account. And what you account is, is the domain and the data behind it. And what the contract is, is something that you can deploy to your account that enforces some kind of conversational messaging protocol with your data score. As soon as you are done having that conversation you can take it off. It is basically this outfit you put on for the purpose of engaging with some system. Can Account A Interrogate its Provisions on Account B? Its all public information. Is there a way for an account to get a list of keys on another account from inside of a contract? You can add keys or delete keys from inside of a contract - when you say can an account do something - the next question is - do we support the ability to ask another account for keys that it has? I don’t think we have a list keys action. You can add a key, delete a key, call a contract, list function, add account, create account, send tokens, transfer or stake, those are the eight primitive actions that we have got. So there is no primitive action from within a contract to ask for account information on a contract. You could go out to an Oracle, because accounts are public information, and have the Oracle tell you what the keys are on account keys. So account A could have some method that allows you to receive news from Account B on some external Oracle. That would be one way to get that done. Use Cases: Could you call a method on my contract from another contract? Do you have a key on the account B - that satisfies some condition on the contract code deployed on account A. What you can do - is outside of the Chain from NEAR CLI or NEAR API JS you can go ahead and try that with the RPC. If the key is not valid - and does not have the permissions to call any contract functions on account A, then account B would not have a key that satisfies that condition. Function Limited Keys: Let say we have two accounts, Alice and Bob (.near each). It is true that Bob can all a function call key that has a receiver of Alice and is only scoped to call methods on Alice. So through some sort of construction, whether it is in the CLI or whether it is in a contract or using NEAR API JS and the user approves that transaction - Bob can add a key to that account. So Bob would have this function call Key with the receiver of Alice - and it is scoped to a particular method - and Bob would have approved some sort of allowance. So lets say you can use, up to 0.1 NEAR for gas, so the allowance is always for something like Gas. This is where it gets interesting, the question is, who maintains the private key? If Bob is a human user, and he approves that key to call Alice's function and with some allowance - does the app have the private key in which case the app can sign transactions on bobs’ behalf that call methods on Alice's contract? So you are saying that I can set a key on my account, to give anybody holding the private key for that key the right to spend my tokens for calling your contract? Well because anyone with a private key can actually create the key pair, and start firing away. So the app could be a node JS service with like a con job that says, hey go poke Alice’s contract, and it can just poke Alice’s contract until the allowance runs out. Because what do we know about ‘gas burn’ from the Ethereum world is that, that’s what keeps the Turing Machine from going into an infinite loop or spending all of the gas in a block. So we had this allowance per key pair that you can enforce which makes it so that if you grant an app access, to even a function call key, you can set the upper bar of how much you are willing to allow that key to spend. And so it will spend down as if you are a car just running down the road and every time you pass a kilometer or a mile, you would run down the gas. Followup question: So you need the equivalent key on Alice's account as well? This is down to the functionality of your app. Bob can add a key to his account, or he can approve the adding of a key - now the real question is who can sign those transactions? It is whoever has visibility or private access to that private key. Bob can add a key to his account that has a receiver of Alice’s account and a list of specific functions that Bob is willing to call. In this instance, if it is just Bob calling Alice, then Alice doesn’t need a special key added to her account. But going the other way, if Alice wanted to call special functions on Bobs account or Alice wanted to call special functions on herself, let’s say Alice has a contract deployed to some account an the App wants to add an access key and says hey we have deployed an app to your account to call functions on your account autonomously. Then Alice would have to self-add a key. Alice could add a key to her account where the receiver ID is Alice herself. Are you saying that if there is a function call access key on account A with a receiver on account B, then whoever has the private keys to that can spend money through A to call B without any keys on B? That’s possible? That seems surprising. Whether or not the method is successful or not - that is up to the contract itself - the contract could deny the call from Bobs account. In a lot of smart contracts, there is going to be this check making sure that the calling account is in fact the current account - matching the predecessor account. The signing account ID matches the predecessor account ID. That is the self- check that protects against Bob calling random arbitrary methods of Bob's account. But it's possible. The Analogy from the Ethereum World: Somebody deploys a smart contract. It has a bunch of functions, some of those functions are public. And anyone with an external account can call those methods, whether the methods succeed or not, depends on the contracts own internal logic, i.e. do you have enough tokens, have you bought these tokens before, and also are you whitelisted? Ultimately, a contract could be deployed on Ethereum like it is on NEAR that enforces the self calling philosophy, in which you have to be the owner. In Ethereum you use these function modifiers to protect functions with the ‘Owner’ attribute. You can add a key to your account that can call functions on another account, whether you are successful or not is kind of up to the account that you are calling. But it is cool. Alice has a multisignature contract. Bob should not be allowed to have a key that creates arbitrary requests, inside Alice’s multisig contract that would be really not cool or not secure cause then Alice's contract will be junked up with a bunch of requests to transfer NEAR and do a bunch of stuff and Alice might confirm. Back to the Original Question: In a system where you have a contract that runs that can call multiple contracts, the predecessor for any particular call is just the account that called you. The signer must be from that account id - this harkens back to the question from before: Do you have a way inside of the contract run time to check to see if a key is part of an account? Well the contract run time is already doing this when you submit a signed transaction. It is basically surfacing this caller variable. Predecessor is not an insanely conceptual term right off the hop. The current account ID and the execution must match the execution. This comes into play, because the brilliant minds of NEAR are already forward thinking into the future, about Cross contract calls and this short of cross-shard calls, but they don’t want us developers to have to bear the burden of understanding which shard or contract it came from - all of that is completely transparent. Basically what you are allowed to do is refer to one call backwards and figure out who that was. So you could have 3 contracts - A,B,C - Account A could require that all of its calls originate from account B and B for C. So this case, if someone makes a call to contract C, the predecessor is going to be matt.near, the current account id is going to be contract C, and then contract C is going to call contract B, the predecessors contract C and then the current account and then it is going to call contract B and then contract A. So this is where it gets really powerful. In the contract run time we are going to derive that for you inside the contract run time and spit that out as the environment variable. This Rust SDK variable that you can just read. The run time enforces which method it is allowed to call, and on which receiver - which contract. And then once you are in there you can see who that is: Which account ID is this call originating from? It is important that we understand the two main concepts: Accounts and then the key pairs are added to the accounts under various permissions, but there is almost like a pseudo concept with these automatic function calls, and that is who controls the private key once you've added a key pair with some allowance to call some functions? T hat opens up this whole other world of possibilities: For example, I could create an API and people could deposit funds to my contract, to get a key that allows them to add a key to my account, so you could add a key to my API contract, that basically gives you an allowance to call a certain number of functions. So this becomes really interesting because who has the private key is the one who can call that, on the accounts behalf. Information About Top Level Account Registration Processes: As far as I know we haven't made any hard and fast decisions about what is going on with TLA’s - Top Level Account Names - so as of now everyone has to create a something.near account. In the future it will be an auction. NEAR will host a very fair and open auction for TLA’s on NEAR - Top Level Accounts - and then you can deploy a contract on the Account that can govern how you will sell sub accounts. How will users create matt.theoforec. Top level accounts will be auctioned off at some point in the future. Final Comment - Question: How to do randomness on NEAR and how to create a fair environment where two people can enter into a contractual agreement. A popular way to do this is to do a commit reveal where Sharif submits some hash of something - it is essentially secret - some junk plus some random number that Sharif chose. In Ethereum or any blockchain, each user would need to commit commit and then call reveal reveal after a certain amount of time so there can be no block manipulation. What would be interesting is that when Sharif calls a method to commit his hash and I call a method to commit mine what would be interesting is if a key is created, that adds another function on that account with a very small allowance of gas - Do a commit reveal scheme with one transaction from the user, then have the app hold the private key to call the reveal.
Enter the password to open this PDF file:
-
-
-
-
-
-
-
-
-
-
-
-