// sample Abra type definitions
// define some standard trit lengths we will use in our examples
// note that you can define the optimal size for any type's range
// to reduce energy requirements accordingly
Trit [1]; // -1 to +1
Tryte [3]; // -13 to +13
Short [9]; // -9,841 to +9,841
Int [27]; // -3,812,798,742,493 to +3,812,798,742,493
Long [81]; // -2.217...e+38 to +2.217...e+38
Hash [243];
State [729];
// convenience type to make code more clear
// supposed to always contain a binary boolean value 0 (false) or 1 (true)
// should never be null or have the value - (convention not enforced by Abra)
Bool [Trit];
// here's how to define a named structured trit vector
// it consists of the concatenation of all sub-vectors
// its size is the sum of all sub-vector sizes
// IOTA transaction layout
Transaction {
signature [27 * Hash]
, extradatadigest [Hash]
, address [Hash]
, value [Long]
, issuancetimestamp [Int]
, timelocklowerbound [Int]
, timelockupperbound [Int]
, bundle [Long]
, trunk [Hash]
, branch [Hash]
, tag [Long]
, attachmenttimestamp [Int]
, attachmenttimestamplowerbound [Int]
, attachmenttimestampupperbound [Int]
, nonce [Long]
};
// sample Abra look-up tables
// these are a look-up tables, or LUTs
// a LUT describes for each combination of input trits what the resulting output trits will be
// any missing explicitly defined combinations will cause the resulting output to be null
// if any input to a LUT is null, the result will be null as well,
// so we only need to specify combinations of non-null input values
// ************* BINARY OPERATORS *************
// LUT logic: binary NOT
// return !trit1;
not [
0 = 1;
1 = 0;
];
// LUT logic: binary AND
// return (trit1 & trit2);
and [
0,0 = 0;
0,1 = 0;
1,0 = 0;
1,1 = 1;
];
// LUT logic: binary OR
// return (trit1 | trit2);
or [
0,0 = 0;
0,1 = 1;
1,0 = 1;
1,1 = 1;
];
// LUT logic: binary XOR
// return (trit1 ^ trit2);
xor [
0,0 = 0;
0,1 = 1;
1,0 = 1;
1,1 = 0;
];
// LUT logic: binary NAND
// return !(trit1 & trit2);
nand [
0,0 = 1;
0,1 = 1;
1,0 = 1;
1,1 = 0;
];
// LUT logic: binary NOR
// return !(trit1 | trit2);
nor [
0,0 = 1;
0,1 = 0;
1,0 = 0;
1,1 = 0;
];
// LUT logic: binary XNOR
// return !(trit1 ^ trit2);
xnor [
0,0 = 1;
0,1 = 0;
1,0 = 0;
1,1 = 1;
];
// ************* TERNARY OPERATORS *************
// LUT logic: return the negative value of the input trit
// return -trit1;
/ note that making an entire trit-vector value negative
// can be done by simply negating every trit in the vector
neg [
- = 1;
0 = 0;
1 = -;
];
// LUT logic: return a boolean indicating whether the two input trits are equal
// return (trit1 == trit2);
equal [
-,- = 1;
-,0 = 0;
-,1 = 0;
0,- = 0;
0,0 = 1;
0,1 = 0;
1,- = 0;
1,0 = 0;
1,1 = 1;
];
// LUT logic: return a boolean indicating whether the two input trits are unequal
// return (trit1 != trit2);
unequal [
-,- = 0;
-,0 = 1;
-,1 = 1;
0,- = 1;
0,0 = 0;
0,1 = 1;
1,- = 1;
1,0 = 1;
1,1 = 0;
];
// LUT logic: when (boolean) trit1 equals 1 return trit2 else return trit3
// return trit1 ? trit2 : trit3;
unequal [
0,-,- = -;
0,-,0 = 0;
0,-,1 = 1;
0,0,- = -;
0,0,0 = 0;
0,0,1 = 1;
0,1,- = -;
0,1,0 = 0;
0,1,1 = 1;
1,-,- = -;
1,-,0 = -;
1,-,1 = -;
1,0,- = 0;
1,0,0 = 0;
1,0,1 = 0;
1,1,- = 1;
1,1,0 = 1;
1,1,1 = 1;
];
// LUT logic: return the 2rd input trit only when 1st input trit equals 1 (true)
// return (trit1 == 1) ? trit1 : null;
nullOrTrit [
1,0 = 0;
1,1 = 1;
1,- = -;
];
// sample Abra functions
// this is a function that takes a trit vector of State [729],
// but we don't need to constantly repeat that size since we
// already established the size at the top of the file
digest(state [State]) =
// a function returns the value of its last statement,
// which in this case is a concatenation (comma operator)
// of the input state and the result of the transform() function
state, transform(state, 81);
// note that this function does not need curly braces around its single statement
// curly braces are only necessary when grouping multiple statements
// construct functions for all predefined types that perform
// a similar task to the nullOrTrit LUT for those larger types
// note that we have defined each successive type a factor 3 times bigger
// which means we can easily define each successive type in terms of the previous one
// every nullOrXxx function returns
when
equals 1 (true), and null otherwise
// note that it may seem wasteful to define it this way, but when mapped to FPGA
// these can be translated into parallel circuitry that executes them simultaneously.
// for other architectures, Abra will allow the Abra functions to be replaced with
// a dll function that uses optimal architecture-specific instructions.
// we expect a library of common functions to be developed over time
nullOrTryte(t [Bool], val [Tryte]) = {
// concatenate the 3 separate trits via the LUT
nullOrTrit[t, val[0]],
nullOrTrit[t, val[1]],
nullOrTrit[t, val[2]];
};
nullOrShort(t [Bool], val [Short]) = {
// concatenate the 3 separate trytes via the previous function