Automated Transactions Specification

In brief an Automated Transaction is a "Turing complete" set of byte code instructions which will be executed
by a byte code interpreter built into its host. An AT supporting host platform automatically supports various
applications ranging from games of chance to automated crowdfunding and ensuring that "long term savings" are
not lost forever.

User Requirements

The host will require changes to support the execution of Automated Transactions. These changes required need
to include a way for a user to publish an AT as well as a way of being able to execute up to a max. number of
steps for a given AT. After step execution is complete all relevant state for the AT is required to be stored
in a newly created block (a *hash* of the state could be used provided that AT execution is mandatory).

An AT needs to have an "account" (perhaps determined via a hash of its code) so that normal host users have a
simple way to "send it funds". It also needs to be able to send funds to others (where the transactions could
need to be recorded explictly for nodes that do not support running AT to be permitted).

An AT engine needs to be built into the host that supports basic validation of AT the instructions and allows
the execution of the AT to be controlled one step at a time.

Use Case #1: Lottery

Create a "lottery" program which will pay out its balance to a "winner" automatically once per week.

To purchase a "ticket" a host user would send X to the "lottery AT account" (where some of this amount may be
needed to pay for running the AT). The "ticket" itself would be need to be determinstic yet "random" (such as
a future block hash) and may have to be determined "well after the block that its purchase occurs in".

Use Case #2: Dormant Funds Transfer

Create a program that if not notified before a certain period of time will transfer its funds to one specific
account. The notification mechanism will be via an AM transaction and the content of the AM (if not empty) is
a new address to payout to (note that AMs may not be supported in all hosts).

Use Case #3: Project Crowdfunding Agent

Create a program that will at a certain time check if it has a balance greater than or equal to a target that
was hard-coded into it. If the required balance level has been reached then all funds will be then sent to an
account hard-coded into it. If the required balance has not been met then each tx sender will be refunded the
amount they sent (tx fees may also need to be considered).

Functional Requirements

Code in an AT will be run by an AT byte code interpreter which will use a fixed amount of memory per program.
ATs that require more than a "minimal" amount of memory will have a value deduced from their balance *before*
they are executed (if the balance is too small to result in any execution then execution would not occur with
no memory allocation actually being performed). It needs to be clearly understood that an AT can be halted at
any step so there can be no "working memory" or the like in the AT interpreter itself.

Both AT code and data need to be persistent (although data doesn't need to be stored until the AT has had one
or more steps executed). Blockchain pruning could not include ATs that have a non-zero account balance. There
should probably also be the ability to set a block number for execution so any unnecessary code execution can
be avoided (perhaps this could be stored as part of the account information for the AT). It should also be an
option to include initial values for (a portion of) the data area after the code.

An AT will need to be created via its own special type of transaction which will need to include a fee amount
large enough to cover the "costs" that the size of its code and data will dictate. Execution of AT code would
be expected to be dependent upon the account balance of the AT and this balance would be reduced by each step
executed (with some or all function call steps perhaps incurring more costs than non-function call steps).

It can be expected that over time an increasing number of ATs will be created so the cost for running AT code
must be kept to an absolute minimum. This will require AT code to be deterministic, and that its instructions
must not be able to take arbitrary amounts of time. This will limit the set of API functions accessible to an
AT to only those that do not require arbitrary scans over the blockchain (i.e. they should be only applicable
to indexed information).

An AT will be able to execute transactions (via the AT API) which can include different types of transactions
such as those for using AM (where this is applicable according to the host platform).

In order to satisfy the Lottery use case the following API functions need to be available to the AT engine:

Get_Last_Time_Stamp (will return the "time stamp" of the previous block)
Get_Tx_After (given a "time stamp" return the first tx id sent to the AT after it)
Get_Tx_Type (for a given tx id return the type and subtype of the tx)
Get_Tx_Amount (for a given tx id return the amount of host funds)
Get_Tx_Time_Stamp (for a given tx id return its "time stamp")
Get_Tx_Ticket_Num (for a given tx id return a "ticket value" *)
Get_Tx_Source_Account (given a tx id this returns the account id of the funds sender)
Get_Old_Balance (get the account balance of the AT after it had been last executed)
Send_Old_To_Account (for a given account will send the AT's old balance)
Send_Funds_to_Account (for a given account will send the given amount if the balance is enough to do so)

* note that this function won't return until enough confirmations have allowed it to become available (so
the AT will effectively sleep until it is ready to continue execution)

Time stamp values need to also include the transaction # (zero when requesting a block time stamp) so that it
is as simple as possible to do looping with API commands such as Get_Tx_After (and instead are really a block
number and transaction number concatenated).

Further API functions that will be required for the Dormant Funds Transfer are as follows:

Get_Creator (will return the account/address of the AT's creator)
Get_Balance (get the current account balance of the AT)
Get_AM_Val (for a given tx id return the requested 64 bit "chunk" of AM data)
Send_All_To_Account (for a given account will send the AT's remaining balance)

Some other suggested API functions not covered by the above use cases are as follows:

Send_AM (will cause the script to send an AM tx to a given account/address)

Note that the "Automated Transactions API Specification" document will provide a formal description for every
function that an AT can be guaranteed to use.

Technical Specifications

An AT creation tx would include header information along with the byte code and would optioinally include the
amount of host funds to transfer to become the AT's initial account balance (allowing execution to start from
the same block as the creation tx occurs).

0x0001 ; AT version (16 bits)
0x0000 ; (reserved) (16 bits)
0x0001 ; code pages (16 bits) (number of 256 byte pages required)
0x0001 ; data pages (16 bits) (number of 256 byte pages required)
0x0000 ; call stack (16 bits) (number of 256 byte pages required)
0x0000 ; user stack (16 bits) (number of 256 byte pages required)

[Code - to be length prefixed]

[Initial Data - also to be length prefixed]

Although theoretically an AT could be 32MB in size an AT will have to be restricted to a much smaller maximum
amount and all data bytes will need to be zeroed prior to initial execution. Note the version number would be
incremented with each release that either extends the AT interpreter or adds newer AT APIs.

State storage would need to include all data but also all other state that is necessary to "continue" running
an AT after any step it had previously stopped at.

0x00000000 ; flags (32 bits)
0x00000000 ; pc (32 bits) program counter
0x00000000 ; cs (32 bits) call stack counter
0x00000000 ; us (32 bits) user stack counter
0x00000000 ; pce (32 bits) program counter error handler point
0x00000000 ; pcs (32 bits) program counter next starting point
0x00000000 ; sleep_until (32 bits) execution to wait until >= this block
0x0000000000000000 ; stopped at balance (64 bits)*
0x0000000000000000000000000000000000000000000000000000000000000000 ; pseudo register A (256 bits)
0x0000000000000000000000000000000000000000000000000000000000000000 ; pseudo register B (256 bits)

* if AT stops set to current balance and execution will not continue until balance is greater (then clear it)

In order to conserve space it would be recommended to use two flags to indicate a zero value for the A and B
register (saving either 32 or 64 bytes).


The "flags" would include indicate whether the program has paused (so excution will be continued after the op
that had been last executed), stopped (so execution would continue from the beginning with all the data being
kept intact) or terminated (some ideas about how to handle "termination" will need to be examined and perhaps
the "reserved" part of the code header might need to be used to set some flags for this purpose).

Data addresses are a signed 32 bit value (negative values being invalid) that are used for accessing strictly
aligned 64 bit data value. If you consider a typical raw byte dump as follows:

00000000  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
          0x00000000 (address)    ------------------------
                                  0x00000001 (address)

then each line of 16 bytes would be data for two address (i.e. 0x00000000 and 0x00000001). Addresses for code
are also 32 bit. An op code is a single byte and AT API function numbers are 16 bits. For "branch" commands a
single signed byte offset is used (so can jump to another op code up to +-127 bytes from the current pc). The
"value" type for being able to set a constant value is a signed 64 bit integer.

The following table summarises the types:

opcode   (int8_t)   0x00
offset   (int8_t)   0x00
func #   (int16_t)  0x0000
address  (int32_t)  0x00000000
value    (int64_t)  0x0000000000000000

For AT creation and state updates all values broadcast or hashed must be "little endian". The actual physical
storage is of course up to each platform.

The following are suggested op codes (the hex values are what has been used in the "at.cpp" prototype).

Op Code           Hex    Additional             Operation (and comments)
-------           ----   -----------            -------------------------------------------------------------
NOP               0x7f                          (can be used for padding if required)
SET_VAL           0x01   addr,value             @addr = value
SET_DAT           0x02   addr1,addr2            @addr1 = $addr2
CLR_DAT           0x03   addr                   @addr = 0 (to save space rather than using SET_VAL with 0)
INC_DAT           0x04   addr                   @addr += 1
DEC_DAT           0x05   addr                   @addr -= 1
ADD_DAT           0x06   addr1,addr2            @addr1 += $addr2
SUB_DAT           0x07   addr1,addr2            @addr1 -= $addr2
MUL_DAT           0x08   addr1,addr2            @addr1 *= $addr2
DIV_DAT           0x09   addr1,addr2            @addr1 /= $addr2
BOR_DAT           0x0a   addr1,addr2            @addr1 |= $addr2
AND_DAT           0x0b   addr1,addr2            @addr1 &= $addr2
XOR_DAT           0x0c   addr1,addr2            @addr1 ^= $addr2
NOT_DAT           0x0d   addr                   @addr = ~$addr (bitwise not)
SET_IND           0x0e   addr1,addr2            @addr1 = $($addr2) (fetch indirect)
SET_IDX           0x0f   addr1,addr2,addr3      @addr1 = $($addr2 + $addr3) (fetch indirect indexed)
PSH_DAT           0x10   addr                   @--ustack_top = $addr
POP_DAT           0x11   addr                   $addr = @ustack_top++
JMP_SUB           0x12   addr                   @--cstack_top = pc + 5, pc = addr
RET_SUB           0x13                          pc = @cstack_top++
IND_DAT           0x14   addr1,addr2            @($addr1) = $addr2 (store indirect)
IDX_DAT           0x15   addr1,addr2,addr3      @($addr1 + $addr2) = $addr3 (store indirect indexed)
MOD_DAT           0x16   addr1,addr2            @addr1 %= $addr2
SHL_DAT           0x17   addr1,addr2            @addr1 <<= $addr2
SHR_DAT           0x18   addr1,addr2            @addr1 >>= $addr2
JMP_ADR           0x1a   addr                   pc = addr
BZR_DAT           0x1b   addr,offset            if $addr == 0 then pc += offset
BNZ_DAT           0x1e   addr,offset            if $addr != 0 then pc += offset
BGT_DAT           0x1f   addr1,addr2,offset     if $addr1 > $addr2 then pc += offset
BLT_DAT           0x20   addr1,addr2,offset     if $addr1 < $addr2 then pc += offset
BGE_DAT           0x21   addr1,addr2,offset     if $addr1 >= $addr2 then pc += offset
BLE_DAT           0x22   addr1,addr2,offset     if $addr1 <= $addr2 then pc += offset
BEQ_DAT           0x23   addr1,addr2,offset     if $addr1 == $addr2 then pc += offset
BNE_DAT           0x24   addr1,addr2,offset     if $addr1 != $addr2 then pc += offset
SLP_DAT           0x25   addr                   sleep until $addr timestamp*
FIZ_DAT           0x26   addr                   if $addr == 0 then pc = pcs and stop
STZ_DAT           0x27   addr                   if $addr == 0 then stop
FIN_IMD           0x28                          pc = pcs and stop
STP_IMD           0x29                          stop
SLP_IMD           0x2a                          sleep until the next block
ERR_ADR           0x2b   addr                   pce = addr
SET_PCS           0x30                          pcs = pc + 1
EXT_FUN           0x32   func                   func( )
EXT_FUN_DAT       0x33   func,addr              func( $addr )
EXT_FUN_DAT_2     0x34   func,addr1,addr2       func( $addr1, $addr2 )
EXT_FUN_RET       0x35   func,addr              @addr = func( )
EXT_FUN_RET_DAT   0x36   func,addr1,addr2       @addr1 = func( $addr2 )
EXT_FUN_RET_DAT_2 0x37   func,addr1,addr2,addr3 @addr1 = func( $addr2, $addr3 )

* where timestamp is actually a 32 bit block height stored in the high order 32 bits of the address value and
if the block height is not greater than the current block height then it will instead just operate as SLP_IMD

All instructions that modify the pc will need to ensure the value it is being set to is a valid code address.

Note that there is only a "code" and "data" segment. The "stacks" (if used) are actually included at the last
part of the data segment. If using any stack operations (i.e. PSH_DAT/POP_DAT/JMP_SUB/RET_SUB) then sufficent
data storage for both variables and the stacks would need to be allocated.

The call stack preceeds the user stack (with both growing backwards). The following picture illustrates this:

| data         |
|              |
|              |
|              |
|              |
|              |
|              |
| call stack   |
|              |
|              |
| user stack   |

For the purpose of being able to create an AT and to store its state after executing steps there will need to
specially created host transactions.