Page 58 - MSDN Magazine, November 2019
P. 58
A verification trigger is used to invoke the contract as a verifica- tion function, accepting multiple parameters and returning a valid Boolean value, indicating the validity of the transaction or block. The contract code is executed to verify whether a transaction involving assets owned by the contract address should be allowed to succeed.
When you transfer assets from account A to account B, verifica- tion is triggered. All the nodes in the blockchain that received the transaction verify account A’s contract. If the return value is true, the transfer completes successfully. If the return value is false, the trans- fer will fail and the transaction won’t be recorded in the blockchain:
public static bool Main(byte[] signature) {
if (Runtime.Trigger == TriggerType.Verification) {
if (/*condition A*/) return true;
else
return false;
}
An application trigger is used to invoke the contract and you can expect the input arguments with the types you specified to be present. You’ll utilize these input values to determine the resulting state of the contract, and its output.
Unlike the verification trigger, which is activated by a transfer, an application trigger (shown in Figure 3) is activated by a special trans- action, InvocationTransaction. Because the contract is executed after
Figure 2 DNS Smart Contract
InvocationTransaction is confirmed, the transaction is recorded in the blockchain irrespective of whether the smart contract execution succeeds or fails.
In this example, because it’s a smart contract without asset trans- fers involved, the only trigger that needs to be considered is the application trigger.
CheckWitness In many, if not all, cases, you’ll want to validate whether the address invoking your contract code is really who it says it is. The Runtime.CheckWitness method accepts a single parameter that represents the address you’d like to validate against the address used to invoke the contract code. More specifically, it verifies that the transactions or block of the calling contract has validated the required script hashes.
Programming Your First C# Smart Contract
We’ll use the preview release of the NEO Blockchain Toolkit for .NET on Visual Studio Code Marketplace to develop, debug and deploy our first smart contract using C#. For brevity, rather than using the Visual Studio Code extensions, we’ll use command-line tools to illustrate the steps. We’ll use the Hello World contract as our example.
In your terminal window, create an empty directory called HelloWorld. Change to that directory and invoke the dotnet new new-contract command. This will create a NEO smart contract that writes Hello World to blockchain storage. If you wish, you can create a Visual Basic smart contract by adding -lang VB to the command prior to execution.
You can immediately build the smart contract via the dotnet build command. The result should look something like Figure 4. From the terminal window in your HelloWorld project directory,
you can launch Visual Studio Code by executing code.
Before you can run the contract in the debugger, you need to create a launch configuration. The NEO smart contract debugger makes this very easy. From the top-level Debug menu select Add Configuration, and then from the Select Environment input box select NEO Contract. When you hit F5 or select Debug | Start Debugging from the menu, the HelloWorld contract launches for debugging. At this
point, you can do any of the following:
• Continue, Step Into, Step Over and Step In • Set Breakpoints
Figure 3 Application Trigger
}
using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Services.Neo; namespace Neo.SmartContract
{
public class Domain : SmartContract {
public static object Main(string operation, params object[] args) {
if (Runtime.Trigger == TriggerType.Application){ switch (operation){
case "query":
return Query((string)args[0]);
case "register":
return Register((string)args[0], (byte[])args[1]);
case "delete":
return Delete((string)args[0]);
default: return false;
} }
}
private static byte[] Query(string domain) {
return Storage.Get(Storage.CurrentContext, domain); }
private static bool Register(string domain, byte[] owner) {
// Check if the owner is the same as the one who invoke the contract if (!Runtime.CheckWitness(owner)) return false;
byte[] value = Storage.Get(Storage.CurrentContext, domain);
if (value != null) return false; Storage.Put(Storage.CurrentContext, domain, owner);
return true; }
private static bool Delete(string domain) {
// To do }
} }
public static Object Main(string operation, params object[] args) {
if (Runtime.Trigger == TriggerType.Verification) {
if (/*Condition A*/) return true;
else
return false;
}
if (Runtime.Trigger == TriggerType.Application) {
if (operation == "FunctionA") return FunctionA(args); }
}
// There is a smart contract entry point and redirected from main method public static bool FunctionA(params object[] args)
{
// Some code }
46 msdn magazine
Blockchain