## Nobicoin Virtual Machine
`vm.py`
We write our codes for this section in this file.
```
class VM:
def __init__(self, storage, transaction):
self.storage = storage
self.tx = transaction
def transaction_type(self):
# detect the transaction type( contract call, asset transfer, contract deployment)
pass
def parse(self, code):
# Parse the contract code and return it in a format that's easy to execute.
pass
def execute(self, parsed_code):
# Execute the parsed code.
pass
def get_storage(self, address):
# Get the storage for the given address.
return self.storage.get(address, {})
def set_storage(self, address, key, value):
# Set a value in the storage for the given address.
if address not in self.storage:
self.storage[address] = {}
self.storage[address][key] = value
def run(self, code):
parsed_code = self.parse(code)
self.execute(parsed_code)
if __name__=="__main__":
# write testing purpose thing in here
pass
```
**trace and dependencies:**
> 1. depend to the kv file storage
> 2. it get used when a miner wants to create new block during the each transaction proccessing
**contract language design**:
```
file extention .nob
```
`variable_types: uint, string, address, mapping`
```
pragma we.are.nob
var uint x = value1;
var string y = value2;
var address z = value3;
var mapping l (address , uint);
constructor(inputs){
uint x = value1;
string y = value2;
address z = value3;
}
func function_name(uint v1, address v2){
if (v1 > 10){
z = v2
} else{
z = nobi.sender
}
}
```
**tasks**:
> 1. in this file first we check we need to fire the vm or not. conditions:
> a. the destination address is zero address (nobi00000)
> b. the destination address has code storage
> 2. if it was just simple coin transfer we rturning true and current state root and let the codes continue the proccsess
> 3. if the destination was zero address (nobi000) thats means we have new contract to deploy. so we push the contract on the code storage space of the account and run constructor and imply the result on the storage of the account .
> 4. if it was contract call we should first load the destination code and sotrage and get the call data and the code and start the interprate the contract code and apply the result on the destination contract storage.
> 5. we should also design the data read api in this file for reading the storage of the contracts
> 6. we should impelement the state root approach to commit the state root in each new block and for doing this after each function the vm run it should return the new state root
> 7. we should implement the interpretur for our language
**fungible token contract in Nobi Language (erc20 like)**
```
pragma we.are.nob
var string token_name;
var uint max_supply;
var mapping balance (address , balance);
constructor(string name, uint supply, addree reciver){
token_name = name;
max_supply = supply;
balance[reciver] = max_supply;
}
func transfer (uint amount, address reciver){
internal_var sender_balance = balance [nobi.sender]
internal_var reciver_balance= balance [reciver]
if (sender_balance >= amount){
balance[nobi.sender] = sender_balance - amount;
balance [reciver] = reciver_balance + amount;
} else {
reject;
}
}
```
**Instrutions**
```
<!-- GET instruction: read data in key and set it in var -->
GET {var_name} {key}
<!-- SET instruction: write data in var in key storage space -->
SET {key} {var_name}
<!-- Var instruction: define a variable and set initial value -->
VAR {var_name} {if exist? initial_value : default value}
INC {var_name}
ADD {var_name1} {var_name2} {dst_var_name}
SUB {var_name1} {var_name2} {dst_var_name}
MOL {var_name1} {var_name2} {dst_var_name}
DIV {var_name1} {var_name2} {dst_var_name}
GT {var_name1} {var_name2} {dst_var_name}
LT {var_name1} {var_name2} {dst_var_name}
GTE {var_name1} {var_name2} {dst_var_name}
LTE {var_name1} {var_name2} {dst_var_name}
EQ {var_name1} {var_name2} {dst_var_name}
NEQ {var_name1} {var_name2} {dst_var_name}
JIF {condition_var_name} {dst_line / Lable} {else_line, els_lable}
CONCAT {var_name_1} {var_name_2} {dst_var_name}
HALT
<!-- MSG_SENDER instruction: the initial value is set to the transaction sender -->
MSG_SENDER
FUNCTION_SELECTOR
INPUTS_0
INPUTS_1
INPUTS_2
...
INPUTS_7
```
**Fungible token Contract with nobi assembly**
```
VAR is_constractor 0
VAR constractor_signature 1001
VAR is_transfer 0
VAR transfer_signature 1002
VAR suffix = "_balance"
EQ FUNCTION_SELECTOR constractor_signature is_contractor
EQ FUNCTION_SELECTOR transfer_signature is_transfer
JIF is_contractor Constructor
JIF is_transfer Transfer
###Constructor:
VAR total_suplly 10000
// VAR token_name "noooobtoken"
VAR key
CONCAT MSG_SENDER suffix key
Set key total_suplly
HALT
###Transfer:
// INPUTS_0 Amount
// INPUTS_1 Receiver
VAR key
CONCAT MSG_SENDER suffix key
VAR balance
GET balance key
VAR is_not_enough_balance 0
LT balance, INPUTS_0 is_not_enough_balance
JIF is_not_enough_balance Halt_the_program
VAR remaining_balance
SUB balance INPUTS_0 remaining_balance
SET key remaining_balance
VAR receiver_key
CONCAT INPUTS_1 suffix receiver_key
VAR receiver_balance
GET receiver_balance receiver_key
VAR new_receiver_balance
ADD receiver_balance INPUTS_0 new_receiver_balance
SET receiver_key new_receiver_balance
HALT
Halt_the_program:
HALT