Automated Transactions API Specification
----------------------------------------

This specification details the AT API which is what allows an AT to communicate with its host's blockchain to
find out details about blocks and transactions relevant to the AT and to issue its own transactions. In order
to write "portable" ATs (i.e. those that can run analtered across different kinds of blockchain platforms) it
is required that only the functions in the range 0x0100 to 0x04ff be used. Experimental functions can be used
when prototyping (and have no formal definition here) and platform specific functions can be defined in order
for ATs to be able to work more efficiently on a specific platform (and also have no formal definition here).

As the AT machine uses a 64 bit design some very useful API commands such as cryptographic hash functions are
not able to be perfomed directly with machine addresses. To work around this problem without resorting to the
API having to perform memory range testing to use the AT's data, a set of "pseudo registers" must be provided
by the AT API (every AT instance needs its own set) that are initially set to zero.

There are four 64 bit registers called A1..4 and another four called B1..4 for this purpose (also referred to
as two 256 bit registers called A and B). It is important to note that the A and B pseudo registers will need
to be stored along with the other "state" variables such as the program counter and stack counters.

Note that "timestamp" does not mean a real timestamp but instead is an artificial timestamp that includes two
parts. The first part is a block height (32 bits) with the second part being the number of the transaction if
applicable (also 32 bits and zero if not applicable).

Note also that functions can be identified as being "blocking" functions. They will cause the AT to sleep for
X blocks when it is known that the function will then be ready to return (with the function being executed by
the AT twice with the first call needing to rewind the AT's program counter before putting it to sleep).

In order to keep the functions organised in groups function number ranges are as follows:

Number Range      Range Usage
--------------    ----------------------------------------------
0x0000..0x000f    Reserved for internal AT testing purposes
0x0010..0x00ff    Experimental API function calls (for prototyping)
0x0100..0x01ff    Get/Set functions for "pseudo registers"
0x0200..0x02ff    Functions that perform hash operations
0x0300..0x03ff    Generic functions that get block and tx info
0x0400..0x04ff    Generic functions that check balances and perform ops
0x0500..0x05ff    Platform specific functions that get block and tx info
0x0600..0x06ff    Platform specific functions that check balances and perform ops

As cryptographic hash operations are *expensive* operations it is suggested that the "fee" for each of those
function calls be higher than that of others (fees themselves are a platform specific implementation issue).

Function Name             Number AT op code        Operation (and comments)
------------------------- ------ ----------------- ----------------------------------------------------------
Get_A1                    0x0100 EXT_FUN_RET       sets @addr to A1
Get_A2                    0x0101 EXT_FUN_RET       sets @addr to A2
Get_A3                    0x0102 EXT_FUN_RET       sets @addr to A3
Get_A4                    0x0103 EXT_FUN_RET       sets @addr to A4
Get_B1                    0x0104 EXT_FUN_RET       sets @addr to B1
Get_B2                    0x0105 EXT_FUN_RET       sets @addr to B2
Get_B3                    0x0106 EXT_FUN_RET       sets @addr to B3
Get_B4                    0x0107 EXT_FUN_RET       sets @addr to B4

Set_A1                    0x0110 EXT_FUN_DAT       sets A1 from $addr
Set_A2                    0x0111 EXT_FUN_DAT       sets A2 from $addr
Set_A3                    0x0112 EXT_FUN_DAT       sets A3 from $addr
Set_A4                    0x0113 EXT_FUN_DAT       sets A4 from $addr
Set_A1_A2                 0x0114 EXT_FUN_DAT_2     sets A1 from $addr1 and A2 from $addr2
Set_A3_A4                 0x0115 EXT_FUN_DAT_2     sets A3 from $addr1 and A4 from $addr2
Set_B1                    0x0116 EXT_FUN_DAT       sets B1 from $addr
Set_B2                    0x0117 EXT_FUN_DAT       sets B2 from $addr
Set_B3                    0x0118 EXT_FUN_DAT       sets B3 from $addr
Set_B4                    0x0119 EXT_FUN_DAT       sets B4 from $addr
Set_B1_B2                 0x011a EXT_FUN_DAT_2     sets B1 from $addr1 and B2 from $addr2
Set_B3_B4                 0x011b EXT_FUN_DAT_2     sets B3 from $addr1 and B4 from $addr2

Clear_A                   0x0120 EXT_FUN           sets A to zero (A being A1..4)
Clear_B                   0x0121 EXT_FUN           sets B to zero (B being B1..4)
Clear_A_And_B             0x0122 EXT_FUN           sets both A and B to zero
Copy_A_From_B             0x0123 EXT_FUN           copies B into A
Copy_B_From_A             0x0124 EXT_FUN           copies A into B
Check_A_Is_Zero           0x0125 EXT_FUN_RET       @addr to 1 if A is zero or 0 if it is not (i.e. bool)
Check_B_Is_Zero           0x0126 EXT_FUN_RET       @addr to 1 if B is zero of 0 if it is not (i.e. bool)
Check_A_Equals_B          0x0127 EXT_FUN_RET       @addr to bool if A is equal to B
Swap_A_and_B              0x0128 EXT_FUN           swap the values of A and B
OR_A_with_B               0x0129 EXT_FUN           sets A to A | B (bitwise OR)
OR_B_with_A               0x012a EXT_FUN           sets B to B | A (bitwise OR)
AND_A_with_B              0x012b EXT_FUN           sets A to A & B (bitwise AND)
AND_B_with_A              0x012c EXT_FUN           sets B to B & A (bitwise AND)
XOR_A_with_B              0x012d EXT_FUN           sets A to A ^ B (bitwise XOR)
XOR_B_with_A              0x012e EXT_FUN           sets B to B ^ A (bitwise XOR)
--- NOTE: These 8 math ops are intended for a future implementation so no need to support them currently.
Add_A_To_B                0x0140 EXT_FUN           adds A to B (result in B)
Add_B_To_A                0x0141 EXT_FUN           adds B to A (result in A)
Sub_A_From_B              0x0142 EXT_FUN           subs A from B (result in B)
Sub_B_From_A              0x0143 EXT_FUN           subs B from A (result in A)
Mul_A_By_B                0x0144 EXT_FUN           multiplies A by B (result in B)
Mul_B_By_A                0x0145 EXT_FUN           multiplies B by A (result in A)
Div_A_By_B                0x0146 EXT_FUN           divides A by B (result in B)*
Div_B_By_A                0x0147 EXT_FUN           divides B by A (result in A)*

 * note that these functions could cause a divide by zero error which would put the machine in error

MD5_A_To_B                0x0200 EXT_FUN           take an MD5 hash of A1..2 and put this is B1..2
Check_MD5_A_With_B        0x0201 EXT_FUN_RET       @addr to bool if MD5 hash of A1..2 matches B1..2
HASH160_A_To_B            0x0202 EXT_FUN           take a RIPEMD160 hash of A1..3 and put this in B1..3
Check_HASH160_A_With_B    0x0203 EXT_FUN_RET       @addr to bool if RIPEMD160 hash of A1..3 matches B1..3
SHA256_A_To_B             0x0204 EXT_FUN           take a SHA256 hash of A and put this in B
Check_SHA256_A_With_B     0x0205 EXT_FUN_RET       @addr to bool if SHA256 hash of A matches B

Get_Block_Timestamp       0x0300 EXT_FUN_RET       sets @addr to the timestamp of the current block
Get_Creation_Timestamp    0x0301 EXT_FUN_RET       sets @addr to the timestamp of the AT creation block
Get_Last_Block_Timestamp  0x0302 EXT_FUN_RET       sets @addr to the timestamp of the previous block
Put_Last_Block_Hash_In_A  0x0303 EXT_FUN           puts the block hash of the previous block in A
A_To_Tx_After_Timestamp   0x0304 EXT_FUN_DAT       sets A to tx hash of the first tx after $addr timestamp
Get_Type_For_Tx_In_A      0x0305 EXT_FUN_RET       if A is a valid tx then @addr to tx type*
Get_Amount_For_Tx_In_A    0x0306 EXT_FUN_RET       if A is a valid tx then @addr to tx amount**
Get_Timestamp_For_Tx_In_A 0x0307 EXT_FUN_RET       if A is a valid tx then @addr to the tx timestamp
Get_Random_Id_For_Tx_In_A 0x0308 EXT_FUN_RET       if A is a valid tx then @addr to the tx random id***
Message_From_Tx_In_A_To_B 0x0309 EXT_FUN           if A is a valid tx then B to the tx message****
B_To_Address_Of_Tx_In_A   0x030a EXT_FUN           if A is a valid tx then B set to the tx address
B_To_Address_Of_Creator   0x030b EXT_FUN           sets B to the address of the AT's creator

 * tx type is 0 for a normal tx and 1 for a message tx
 ** amount will always have the minimum fee subtracted from it
 *** a random id is a 64 bit signed value (that is always returned positive) and this is a blocking function
 **** if the tx does not include a message tx then this will zero out the B value

 NOTE: For all cases where A is not a valid tx @addr will be set to 0xffffffffffffffff

Get_Current_Balance       0x0400 EXT_FUN_RET       sets @addr to current balance of the AT
Get_Previous_Balance      0x0401 EXT_FUN_RET       sets @addr to the balance it had last had when running*
Send_To_Address_In_B      0x0402 EXT_FUN_DAT       if B is a valid address then send it $addr amount**
Send_All_To_Address_In_B  0x0403 EXT_FUN           if B is a valid address then send it the entire balance
Send_Old_To_Address_In_B  0x0404 EXT_FUN           if B is a valid address then send it the old balance**
Send_A_To_Address_In_B    0x0405 EXT_FUN           if B is a valid address then send it A as a message
Add_Minutes_To_Timestamp  0x0406 EXT_FUN_RET_DAT_2 set @addr1 to timestamp $addr2 plus $addr3 minutes***

 * this amount does not include any additional amounts sent to the AT between "execution events"
 ** if this amount is greater than the AT's balance then it will only send the current balance amount
 *** the API is expected to base this timestamp according to the "average block time" for the blockchain