3. INTRODUCING THE BIG BLOCK BITCOIN MINIMALIST
Mark Smalley - CEO ( Neuroware.io )
Living in Malaysia for the past 20 Years
Building FinTech Applications for 15 Years
Spent 10 Years Helping Tech Communities
Building Blockchain Apps for 5 Years
4. INTRODUCING R1 DOT MY SDN BHD
GLOBAL
FUNDING
Only Malaysian company to graduate
from 500 Startups Accelerator in Silicon
Valley, with funding from Coinsilium too
FINTECH
FOCUS
With DBS, Maybank and Securities
Commission of Malaysia as clients, we
have a broad understanding of fintech
FULL-STACK
SERVICES
We provide corporate blockchain
training and workshops along with
consulting on solutions utilizing Cortex
NEUROWARE
enterprise infrastructure
BCE.ASIA
consortium
BLOCKSTRAP
framework
12. ETHEREUM’S BIGGEST SURPRISES
● An object oriented language without objects
● A static typing language with only one type
● Indexes via mapped hash tables cannot be removed
● Indexes cannot be natively counted
● Moving beyond 32 byte dynamic chunks is complicated
● Output functionality is even more restrictive than inputs
13. ONE TYPE TO RULE THEM ALL
Inline data types available within contracts includes:
● Booleans
● Integers
● Addresses
● Strings
● Bytes
Data types stored on the blockchain:
● Byte arrays
14. DEFINING VARIABLE TYPES AND THEIR VISIBILITY
contract CRM
{
bool internal deactivated = 0;
uint public contact_count = 0;
address private contract_owner;
string external owner_name = “Mark”;
function CRM(string name)
{
contract_owner = msg.sender;
owner_name = name;
}
}
Global variables automatically available
anywhere within the contract include:
● block (current height, gas, difficulty, etc)
● msg (data, gas, sender, value, etc)
● now (alias for block.timestamp)
● tx (gas price & origin)
function is auto initiated if its
the same as contract name
15. ONE DIMENSIONAL ARRAYS
● All four data types (other than strings) can be set as arrays
● Arrays can only contain the same data type
● Constructing arrays within functions requires length definitions
● Don’t forget that strings are also arrays (chunks are relative)
● Arrays used for input & output parameters cannot be strings
17. BUILDING NEW ARRAYS
uint[] private owner_ip4_address;
address[] public owners;
uint[] public owner_switch_blocks;
function SwitchOwner(string ip_address, address new_owner)
returns(uint[] previous_owner)
{
uint[] memory previous = new uint[](6);
if(msg.sender == contract_owner)
{
contract_owner = new_owner;
owners.push(contract_owner);
owner_switch_blocks.push(block.number);
owner_ip_address = string_to_array (ip_address, “.”);
previous[0 to 3] = owner_ip_address[0 to 3];
previous[4] = owner_switch_blocks[owner_switch_blocks.length - 1];
previous[5] = owner_switch_blocks.length;
}
return previous; // Everything but the name :-(
}
18. STRUCTS TO THE RESCUE !!! ???
contract CRM
{
struct owner
{
address id;
string name;
uint[] ip;
}
owner[] public owners; // manual auto inc id ???
function CRM(string owner_name, uint[] ip_address)
{
owner new_owner;
new_owners.id = msg.sender;
new_owners.name = owner_name;
new_owners.ip = ip_address;
owners.push(new_owner);
}
}
19. INDEXING VIA HASH TABLES - ALREADY REMOVES 4 LINES
contract CRM
{
struct owner
{
string name;
uint[] ip;
}
mapping(address => owner) owners;
function CRM(string owner_name, uint[] ip_address)
{
// can then create, read & update with key ...
owners[msg.sender].name = owner_name;
owners[msg.sender].ip = ip_address;
}
}
20. HOWEVER
● Structs cannot be returned
● Struct parameters cannot be counted natively
● Mappings cannot be counted
-- which requires index counts to be managed separately
● Mappings cannot be removed
● Mappings cannot be collectively returned
-- returned results must also be singular types of arrays
21. IN ALL HONESTY - IT’S BYTES THAT SAVE THE DAY !!!
struct owner
{
string name;
uint[] ip;
}
mapping(address => owner) owners;
uint owner_count = 0;
function CRM(string owner_name, uint[] ip_address)
returns(bytes32[] owner)
{
bytes32[] memory new_owner = new bytes32[](2);
new_owner[0] = string_to_bytes (owner_name);
new_owner[1] = combine(ip_address[0 to 4])
owners[msg.sender].name = owner_name;
owners[msg.sender].ip = ip_address;
owner_count++; // manual owner count management
return new_owner
}
22. THE ONLY WAY TO DELETE - STEP 1 - BE PREPARED ???
struct owner
{
bool is_active;
string name;
uint[] ip;
}
mapping(address => owner) owners;
uint owner_count = 0;
function CRM(string owner_name, uint[] ip_address)
{
bytes32[] memory new_owner = new bytes32[](2);
owners[msg.sender].is_active = 1; // activate
owners[msg.sender].name = owner_name;
owners[msg.sender].ip = ip_address;
owner_count++; // manual owner count management
}
23. THE ONLY WAY TO DELETE - STEP 2 - COST EFFECTIVE UPDATING
struct owner
{
bool is_active;
string name;
uint[] ip;
}
mapping(address => owner) owners;
uint owner_count = 0;
function destroy(address owner_id)
{
owners[owner_id].is_active = 0; // this costs ether
owner_count--; // manual owner count management
}
29. CRUDy RECAP - DESTROY RECORDS
contract CRM
{
struct user
{
string name;
string email;
bool is_active;
}
mapping(address => user) users;
function destroy(address user_address) onlyOwner public
{
require(users[user_address].is_active == 1);
users[user_address].is_active = 0;
}
}
30. CRUDy RECAP - COMPLICATED BY COUNTS
contract CRM
{
struct user
{
string name;
string email;
bool is_active;
}
mapping(address => user) users;
uint public user_count;
function destroy(address user_address) onlyOwner public
{
require(users[user_address].is_active == 1);
users[user_address].is_active = 0;
user_count--;
}
}
31. CRUDy RECAP - EVEN MORE SO WITH JOINS
struct user
{
string name;
string email;
bool is_active;
uint index_key;
}
mapping(address => user) users;
address[] public user_indexes;
function destroy(address user_address) onlyOwner public
{
require(users[user_address].is_active == 1);
users[user_address].is_active = 0;
users[user_indexes[user_indexes.length - 1]].index_key =
users[user_address].index_key
user_indexes[users[user_address].index_key] =
user_indexes[user_indexes.length - 1];
user_indexes.length = user_index.length - 1;
}
32. CAVEATS - WORKING WITH STRINGS
● Since strings cannot be returned from external contracts every
contract dealing with strings needs it own conversion functions
● Converting strings to 32 byte arrays allow anything to be
returned - so long as each value is within 32 bytes, which
also requires the decoding to be done by the client
● Which brings us to what I thought we would cover today ...
33. WHAT ABOUT CRUD BEYOND PREDEFINED STRUCTURE ???
CREATE READ UPDATE DESTROY
34. TO BE CONTINUED IN PART 2
CREATING A DATABASE WITHIN A CONTRACT