Quick start

Smacco is a tool designed to easily generate “smart accounts” for holding assets. The specification of a smart account is made on JSON language, and the corresponding C# code is generated for Neo2 blockchain. A visual diagram is also generated, for simplicity.

The tool can be used online, so installing is not required (only for local testing).

First Example

The first Smart Account is a basic public key verification contract, which is the simplest and most widespread mechanism to hold assets on Neo blockchain (and also on Bitcoin).

{
    "standard": "smacco-1.0",
    "input_type" : "single",
    "pubkey_list" : ["036245f426b4522e8a2901be6ccc1f71e37dc376726cc6665d80c5997e240568fb"],
    "rule" : {
        "rule_type": "ALLOW_IF",
        "condition" : {
            "condition_type" : "CHECKSIG"
        }
    }
}

And the corresponding C# smart contract:

using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Services.Neo;
using Neo.SmartContract.Framework.Services.System;
namespace NeoContract1 {
public class Contract1 : SmartContract {
    public static readonly byte[] pubkey_0 = "036245f426b4522e8a2901be6ccc1f71e37dc376726cc6665d80c5997e240568fb".HexToBytes();
    public static bool Main(byte[] signature){
        return (VerifySignature(signature, pubkey_0));
    }
}
}

Hint

The online platform already compiles C# code using NeoCompiler Eco infrastructure. Platform also generates the following diagram: First contract

Definition starts with standard, and smacco-1.0 has two input_type: single or multi. We start with input_type single, which means that a single signature is received as input parameter. The field pubkey_list declares the used keys for public key criptography.

Note

Neo uses NIST P-256 secp256r1 elliptic curve cryptography. See project libcrypton for more information.

The goal of the generated verification contract is to return a boolean (true/false) response, when a matching signature is provided.

We then explore rule section.

Understanding Rules

Every smart account is composed by one or more rules, that govern the behavior of the contract. Smacco provides two fields:

  • rule: when a single rule is used (the simplest form)

  • rules: when multiple rules are used

Each rule is divided in two parts: rule_type and condition.

A rule_type can be:

  • ALLOW_IF: directly accepts operation (returns true) if condition is satisfied

  • DENY_IF: directly rejects operation (returns false) if condition is not satisfied

Every condition has a condition_type in many formats, including:

  • CHECKSIG: checks a single signature parameter against public key

  • CHECKMULTISIG: checks an array of signatures as parameter against an array of public keys

  • and many others… note that details are not given at this point, let’s move on

Default Rule and Inlining

It’s important to highlight that a default_rule governs the corner cases of the contract, and can be:

  • DENY_ALL: standard option, if no rule explicitly accepts, then operation is rejected

  • ACCEPTS_ALL: if no rule explicitly rejects, then operation is accepted

Important

Note that default_rule is only used when "inline_last"="disabled". Since inlining is enabled by default, we typically don’t use a default_rule.

MultiSig Example

Next example validates a subset of public keys against an array of signatures passed as parameter, known as multisig. This account type is generally used to provide extra security, in two common scenarios:

  • requiring multiple entities to attach signatures, e.g., a 3/3 multisig (only valid if three-out-of-three sign together)

  • accepting fallback signatures, if some of them is lost, e.g., a 2/3 multisig (valid if any two-out-of-three sign together)

We provide an example of 2/3 multisig, with default_rule set to DENY_ALL (disabling inlining):

{
    "standard": "smacco-1.0",
    "input_type": "array",
    "pubkey_list": [
        "036245f426b4522e8a2901be6ccc1f71e37dc376726cc6665d80c5997e240568fb",
        "0303897394935bb5418b1c1c4cf35513e276c6bd313ddd1330f113ec3dc34fbd0d",
        "02e2baf21e36df2007189d05b9e682f4192a101dcdf07eed7d6313625a930874b4"
    ],
    "rule": {
        "rule_type": "ALLOW_IF",
        "condition": {
        "condition_type": "CHECKMULTISIG",
        "minimum_required": "2"
        }
    },
    "default_rule" : "DENY_ALL"
}

And the corresponding C# smart contract:

using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Services.Neo;
using Neo.SmartContract.Framework.Services.System;
namespace NeoContract1 {
public class Contract1 : SmartContract {
    public static readonly byte[] pubkey_0 = "036245f426b4522e8a2901be6ccc1f71e37dc376726cc6665d80c5997e240568fb".HexToBytes();
    public static readonly byte[] pubkey_1 = "0303897394935bb5418b1c1c4cf35513e276c6bd313ddd1330f113ec3dc34fbd0d".HexToBytes();
    public static readonly byte[] pubkey_2 = "02e2baf21e36df2007189d05b9e682f4192a101dcdf07eed7d6313625a930874b4".HexToBytes();
    public static bool CheckMultiSig2_3(byte[][] signatures){
        byte[][] vpub = new[] {pubkey_0, pubkey_1, pubkey_2};
        byte[][] vsig = new[] {signatures[0], signatures[1]};
        return VerifySignatures(vsig, vpub);
    }
    public static bool Main(byte[][] signatures) {
        if(CheckMultiSig2_3(signatures))
            return true;
        return false;
    }
}
}

Hint

The online platform already compiles C# code using NeoCompiler Eco infrastructure. Platform also generates the following diagram: Multisig contract

Timelock Contract

One of the most powerful capability of Smacco is to easily generate timelock accounts. Many blockchain projects rely on time locks to enforce token governance, disabling any possible operation before or after a given time.

We provide an example of a timelock until timestamp 1536896190 (09/14/2018 @ 3:36am UTC):

{
    "standard": "smacco-1.0",
    "input_type": "single",
    "pubkey_list": [
        "036245f426b4522e8a2901be6ccc1f71e37dc376726cc6665d80c5997e240568fb"
    ],
    "rules": [
        {
            "rule_type": "DENY_IF",
            "condition": {
                "condition_type": "TIMESTAMP_LESS",
                "timestamp": "1536896190"
            }
        },
        {
            "rule_type": "ALLOW_IF",
            "condition": {
                "condition_type": "CHECKSIG"
            }
        }
    ]
}

And the corresponding C# smart contract:

using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Services.Neo;
using Neo.SmartContract.Framework.Services.System;
namespace NeoContract1 {
public class Contract1 : SmartContract {
    public static readonly byte[] pubkey_0 = "036245f426b4522e8a2901be6ccc1f71e37dc376726cc6665d80c5997e240568fb".HexToBytes();
    public static bool Main(byte[] signature) {
        if(Blockchain.GetHeader(Blockchain.GetHeight()).Timestamp < 1536896190)
            return false;
        return (VerifySignature(signature, pubkey_0));
    }
}
}

Hint

The online platform already compiles C# code using NeoCompiler Eco infrastructure. Platform also generates the following diagram: Timelock contract

Logic Operations

Conditions can also be combined by means of logic AND/OR operations.

For example, by giving two pubkeys as parameter, we can use OR to make a choice between them:

{
    "rule_type": "ALLOW_IF",
    "condition" : {
        "condition_type" : "OR",
        "conditions" : [
            {
                "condition_type" : "CHECKSIG",
                "pubkey" : "0"
            },
            {
                "condition_type" : "CHECKSIG",
                "pubkey" : "1"
            }
        ]
    }
}

Hint

The above example is equivalent to a 1/2 MultiSig. Practice a little bit and try that!

Available Conditions

We present a short list of available conditions.

Warning

This list is very likely to be incomplete! If more information is needed, open an Issue for a discussion on GitHub, or inspect the source code smacco.js to find out more details.

Conditions and subfields:

  • AND: performs logic AND
    • conditions: json list of conditions to perform AND

  • OR: performs logic OR
    • conditions: json list of conditions to perform OR

  • CHECKSIG: performs CHECKSIG to validate default or explicit pubkey
    • pubkey: explicit pubkey index (defaults to 0)

  • CHECKMULTISIG: performs CHECKMULTISIG X/Y
    • pubkeys: list of public keys to check (value Y). Defaults to global pubkey_list.

    • minimum_required: value X of X/Y multisig

    • signatures: explicit index of signatures passed as array to contract. Length of list replaces minimum_required.

    • condition_name: name of condition (affects C# function name)

  • TIMESTAMP_LESS: check if timestamp is less than a given value
    • timestamp: explicit time value in timestamp format

    • utc: explicit time value in utc format

  • TIMESTAMP_GREATER: check if timestamp is greater than a given value
    • timestamp: explicit time value in timestamp format

    • utc: explicit time value in utc format

  • SELF_TRANSFER: check if transaction is a self-transfer (destination is same as source)

  • ONLY_NEO: check if only NEO asset is being transferred

  • ONLY_GAS: check if only GAS asset is being transferred

Interesting examples of each of these options are presented on file smacco.test.js.