Iadix HTML 5.0 multichain technologie
Blockchain, solutions économiques et commerce en ligne
Une blockchain pour les relier toutes

posted on 19/03/17 13:01 60 views

The purenode blockchain engine rely on a framework made in C to handle low level function such as memory managment, software typing, I/O, and network protocol definition.

It is strongly though with scalability and parallelisation in mind, based on lockless list of event who can be hanlded either as "green threads", where events are processed sequentially in a single thread, or sharing dynamically a list of dynamic object between differents thread, locklessly if only one thread need to modify the data, which can be usefull when an UI or front end need to only read the data, keeping its local copy synchronized and coherent if other thread change this list of object.

 

The memory model can be though in 3 layers :

 

 

 


 

  1. Memory area :



    base memory model

    They are initialized for each threads, contain a stack of free zones initialized with a fixed memory size,and keep track of all memory allocated and free areas.

     

    The implementation of the memory area and the base allocator is found is this file

     

    https://github.com/iadix/purenode/blob/master/libcon/base/mem_base.c

     

    The first initialization of the memory system is in this function

     

    https://github.com/iadix/purenode/blob/master/libcon/base/mem_base.c#L24

     

    typedef struct  memory zone descriptor  
     {    
      mem_ptr ptr; pointer to the memory location
      mem_size size; size of the allocated memory
     }mem_zone_desc;    
         
     typedef struct     referenced memory zone definition
     {    
      mem_zone_desc mem;  memory description
      unsigned int area_id;  area id
      unsigned int n_refs;  reference counter
      unsigned int time;  allocation / used time
      zone_free_func_ptr free_func;  custom function on free
     }mem_zone;    
         
     typedef mem_zone * mem_zone_ptr;  
     typedef const mem_zone_desc * mem_zone_desc_ptr;  
         
     typedef struct    memory area
     {    
      unsigned int area_id;  id of the area
      mem_area_type_t type;  type tree node or plain
      mem_ptr lock_sema;  semaphore for multi thread allocation
      mem_ptr area_start;  start of area in process memory
      mem_ptr area_end;  end of area in process memory
      mem_zone_desc zones_free[MAX_MEM_ZONES];  descriptor for free zones
      mem_zone_ptr zones_buffer;  dyanmic buffer of free zones
     }mem_area;    
         
         

     

    https://github.com/iadix/purenode/blob/master/libcon/base/mem_base.c#L484

     

    OS_API_C_FUNC(void)  init_mem_system() initialize memory system
    {    
     __global_mem_areas = get_next_aligned_ptr(kernel_memory_map_c(MAX_MEM_AREAS*sizeof(mem_area)+8)); allocate memory from the kernel for memory areas structures
     __global_mem_zones = get_next_aligned_ptr(kernel_memory_map_c(MAX_MEM_AREAS*MAX_MEM_ZONES*sizeof(mem_zone)+8)); allocate memory from the kernel for available memory zones for each areas
         
     memset_c(__global_mem_areas, 0,MAX_MEM_AREAS*sizeof(mem_area) ); initialize memory area pool
     memset_c(__global_mem_zones, 0,MAX_MEM_AREAS*MAX_MEM_ZONES*sizeof(mem_zone) ); initlialize memory zone pool
     }

     

     https://github.com/iadix/purenode/blob/master/libcon/base/mem_base.c#L678

     

    OS_API_C_FUNC(unsigned int) init_new_mem_area(mem_ptr phys_start,mem_ptr phys_end,mem_area_type_t type) initialize new memory area from start to end , type is either tree node or regular memory 
     {    
     int n;    
         
     n = 0;    
     while (!compare_z_exchange_c(&area_lock, 1)) if ((n++) >= 1000)return 0;  wait for free lock on the global memory where the memory area are stored
         
         
     n = 0;    find unused memory area in the pool
     while(n<MAX_MEM_AREAS)    
     {    
     if(__global_mem_areas[n].area_start == 0x00000000)    initialize new memory area from the input parameters
     {    
     __global_mem_areas[n].area_start =  phys_start;  
     __global_mem_areas[n].area_id = n+1;  
     __global_mem_areas[n].area_end = phys_end;  
     __global_mem_areas[n].type = type;  
     __global_mem_areas[n].zones_buffer = &__global_mem_zones[MAX_MEM_ZONES*n];  assign pointer to zone buffer in the global area
     __global_mem_areas[n].lock_sema = PTR_NULL;  
     memset_c (__global_mem_areas[n].zones_free , 0,MAX_MEM_ZONES*sizeof(mem_zone_desc));  initialize free zones stack
         
     __global_mem_areas[n].zones_free[0].ptr = get_next_aligned_ptr(__global_mem_areas[n].area_start);  initialize initial free zone to the whole avaliable memory for this area
     __global_mem_areas[n].zones_free[0].size = get_aligned_size(__global_mem_areas[n].area_start,__global_mem_areas[n].area_end);  
         
     area_lock =  0;   release the lock and return
     return __global_mem_areas[n].area_id;    
         
     }    
     n++;    next area
     }    
         
     area_lock = 0;   no free area found 
     return 0xFFFFFFFF;    
         
     }    
     

     

    https://github.com/iadix/purenode/blob/master/libcon/base/mem_base.c#L1262

     

    OS_API_C_FUNC(unsigned int) allocate_new_zone(unsigned int area_id,mem_size zone_size,mem_zone_ref *zone_ref)   allocate a new zone and output reference to it in zone_ref
     {    
     unsigned int  n;  
     mem_area * area_ptr;  
         
     area_ptr = get_area(area_id);  find area, or get default memory for the thread
     if(area_ptr==PTR_NULL)  return 0;  
         
     release_zone_ref (zone_ref);    release reference to object in output parameter
         
     zone_size =  ((zone_size&0xFFFFFFF0)+16);  
     n = 0;  
     while(n>MAX_MEM_ZONES)    
     {    
      if(area_ptr->zones_buffer[n].mem.ptr ==   PTR_NULL)  find available zone in the area buffer
      {    
     mem_zone * nzone;  
         
     nzone =  &area_ptr->zones_buffer[n];  
     if(find_free_zone(area_ptr,zone_size, &nzone->mem)==1) find free zone in the memory pool and assign the memory descriptor in the zone buffer
     {    
      if(allocate_zone(area_ptr,&nzone->mem)==1)  allocate the zone and reference it to the output reference
      {  
      nzone->area_id = area_ptr->area_id;  
      nzone->n_refs = 1;  
      nzone->free_func= PTR_NULL;  
      memset_c (nzone->mem.ptr,0x00,nzone->mem.size);  
      zone_ref-> zone = nzone;  
      return 1;  
       
       else return 0;  allocation failure not enough free memory
     }    no more free zones
     else return 0    
     }    
     n++;    next avaiable memory zone
     }    
     return 0;    no available new zone found
     }    

     

     

    The main api to use the base memory allocator is in the file

     

     https://github.com/iadix/purenode/blob/master/libcon/base/mem_base.h

     

    LIBC_API void C_API_FUNC init_default_mem_area (unsigned int size);
    LIBC_API unsigned int C_API_FUNC mem_area_enable_sem (unsigned int area_id);  
    LIBC_API unsigned int C_API_FUNC init_new_mem_area (mem_ptr phys_start, mem_ptr phys_end,mem_area_type_t type);  
    LIBC_API unsigned int C_API_FUNC free_mem_area (unsigned int area_id);  
    LIBC_API unsigned int C_API_FUNC allocate_new_zone (unsigned int area_id, mem_size zone_size, mem_zone_ref *zone_ref);  
    LIBC_API unsigned int C_API_FUNC allocate_new_empty_zone (unsigned int area_id,mem_zone_ref *zone_ref);  
    LIBC_API int C_API_FUNC expand_zone (mem_zone_ref *ref,mem_size new_size);  
    LIBC_API int C_API_FUNC realloc_zone (mem_zone_ref *zone_ref,mem_size new_size);  
         
         
    LIBC_API void C_API_FUNC copy_zone_ref (mem_zone_ref_ptr dest_zone_ref,mem_zone_ref_const_ptr zone_ref);  
    LIBC_API void C_API_FUNC copy_zone_const_ref (mem_zone_const_ref_ptr dest_zone_ref,mem_zone_const_ref_ptr zone_ref);  
    LIBC_API unsigned int C_API_FUNC create_zone_ref (mem_zone_ref *dest_zone_ref,mem_ptr ptr,mem_size size);  
    LIBC_API void C_API_FUNC init_mem_system ();  
    LIBC_API void C_API_FUNC dump_mem_used (unsigned int area_id);  
    LIBC_API void C_API_FUNC dump_mem_used_after (unsigned int area_id,unsigned int time);  
         
    LIBC_API mem_ptr C_API_FUNC get_zone_ptr (mem_zone_ref_const_ptr ref,mem_size ofset);  
    LIBC_API mem_size C_API_FUNC get_zone_size (mem_zone_ref_const_ptr ref);  
         
    LIBC_API unsigned int C_API_FUNC find_zones_used (unsigned int area_id);  
    LIBC_API unsigned int C_API_FUNC get_zone_numref (mem_zone_ref *zone_ref);  
         
         
    LIBC_API void C_API_FUNC swap_zone_ref (mem_zone_ref_ptr dest_zone_ref, mem_zone_ref_ptr src_zone_ref);  
    LIBC_API int C_API_FUNC align_zone_memory (mem_zone_ref *zone_ref, mem_size align);  
         
         
    LIBC_API int C_API_FUNC set_mem_area_id (unsigned int area_id);  
    LIBC_API int C_API_FUNC set_tree_mem_area_id (unsigned int area_id);  
    LIBC_API unsigned int C_API_FUNC get_mem_area_id ();  
    LIBC_API unsigned int C_API_FUNC get_tree_mem_area_id ();  

     

     

    An example initialization of the memory area system is found in the launcher executable 

     

    https://github.com/iadix/purenode/blob/master/launcher/main.c#L30

     

     

     

    int main(int argc, char **argv)
    {  
     mem_zone_ref params =  { PTR_NULL };
     mem_ptr * params_ptr;
     int done =  0,n;
       
     init_mem_system  ();
     init_default_mem_area  (8 * 1024 * 1024);
     set_exe_path  ();
     if (!set_home_path("purenode"))  
     {  
      console_print("could not set home dir 'purenode' \n");
      return 0;
     }  
       
     network_init ();
     load_module ("modz/libbase.tpo", "libbase", &libbase_mod);
     load_module ("modz/protocol_adx.tpo", "protocol_adx", &protocol_mod);
     load_module ("modz/block_adx.tpo", "block_adx", &block_mod);
     load_module ("modz/iadixcoin.tpo", "iadixcoin", &iadix_mod);
       
     app_init =  (app_func_ptr)get_tpo_mod_exp_addr_name(&iadix_mod, "app_init", 0);
     app_start =  (app_func_ptr)get_tpo_mod_exp_addr_name(&iadix_mod, "app_start", 0);
     app_loop =  (app_func_ptr)get_tpo_mod_exp_addr_name(&iadix_mod, "app_loop", 0);
     app_stop =  (app_func_ptr)get_tpo_mod_exp_addr_name(&iadix_mod, "app_stop", 0);
       
     if (!app_init((mem_zone_ref_ptr)PTR_NULL))  
     {  
      console_print("could not initialize app ");
      console_print(iadix_mod.name);
      console_print("\n");
      return 0;
     }  
     if (daemonize("purenode") <= 0)  
     {  
      console_print("daemonize failed \n");
      return 0;
     }  
       
     if (argc > 1)  
     {  
     allocate_new_zone (0, argc*sizeof(mem_ptr),¶ms);
     for (n = 0; n < (argc-1); n++)  
     {  
     params_ptr =  get_zone_ptr(¶ms, n*sizeof(mem_ptr));
     (*params_ptr) =  argv[n+1];
     }  
     params_ptr = get_zone_ptr(¶ms, n*sizeof(mem_ptr));
     (*params_ptr) =  PTR_NULL;
     }  
       
     if (!app_start(¶ms))  
     {  
      console_print("could not start app ");
      console_print(iadix_mod.name);
      console_print("\n");
      return 0;
     }  
       
     while (isRunning())  
     {  
      app_loop(PTR_NULL);
     }  
       
     app_stop(PTR_NULL);  
     }  

     

     

    The equivalent for the stdc allocation style is found in the file :

    https://github.com/iadix/purenode/blob/master/libcon/base/std_mem.h

     

    The string api is an example of higher level use of the allocation system

    https://github.com/iadix/purenode/blob/master/libcon/include/strs.h

    https://github.com/iadix/purenode/blob/master/libcon/strs.c


  2. Dynamic Tree System Runtime

    tree memory model

    The base api to access the tree node system is defined in this file :

    https://github.com/iadix/purenode/blob/master/libbase/include/tree.h

    Example of tree system to decode and parse blockchain protocol message based on json hard-typed templates:

    https://github.com/iadix/purenode/blob/master/protocol_adx/protocol.c#L1370

     


     

  3. Application layer 

    application module model

    The message processing in the blockchain node application can show an example of high level management of the dynamic tree with reference pointers.

    https://github.com/iadix/purenode/blob/master/purenode/main.c#L1419

    int process_node_messages(mem_zone_ref_ptr node)
     {  
     mem_zone_ref msg_list =  { PTR_NULL };
     mem_zone_ref my_list =  { PTR_NULL };
     mem_zone_ref_ptr msg =  PTR_NULL;
       
       
     if (!tree_manager_find_child_node(node, NODE_HASH("emitted queue"), NODE_BITCORE_MSG_LIST,  &msg_list))return 0;
       
       
     for (tree_manager_get_first_child(&msg_list, &my_list, &msg); ((msg != NULL) && (msg->zone != NULL));  tree_manager_get_next_child(&my_list, &msg))
     {  
     char  cmd[16];
     mem_zone_ref  payload_node = { PTR_NULL };
     int  ret;
       
     if (!tree_manager_get_child_value_str(msg, NODE_HASH("cmd")  , cmd, 12, 16))continue;
       
     tree_manager_find_child_node(msg, NODE_HASH("payload"), NODE_BITCORE_PAYLOAD , &payload_node);
       
     ret = handle_message(node, cmd , &payload_node);
     tree_manager_set_child_value_i32(msg, "handled",  ret);
     release_zone_ref(&payload_node);  
     }  
     tree_remove_child_by_member_value_dword (&msg_list, NODE_BITCORE_MSG, "handled", 1);  
     tree_remove_child_by_member_value_lt_dword (&msg_list, NODE_BITCORE_MSG, "recvtime", get_time_c()-100);  
       
     release_zone_ref(&msg_list);  
     return 1;  
     }  

     

    Message handling in the node application code

    https://github.com/iadix/purenode/blob/master/purenode/main.c#L1323


    int handle_message(mem_zone_ref_ptr node,const char *cmd,mem_zone_ref_ptr payload)
    {  
    unsigned int  testing;
       
    if (!strncmp_c(cmd, "headers", 7))return  handle_headers(node, payload);
    if (!strncmp_c(cmd, "block", 5))return  handle_block(node, payload);
    if (!strncmp_c(cmd, "inv", 3))return  handle_inv(node, payload);
       
       
    if (!tree_manager_get_child_value_i32(node, NODE_HASH("testing_chain"),  &testing))
     testing =  0;
       
    if (testing > 0)return 1;  
       
    if (!strncmp_c(cmd, "verack", 6))return  handle_verack(node, payload);
    if (!strncmp_c(cmd, "version", 7))return  handle_version(node, payload);
    if (!strncmp_c(cmd, "ping", 4))return  handle_ping(node, payload);
    if (!strncmp_c(cmd, "pong", 4))return  handle_pong(node, payload);
    if (!strncmp_c(cmd, "addr", 4))return  handle_addr(node, payload);
    if (!strncmp_c(cmd, "getdata", 7))return  handle_getdata(node, payload);
       
    return 0;  
    }  

     

    High level implementation of the block explorer http request can be seen in this file :

    https://github.com/iadix/purenode/blob/master/block_explorer/block_explorer.c


    https://github.com/iadix/purenode/blob/master/block_explorer/block_explorer.c#L733

     

    OS_API_C_FUNC(int blocks(const char *params, const struct http_req *req, mem_zone_ref_ptr result)  
     {  
     hash_t  nullhash;
     char  chash[65], prm[65];
     mem_zone_ref  time_index_node = { PTR_NULL }, block_index_node = { PTR_NULL }, new_block = { PTR_NULL }, block_list = { PTR_NULL };
     struct string  blk_path = { PTR_NULL };
     ctime_t  time;
     uint64_t  nblks=0;
     size_t  page_num;
     unsigned int  block_time, limit, num, idx,tidx,n,start_time,cur_time;
     const struct key_val  *blockdate, *pageNum, *sinceblock, *beforeblock, *txl;
       
     tree_manager_find_child_node (&my_node, NODE_HASH("block index"), NODE_BITCORE_HASH,  &block_index_node);
     tree_manager_find_child_node (&my_node, NODE_HASH("block time"), NODE_GFX_INT,  &time_index_node);
     tree_manager_get_child_value_i64 (&my_node, NODE_HASH("block height") , &nblks);
       
     memset_c(nullhash, 0 sizeof(hash_t));
       
     if ((pageNum = find_key(req->query_vars, "pageNum"))  != PTR_NULL)
     page_num = strtoul_c(pageNum->value.str,PTR_NULL,10);
      else
     page_num = 0;
       
     if (isdigit_c(params[0]))  
     limit =  strtoul_c(params, PTR_NULL, 10);
      else
     limit = 0;
       
     if ((limit < 1) || (limit > 10))  
     limit=   10;
       
     txl = find_key(req->query_vars, "tx");
       
       
     tree_manager_add_child_node(result, "blocks", NODE_JSON_ARRAY,  &block_list);
       
     if ((blockdate = find_key(req->query_vars, "BlockDate"))  != PTR_NULL)
     {  
     ctime_t  next_day;
     time =  parseDate(blockdate->value.str);
     block_time =  0xFFFFFFFF;
     next_day = time + 24 * 3600;
     idx =  nblks;
     while ((--idx) > 1)  
     {  
     if (!tree_mamanger_get_node_dword(&time_index_node, (idx) * 4, &block_time)) break;
     if (block_time < next_day) break;
     }  
       
       
       
     if (idx <= 1)  
     {  
      release_zone_ref(&block_list);
      release_zone_ref(&block_index_node);
      release_zone_ref(&time_index_node);
     return 1;  
     }  
       
     num = 0;
     tidx = 0;
     while ((block_time >= time)&&((idx--)>0))  
     {  
     if (num < limit)  
     {  
     if (tree_manager_create_node("block", NODE_GFX_OBJECT, &new_block))  
     {  
     tree_manager_get_node_str(&block_index_node, idx * 32 , chash, 65, 16);
     n =  0;
     while (n < 32)  
     {  
     prm[(31 - n) * 2 + 0] =  chash[n * 2 + 0];
     prm[(31 - n) * 2 + 1] =  chash[n * 2 + 1];
     n++;  
     }  
     prm[64] =  0;
       
     if (block(prm, req, &new_block))  
     {  
     if (tidx >= page_num*limit)  
     {  
     tree_manager_node_add_child(&block_list,  &new_block);
     num++;  
     }  
     }  
     release_zone_ref(&new_block);  
     }  
     }  
     tidx++;  
       
     if (!tree_mamanger_get_node_dword(&time_index_node, idx * 4 , &block_time))
      block_time = 0;
     }  
     tree_manager_set_child_value_i32(result, "limit", l imit);
     tree_manager_set_child_value_i32(result, "page_num" page_num);
     tree_manager_set_child_value_i32(result, "numblocks",  tidx);
     }  


    Implementation of the rpc server request can be seen in this file :

    https://github.com/iadix/purenode/blob/master/rpc_wallet/rpc_methods.c



    https://github.com/iadix/purenode/blob/master/rpc_wallet/rpc_methods.c#L1350


    OS_API_C_FUNC(int)   listunspent(mem_zone_ref_const_ptr params, unsigned int rpc_mode, mem_zone_ref_ptr result)  
     {    
      mem_zone_ref minconf = { PTR_NULL }, maxconf = { PTR_NULL }, unspents = { PTR_NULL }, addrs = { PTR_NULL };  
      mem_zone_ref my_list = { PTR_NULL };  
      mem_zone_ref_ptr addr;  
      uint64_t total=0;  
      size_t min_conf = 0, max_conf = 9999;  
      size_t max = 200,ntx=0;  
         
      if (!tree_manager_add_child_node(result,"unspents", NODE_JSON_ARRAY, &unspents))  
      return 0;  
         
      tree_manager_get_child_at(params, 0, &minconf);  
      tree_manager_get_child_at(params, 1, &maxconf);  
      tree_manager_get_child_at(params, 2, &addrs);  
         
      tree_mamanger_get_node_dword(&minconf, 0, &min_conf);  
      tree_mamanger_get_node_dword(&maxconf, 0, &max_conf);  
         
         
      release_zone_ref(&maxconf);  
      release_zone_ref(&minconf);  
         
      for (tree_manager_get_first_child(&addrs, &my_list, &addr); ((addr != NULL) && (addr->zone != NULL)); tree_manager_get_next_child(&my_list, &addr))  
      {  
      btc_addr_t my_addr;  
      tree_manager_get_node_btcaddr (addr, 0, my_addr);  
      list_unspent (my_addr, &unspents, min_conf, max_conf, &total, &ntx, &max);  
      }  
         
         
      tree_manager_set_child_value_i64(result, "ntx", ntx);  
      tree_manager_set_child_value_i64(result, "total",total );  
         
      release_zone_ref (&addrs);  
      release_zone_ref (&unspents);  
         
         
     return 1;    
     }    
0 coms.
Purenode whitepaper   avatarBitAdmin (9 articles)
posted on 26/01/17 18:01 25 views


Purenode White Paper

Purenode is a modular blockchain engine, which can be adapted to either create new blockchain with customized feature from scratch, or be used as a wallet, masternode and block explorer for most coins.

 

Its design is very simple, programmed in C, and it uses a system of binary module which can be created out of dll or so files, and then loaded on any operating system with the same cpu architecture regardless of the locally installed runtime or libraries or the compiler used to produce them.

 

Bitcore use a monolithic architecture, and alternative blockchains are created by forking the source code tree, changing some hard - coded value and recompiling the core to make the new coin which often contain the masternode server, the block kernel and the wallet in a single application executable, with the hard-coded values specific for the coin compiled in.

 

The block explorer is yet another software bundle, typically based on node.js modules, using its own database synchronized with the blockchain node when the block explorer is first initialized, using a server side template system in javascript, working as a middleware between web browser and the blockchain to visualize blocks.

 

 

With purenode, a new blockchain can be created just by setting the coins parameters in a configuration file and running a new instance of the node without having to recompile or edit any code, and a block explorer with an address cache is already included with an html5 - javascript application connected directly to the node. A system of cache in php or another server side script language can be added for better performance.

 





It also include an html5 javascript wallet able to generate private key and sign transaction using javascript code, allowing maximum privacy, as the private key never leave the browser in clear form, and the only javascript code executing in the browser is able to decypher using user supplied secret, and use these private key to sign transaction right inside the browser. Nodes never have to manipulate or access private key, but still keep track of transaction on public addresses, allowing for read-only wallet for financial audit, like bitmonero watch-only wallet, and the private key manipulation and hash signing is made inside of the browser without the node knowing about the private key at all.

 



 

All the functionalities being modularized, it makes it very easy to adapt the code to specific blockchain needs, or add new functionalities by recompiling the binary module, which can be loaded on any operating system as long as the libcon library is compiled for this host. The design is small, < 32Mo of ram used, and <=1mo of binaries most of which are operating system agnostic.

 

The design rely on a framework of dynamic data tree, with an internal memory allocator that use reference counting mechanism rather than standard C allocation, which allow for easy sharing of data pointer between different modules without pointer ownership, and allow the same ease of programming than java like languages where there is no free of memory, but acquiring and releasing of objects references, the powerful system of dynamic data tree allow to represent a hierarchy of dynamically typed nodes, each node being explicitly typed and containing binary data and/or a list children references to other nodes.

 

 

 

 

 

 

The configuration file for the coin looks like this :

 

iadix.conf

{

"name":"purenode",
"seed_node_host":"iadix.com",
"seed_node_port":16714,
"p2p_port":16819,
"magic":0xD9BEFECA, 
"version":60018,
"sign_mod":"ecdsa",
"pubKeyVersion":0x19,

"staking":

{

"staking_kernel":"stake_pos3",
"target spacing":64,
"target timespan":960,
"stake reward":150000000,
limit:0x1B00FFFF

},
"mining":
{

"target spacing":64,
"target timespan":960,
"limit":0x1E0FFFFF,
"reward":10000000000000,
"last_pow_block":200,
"paytxfee":10000

},
"rpc_wallet":
{

"module":"rpc_wallet",
"rpc_port":16820,
"index":"/wallet",
"page file":"wallet.html"

},
"block_explorer":
{

"module":"block_explorer",
"base path":"/api/",
"page file":"blocks.html"

},
"genesis":
{

"version" :1,
"time" :1466419085,
"bits" :0x1e0fffff,
"nonce" :579883,
"InitialStakeModifier":0,
"InitialStakeModifier2":0

}}

 

The design rely on a framework of dynamic data tree, with an internal memory allocator that use reference counting mechanism rather than standard C allocation, which allow for easy sharing of data pointer between different modules without pointer ownership, and allow the same ease of programming that java like language where there is no free of memory, but aquiring and releasing of object reference, and the dynamic data tree allow to represent a hierarchy of typed node, each node has a type and a list of reference to other nodes.

 

The parsing of the configuration file looks like this :

 

mem_zone_ref node_config;

unsigned int node_port, seed_port;

struct string node_port_str;

struct string node_hostname;

 

node_port_str.str = PTR_NULL;

node_port_str.len = 0;

node_port_str.size = 0;

 

node_hostname.str = PTR_NULL;

node_hostname.len = 0;

node_hostname.size = 0;

 

node_config.zone = PTR_NULL;

 

if (get_file("iadix.conf", &data, &data_len)<=0)

{

log_message("unable to file iadix.conf\n", PTR_NULL);

return 0;

}

if (!tree_manager_json_loadb(data, data_len, &node_config))

{

free_c(data);

log_message("unable to parse node config\n", PTR_NULL);

return 0;

}

free_c(data);

 

tree_manager_get_child_value_istr (&node_config, NODE_HASH("seed_node_host"), &node_hostname, 0);

tree_manager_get_child_value_i32 (&node_config, NODE_HASH("seed_node_port"), &seed_port);

tree_manager_get_child_value_istr (&node_config, NODE_HASH("name"), &user_agent, 0);

 

tree_manager_create_node ("log", NODE_LOG_PARAMS, &log);

tree_manager_set_child_value_i32 (&log, "port", node_port);

tree_manager_set_child_value_str (&log, "hostname", node_hostname.str);

log_message ("node port %port% open @ %hostname% ", &log);

release_zone_ref (&log);

 

 

[1478705362] node port 28823827 open @ iadix.com

[1478705366] new message version, 35352084 playload : 100 bytes from iadix.com

:16714

[1478705368] new message verack, 38063939 playload : 0 bytes from iadix.com :16

714

[1478705368] node 82.165.128.213:16714 version 60018 network last block: 34962,

me 88.190.203.85:49352

 

[1478705370] new message ping, 15999093 playload : 8 bytes from iadix.com :1671

4

[1478705371] new message pong, 17993121 playload : 8 bytes from iadix.com :1671

4

[1478705371] block locator:

 

 

 

[1478705373] new message inv, 33129591 playload : 18003 bytes from iadix.com :1

6714

[1478705375] new message block, 18077154 playload : 174 bytes from iadix.com :1

6714

[1478705376] new message block, 90243950 playload : 174 bytes from iadix.com :1

6714

[1478705376] new modifier=22F4FEC149C9617A3AF5B34D506B4211DB61D2E0A6F1AA69AE409B

A222E47029 time=14671632 hash=A611A6783AA6FB83782A454CB11DB2A926E9CCA2678905F839

9ED3AF2B6749AF

[1478705376] ----------------

NEW POW BLOCK

00000FFFFF000000000000000000000000000000000000000000000000000000

00000ED287279BDB4CE0CB9B7E4611143FEB16E5ED4B897EC2B3CF876CFFA260

A611A6783AA6FB83782A454CB11DB2A926E9CCA2678905F8399ED3AF2B6749AF

 

[1478705376] accepted block: A611A6783AA6FB83782A454CB11DB2A926E9CCA2678905F8399

ED3AF2B6749AF , 14671632 - 7 EF96C4CB9CCEE2DDB15839634855DC3265BC028E8D91106740D

0B8EB39F64A18

 

[1478705376] block height : 2 , 223 – 247

 

[1478705292] new message block, 28088885 playload : 477 bytes from iadix.com :16714

[1478705292] new modifier=82059C1ECFF8189D08C69F37A9DBE26042332909D50A169DA564FA67DACA0C05 time=14671634 hash=9D1D236F101428B43471AF03DD54C6A1E394789497D2233423BA7E275FCDD861

[1478705292] ----------------

NEW POW BLOCK

0000033258000000000000000000000000000000000000000000000000000000

000001AEA84D7E7F6E9049BA000D402E2012FE964CF851ECBB667E36CEE9E163

9D1D236F101428B43471AF03DD54C6A1E394789497D2233423BA7E275FCDD861

 

[1478705292] accepted block: 9D1D236F101428B43471AF03DD54C6A1E394789497D2233423BA7E275FCDD861 , 14671634 - 7 D8DC3A8A9F57E0E8F3D0F9CCA1BF91B7F788935096633643D689D8BBA29F1E56

 

[1478705292] block height : 18

 

 

LIBCON ( has to be compiled for the host)

  • memory allocation of references pointer and basic memory manipulation.

  • string and basic text manipulation, utf8.

  • File system access and I/O.

  • Socket and network.

  • XML Parser (expat) used by uPnp.

  • Zlib for compression/decompression.

  • Binary module loader.

  • Base C runtime.

 

LIBBASE (distributed as system agnostic binary module)

  • Dynamic data tree based on references pointer.

  • HTTP protocol.

  • JSON parser.

  • UPNP

  • hashes (SHA256,MD5,RIP160)

 

PROTOCOL (distributed as source)

  • Parsing of bitcore protocol message as binary tree

  • Creation of new message using the bitcore protocol based on binary tree template.

 

BLOCK (distributed as source)

  • Function to check proof of work block header (based on the built-in hash algorithm)

  • Functions to manipulate and verify transactions.

  • Function to store block and transaction data

  • Function to store wallet transaction cache based on block transaction.

 

SIGNATURE (distributed as source)

  • Functions to generate key pairs

  • Functions to extract public key from private key

  • Function to sign data

  • Function to verify data signature

 

RPC WALLET(distributed as source)

  • Function to list json formatted data about the blockchain, compatible with bitcore RPC api, without the transaction signing related methods, which are implemented in a way to allow browser signing in javascript. (called from javascript wallet page).

 

BLOCK EXPLORER(distributed as source)

  • Block explorer web api functions to output json formatted data (called from javascript in the block explorer page).

 

NODE (distributed as system agnostic binary module)

  • Reception of network packet and data transmission to protocol module.

  • Emission of queued messages to other nodes on the network.

  • Loading of RPC server and block explorer module.

  • Handling of HTTP json/ajax/rpc request.

  • Handling of block index and current proof of work difficulty

 

Staking kernel (distributed as source)

  • Validation of proof of stake block and staking reward.

  • Storing of pos specific data on the local system.

  • Computing proof of stake difficulty re-targeting.

  • Generation of new proof of stake block template for staking.

 

COIN (distributed as source)

  • Loading of configuration file.

  • Initialization of the proof of stake kernel module.

  • Initialization of the node module.

  • Global coin logic and network message handling.

 

 

 

 



 

Coin core binary module

Node functions definition

 

 

 

typedef int C_API_FUNC node_init_self_func(mem_zone_ref_ptr out_self_node, mem_zone_ref_ptr node_config);

typedef int C_API_FUNC node_set_last_block_func(mem_zone_ref_ptr header);

typedef int C_API_FUNC node_load_last_blks_func();

typedef int C_API_FUNC node_find_last_pow_block_func(mem_zone_ref_ptr pindex, unsigned int *block_time);

typedef int C_API_FUNC node_is_next_block_func(mem_zone_ref_const_ptr header, mem_zone_ref_ptr lastBlk);

typedef int C_API_FUNC new_peer_node_func(struct host_def *host, mem_zone_ref_ptr peer_nodes);

typedef int C_API_FUNC node_add_block_func(mem_zone_ref_ptr header, mem_zone_ref_ptr txs, uint64_t staking_reward);

typedef int C_API_FUNC read_node_msg_func(mem_zone_ref_ptr node);

typedef int C_API_FUNC send_node_messages_func(mem_zone_ref_ptr node);

typedef int C_API_FUNC node_add_block_header_func(mem_zone_ref_ptr node, mem_zone_ref_ptr hdr);

typedef int C_API_FUNC queue_version_message_func(mem_zone_ref_ptr node, struct string *user_agent);

typedef int C_API_FUNC queue_verack_message_func(mem_zone_ref_ptr node);

typedef int C_API_FUNC queue_ping_message_func(mem_zone_ref_ptr node, uint64_t nonce);

typedef int C_API_FUNC queue_pong_message_func(mem_zone_ref_ptr node, uint64_t nonce);

typedef int C_API_FUNC queue_getaddr_message_func(mem_zone_ref_ptr node);

typedef int C_API_FUNC queue_getdata_message_func(mem_zone_ref_ptr node, mem_zone_ref_ptr hash_list);

typedef int C_API_FUNC queue_block_message_func(mem_zone_ref_ptr node, mem_zone_ref_ptr header, mem_zone_ref_ptr tx_list, struct string *signature);

typedef int C_API_FUNC queue_getblocks_message_func(mem_zone_ref_ptr node);

typedef int C_API_FUNC queue_getblock_hdrs_message_func(mem_zone_ref_ptr node);

typedef int C_API_FUNC queue_send_message_func(mem_zone_ref_ptr node, mem_zone_ref_ptr msg);

typedef int C_API_FUNC queue_emitted_element_func(mem_zone_ref_ptr node, mem_zone_ref_ptr element);

typedef int C_API_FUNC queue_emitted_message_func(mem_zone_ref_ptr node, mem_zone_ref_ptr msg);

typedef int C_API_FUNC node_init_rpc_func(mem_zone_ref_ptr in_config,tpo_mod_file *pos);

typedef int C_API_FUNC check_rpc_request_func();

typedef int C_API_FUNC node_init_block_explorer_func(mem_zone_ref_ptr in_config, tpo_mod_file *pos_mod);

typedef int C_API_FUNC node_add_block_index_func(hash_t hash, unsigned int time);

typedef int C_API_FUNC queue_inv_message_func(mem_zone_ref_ptr node, mem_zone_ref_ptr hash_list);

 

 

 

Staking Kernel function definition

 

typedef int C_API_FUNC init_pos_func(mem_zone_ref_ptr stake_conf);

typedef int C_API_FUNC store_blk_staking_func(mem_zone_ref_ptr header,mem_zone_ref_ptr tx_list);

typedef int C_API_FUNC store_tx_staking_func(mem_zone_ref_ptr tx, hash_t tx_hash, btc_addr_t stake_addr, uint64_t stake_in);

typedef int C_API_FUNC compute_blk_staking_func(mem_zone_ref_ptr prev, mem_zone_ref_ptr prevPOS, mem_zone_ref_ptr hdr, mem_zone_ref_ptr tx_list, uint64_t *staking_reward);

typedef int C_API_FUNC compute_last_pos_diff_func(mem_zone_ref_ptr lastPOS, unsigned int *nBits);

typedef int C_API_FUNC load_last_pos_blk_func(mem_zone_ref_ptr header);

typedef int C_API_FUNC store_last_pos_hash_func(hash_t hash);

typedef int C_API_FUNC find_last_pos_block_func(mem_zone_ref_ptr pindex, unsigned int *block_time);

typedef unsigned int C_API_FUNC get_current_pos_difficulty_func();

 

 

 

 

 

 

Base initialization

 

OS_API_C_FUNC(int) app_init(mem_zone_ref_ptr params)

{

mem_zone_ref log = { PTR_NULL };

unsigned char *data;

size_t data_len;

 

tree_manager_init(8*1024*1024);

 

node_port_str.str = PTR_NULL;

node_port_str.len = 0;

node_port_str.size = 0;

 

node_hostname.str = PTR_NULL;

node_hostname.len = 0;

node_hostname.size = 0;

 

node_config.zone = PTR_NULL;

init_string(&user_agent);

peer_nodes.zone = PTR_NULL;

memset_c(null_hash, 0, 32);

 

 

if (get_file("iadix.conf", &data, &data_len)<=0)

{

log_message("unable to file iadix.conf\n", PTR_NULL);

return 0;

}

 

if (!tree_manager_json_loadb(data, data_len, &node_config))

{

free_c(data);

log_message("unable to parse node config\n", PTR_NULL);

return 0;

}

free_c(data);

 

 

tree_manager_get_child_value_istr(&node_config, NODE_HASH("seed_node_host"), &node_hostname, 0);

tree_manager_get_child_value_i32(&node_config, NODE_HASH("seed_node_port"), &seed_port);

tree_manager_get_child_value_istr(&node_config, NODE_HASH("name"), &user_agent, 0);

 

self_node.zone = PTR_NULL;

 

create_dir("adrs");

create_dir("txs");

create_dir("blks");

 

load_node_module(&node_config);

if (!node_init_self(&self_node, &node_config))

{

console_print("unable to init self node \n");

return 0;

}

 

tree_manager_create_node("log", NODE_LOG_PARAMS, &log);

tree_manager_set_child_value_i32(&log, "port", node_port);

tree_manager_set_child_value_str(&log, "hostname", node_hostname.str);

log_message("node port %port% open @ %hostname% ", &log);

release_zone_ref(&log);

 

return 1;

}

Application start

 

 

OS_API_C_FUNC(int) app_start(mem_zone_ref_ptr params)

{

mem_zone_ref genesis = { PTR_NULL };

mem_zone_ref log = { PTR_NULL };

mem_zone_ref seed_node = { PTR_NULL }, rpc_wallet_conf = { PTR_NULL }

mem_zone_ref block_explorer_conf = { PTR_NULL }, genesis_conf = { PTR_NULL }, stake_conf = { PTR_NULL };

struct host_def *seed_host;

int nc;

 

if (!tree_manager_find_child_node(&node_config, NODE_HASH("genesis"), 0xFFFFFFFF, &genesis_conf))

{

log_message("no genesis block in node config\n", PTR_NULL);

return 0;

}

 

make_genesis_block(&genesis_conf, &genesis);

if (tree_manager_find_child_node(&node_config, NODE_HASH("staking"), 0xFFFFFFFF, &stake_conf))

{

char staking_kernel[33];

tree_manager_get_child_value_str(&stake_conf, NODE_HASH("staking_kernel"), staking_kernel, 33, 0);

if (load_pos_module(staking_kernel, &pos_kernel))

{

init_pos(&stake_conf);

store_blk_staking(&genesis, PTR_NULL);

}

release_zone_ref(&stake_conf);

}

else

memset_c(&pos_kernel, 0, sizeof(tpo_mod_file));

 

nc = get_last_block_height();

if (nc < 1)

{

hash_t h;

unsigned int t;

tree_manager_get_child_value_hash (&genesis, NODE_HASH("blk hash"), h);

tree_manager_get_child_value_i32 (&genesis, NODE_HASH("time"), &t);

node_set_last_block (&genesis);

node_add_block_index (h,t);

}

release_zone_ref(&genesis_conf);

release_zone_ref(&genesis);

 

seed_host = make_host_def(node_hostname.str, seed_port);

tree_manager_create_node("peer nodes", NODE_BITCORE_NODE_LIST, &peer_nodes);

if (!new_peer_node(seed_host, &peer_nodes))

{

free_string(&node_port_str);

free_string(&node_hostname);

free_host_def(seed_host);

return 0;

}

free_host_def(seed_host);

 

reset_addr_scan();

 

 if (tree_manager_find_child_node(&node_config, NODE_HASH("rpc_wallet"), 0xFFFFFFFF, &rpc_wallet_conf))

{

node_init_rpc (&rpc_wallet_conf,&pos_kernel);

release_zone_ref (&rpc_wallet_conf);

}

 

if (tree_manager_find_child_node(&node_config, NODE_HASH("block_explorer"), 0xFFFFFFFF, &block_explorer_conf))

{

node_init_block_explorer (&block_explorer_conf, &pos_kernel);

release_zone_ref (&block_explorer_conf);

}

 

 

if (nc > 1)

{

mem_zone_ref last_blk = { PTR_NULL };

mem_zone_ref lastPOSBlk = { PTR_NULL }, lastPOWBlk = { PTR_NULL };

unsigned int nBits;

node_load_last_blks();

 

 

tree_manager_find_child_node(&self_node, NODE_HASH("last block"), NODE_BITCORE_BLK_HDR, &last_blk);

 

//compute current block difficulty

if (tree_manager_find_child_node(&self_node, NODE_HASH("last pow block"), NODE_BITCORE_BLK_HDR, &lastPOWBlk))

{

if (compute_last_pow_diff(&lastPOWBlk, &nBits))

tree_manager_set_child_value_i32(&self_node, "current pow diff", nBits);

else

{

tree_manager_get_child_value_i32(&last_blk, NODE_HASH("bits"), &nBits);

tree_manager_set_child_value_i32(&self_node, "current pow diff", nBits);

}

release_zone_ref(&lastPOWBlk);

}

 

if (strlen_c(pos_kernel.name) > 0)

{

unsigned int time, nBits;

 

if (tree_manager_create_node("last pos block", NODE_BITCORE_BLK_HDR, &lastPOSBlk))

{

if (load_last_pos_blk(&lastPOSBlk))

tree_manager_node_add_child(&self_node, &lastPOSBlk);

else if (last_blk.zone != PTR_NULL)

{

copy_zone_ref(&lastPOSBlk, &last_blk);

if (find_last_pos_block(&lastPOSBlk, &time))

{

hash_t h;

tree_manager_get_child_value_hash(&lastPOSBlk, NODE_HASH("blk hash"), h);

store_last_pos_hash(h);

tree_manager_node_add_child(&self_node, &lastPOSBlk);

}

else

copy_zone_ref(&lastPOSBlk, &last_blk);

}

 

if (compute_last_pos_diff(&lastPOSBlk, &nBits))

tree_manager_set_child_value_i32(&self_node, "current pos diff", nBits);

else

{

tree_manager_get_child_value_i32(&self_node, NODE_HASH("limit"), &nBits);

tree_manager_set_child_value_i32(&self_node, "current pos diff", nBits);

}

 

 

log_message("loaded last block pos %blk hash%", &lastPOSBlk);

release_zone_ref(&lastPOSBlk);

}

}

release_zone_ref(&last_blk);

}

 

tree_manager_get_child_at(&peer_nodes, 0, &seed_node);

queue_version_message(&seed_node, &user_agent);

release_zone_ref(&seed_node);

synching = 0;

return 1;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Application main loop

 

OS_API_C_FUNC(int) app_loop(mem_zone_ref_ptr params)

{

mem_zone_ref blk_list = { PTR_NULL };

mem_zone_ref my_list = { PTR_NULL };

mem_zone_ref hash_list = { PTR_NULL };

mem_zone_ref_ptr blk = PTR_NULL;

unsigned int new_block = 0;

 

update_nodes();

process_nodes();

 

tree_manager_create_node("hashes", NODE_BITCORE_HASH_LIST, &hash_list);

if (tree_manager_find_child_node(&self_node, NODE_HASH("submitted blocks"), NODE_BITCORE_BLK_HDR_LIST, &blk_list))

{

for (tree_manager_get_first_child(&blk_list, &my_list, &blk); ((blk != NULL) && (blk->zone != NULL)); tree_manager_get_next_child(&my_list, &blk))

{

hash_t blk_hash = { 0 };

struct string signature = { PTR_NULL };

mem_zone_ref tx_list = { PTR_NULL };

unsigned int is_signed;

int ret;

 

if (!tree_manager_find_child_node(blk, NODE_HASH("txs"), NODE_BITCORE_TX_LIST, &tx_list))continue;

if (!tree_manager_get_child_value_istr(blk, NODE_HASH("signature"), &signature, 0))continue;

 

ret=accept_block (blk, &tx_list,&signature);

if (ret)

{

mem_zone_ref new_hash = { PTR_NULL };

 

tree_manager_get_child_value_hash(blk, NODE_HASH("blk hash"), blk_hash);

if (tree_manager_add_child_node(&hash_list, "hash", NODE_BITCORE_BLOCK_HASH, &new_hash))

{

tree_manager_write_node_hash(&new_hash, 0, blk_hash);

release_zone_ref(&new_hash);

}

new_block = 1;

}

release_zone_ref (&tx_list);

free_string (&signature);

tree_manager_set_child_value_bool (blk, "done", 1);

}

tree_remove_child_by_member_value_dword(&blk_list, NODE_BITCORE_BLK_HDR, "done", 1);

release_zone_ref(&blk_list);

}

if (new_block)

{

mem_zone_ref_ptr node = PTR_NULL;

for (tree_manager_get_first_child(&peer_nodes, &my_list, &node); ((node != NULL) && (node->zone != NULL)); tree_manager_get_next_child(&my_list, &node))

{

queue_inv_message(node, &hash_list);

}

}

release_zone_ref(&hash_list);

return 1;

}

Processing of node I/O

 

int update_nodes()

{

mem_zone_ref_ptr node = PTR_NULL;

mem_zone_ref my_list = { PTR_NULL };

 

for (tree_manager_get_first_child(&peer_nodes, &my_list, &node); ((node != PTR_NULL) && (node->zone != PTR_NULL)); tree_manager_get_next_child(&my_list, &node))

{

send_node_messages (node);

read_node_msg (node);

check_rpc_request ();

}

return 1;

}

 

Processing of node parsed messages

 

int handle_message(mem_zone_ref_ptr node,const char *cmd,mem_zone_ref_ptr payload)

{

if (!strncmp_c(cmd, "verack", 6)){ return handle_verack(node,payload); }

if (!strncmp_c(cmd, "version", 7))return handle_version(node, payload);

if (!strncmp_c(cmd, "ping", 4))return handle_ping(node, payload);

if (!strncmp_c(cmd, "pong", 4))return handle_pong(node, payload);

if (!strncmp_c(cmd, "addr", 4))return handle_addr(node, payload);

if (!strncmp_c(cmd, "inv", 3))return handle_inv(node, payload);

if (!strncmp_c(cmd, "block", 5))return handle_block(node, payload);

if (!strncmp_c(cmd, "getdata", 7))return handle_getdata(node, payload);

return 0;

}

int process_node_messages(mem_zone_ref_ptr node)

{

mem_zone_ref msg_list = { PTR_NULL };

mem_zone_ref_ptr msg = PTR_NULL;

mem_zone_ref my_list = { PTR_NULL };

unsigned int nc;

 

if (!tree_manager_find_child_node(node, NODE_HASH("emitted queue"), NODE_BITCORE_MSG_LIST, &msg_list))return 0;

 

for ( tree_manager_get_first_child(&msg_list, &my_list, &msg);

((msg != NULL) && (msg->zone != NULL));

tree_manager_get_next_child(&my_list, &msg))

{

char cmd[16];

mem_zone_ref payload_node = { PTR_NULL };

int ret;

 

if (!tree_manager_get_child_value_str(msg, NODE_HASH("cmd"), cmd, 12, 16))continue;

tree_manager_find_child_node(msg, NODE_HASH("payload"), NODE_BITCORE_PAYLOAD, &payload_node);

ret = handle_message(node, cmd, &payload_node);

tree_manager_set_child_value_i32(msg, "handled", ret);

release_zone_ref(&payload_node);

}

tree_remove_children(&msg_list);

nc = tree_manager_get_node_num_children(&msg_list);

release_zone_ref(&msg_list);

return 1;

}

 

 

 

int process_nodes()

{

mem_zone_ref_ptr node = PTR_NULL;

mem_zone_ref my_list = { PTR_NULL };

 

for (

tree_manager_get_first_child(&peer_nodes, &my_list, &node);

(node != NULL) && (node->zone != NULL);

tree_manager_get_next_child(&my_list, &node))

{

ctime_t next_check;

ctime_t curtime;

process_node_messages(node);

if (synching == 1)

{

curtime = get_time_c();

if (tree_manager_get_child_value_i64(node, NODE_HASH("next_check"), &next_check))

{

if (curtime >= next_check)

{

queue_getblocks_message(node);

tree_manager_set_child_value_i32(node, "next_check", curtime + 5);

}

}

}

}

return 1;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Sample processing of some messages

 

 

int handle_version(mem_zone_ref_ptr node, mem_zone_ref_ptr payload)

{

char user_agent[32];

mem_zone_ref log = { PTR_NULL }, block_index_node = { PTR_NULL };

unsigned int proto_ver, last_blk, node_port,my_port;

mem_zone_ref addrs[2] = { PTR_NULL };

uint64_t time, services, timestamp;

int index = 0;

ipv4_t node_ip,my_ip;

uint64_t nblks;

 

tree_manager_get_child_value_i32 (payload, NODE_HASH("proto_ver"), &proto_ver);

tree_manager_get_child_value_i64 (payload, NODE_HASH("timestamp"), &time);

tree_manager_get_child_value_i64 (payload, NODE_HASH("services"), &services);

tree_manager_get_child_value_i64 (payload, NODE_HASH("timestamp"), ×tamp);

tree_manager_get_child_value_str (payload, NODE_HASH("user_agent"),user_agent, 32, 16);

tree_manager_get_child_value_i32 (payload, NODE_HASH("last_blk"), &last_blk);

 

index = 1;

tree_node_list_child_by_type (payload, NODE_BITCORE_ADDR, &addrs[0], 0);

tree_node_list_child_by_type (payload, NODE_BITCORE_ADDR, &addrs[1], 1);

 

tree_manager_get_child_value_ipv4 (&addrs[0], NODE_HASH("addr"), my_ip);

tree_manager_get_child_value_i32 (&addrs[0], NODE_HASH("port"), &my_port);

 

tree_manager_get_child_value_ipv4 (&addrs[1], NODE_HASH("addr"), node_ip);

tree_manager_get_child_value_i32 (&addrs[1], NODE_HASH("port"), &node_port);

 

 

tree_manager_create_node("log", NODE_LOG_PARAMS, &log);

tree_manager_set_child_value_ipv4(&log, "nip", node_ip);

tree_manager_set_child_value_i32(&log, "nport", node_port);

tree_manager_set_child_value_ipv4(&log, "ip", my_ip);

tree_manager_set_child_value_i32(&log, "port", my_port);

tree_manager_set_child_value_str(&log, "services", services ? "network" : "no services");

tree_manager_set_child_value_i32(&log, "version", proto_ver);

tree_manager_set_child_value_str(&log, "user_agent", user_agent);

tree_manager_set_child_value_i32(&log, "lastblk", last_blk);

log_message("node %nip%:%nport% version %version% %services% last block: %lastblk%, me %ip%:%port% \n", &log);

release_zone_ref(&log);

 

 

release_zone_ref(&addrs[0]);

release_zone_ref(&addrs[1]);

 

 

 

 

 

 

queue_verack_message (node);

  queue_getaddr_message (node);

 

 if (!tree_manager_get_child_value_i64(&self_node, NODE_HASH("block height"), &nblks))

nblks = 0;

 

if (nblks > (last_blk + 1))

{

mem_zone_ref hash_list = { PTR_NULL };

if (tree_manager_create_node("hashes", NODE_BITCORE_HASH_LIST, &hash_list))

{

int num = 1000;

while (last_blk < nblks)

{

if ((num--) == 0)break;

if (tree_manager_find_child_node(&self_node, NODE_HASH("block index"), NODE_BITCORE_HASH, &block_index_node))

{

hash_t hash;

if (tree_manager_get_node_hash(&block_index_node, last_blk*sizeof(hash_t), hash))

{

mem_zone_ref new_hash = { PTR_NULL };

if (tree_manager_add_child_node(&hash_list, "hash", NODE_BITCORE_BLOCK_HASH, &new_hash))

{

tree_manager_write_node_hash(&new_hash, 0, hash);

release_zone_ref(&new_hash);

}

}

release_zone_ref(&block_index_node);

}

last_blk++;

}

queue_inv_message(node, &hash_list);

release_zone_ref(&hash_list);

}

}

return 1;

}

 

int handle_ping(mem_zone_ref_ptr node, mem_zone_ref_ptr payload)

{

uint64_t nonce;

tree_manager_get_child_value_i64(payload, NODE_HASH("nonce"), &nonce);

queue_pong_message (node, nonce);

return 1;

}

 

 

 

int handle_pong(mem_zone_ref_ptr node, mem_zone_ref_ptr payload)

{

synching = 1;

return 1;

}

 

 

 

int handle_verack(mem_zone_ref_ptr node, mem_zone_ref_ptr payload)

{

queue_ping_message(node,ping_nonce++);

return 1;

}

 

 

 

 

 

int handle_addr(mem_zone_ref_ptr node, mem_zone_ref_ptr payload)

{

mem_zone_ref log = { PTR_NULL };

mem_zone_ref addr_list = { PTR_NULL };

mem_zone_ref my_list = { PTR_NULL };

mem_zone_ref_ptr addr;

 

tree_manager_find_child_node(payload, NODE_HASH("addrs"), NODE_BITCORE_ADDR_LIST, &addr_list);

for (tree_manager_get_first_child(&addr_list, &my_list, &addr); ((addr != NULL) && (addr->zone != NULL)); tree_manager_get_next_child(&my_list, &addr))

{

unsigned int time;

uint64_t services;

ipv4_t ip;

unsigned short port;

 

tree_manager_get_child_value_i32 (addr, NODE_HASH("time") , &time);

tree_manager_get_child_value_i64 (addr, NODE_HASH("services"), &services);

 

tree_manager_get_child_value_ipv4 (addr, NODE_HASH("addr") , ip);

tree_manager_get_child_value_i16 (addr, NODE_HASH("port") , &port);

 

tree_manager_create_node("log", NODE_LOG_PARAMS, &log);

tree_manager_set_child_value_ipv4(&log, "ip", ip);

tree_manager_set_child_value_i32(&log, "port", port);

tree_manager_set_child_value_str(&log, "services", services ? "network" : "no services");

tree_manager_set_child_value_i32(&log, "time", time);

log_message("new address %ip%:%port% %time% %services%\n", &log);

release_zone_ref(&log);

}

release_zone_ref(&addr_list);

return 1;

}

 

 

 

 

 

int handle_inv(mem_zone_ref_ptr node, mem_zone_ref_ptr payload)

{

mem_zone_ref hash_list = { PTR_NULL };

tree_manager_find_child_node(payload, NODE_HASH("hashes"), NODE_BITCORE_HASH_LIST, &hash_list);

queue_getdata_message(node, &hash_list);

release_zone_ref(&hash_list);

return 1;

}

 

 

 

 

 

 

 

 

 

 

 

int accept_block(mem_zone_ref_ptr header, mem_zone_ref_ptr tx_list, struct string *signature)

{

hash_t blk_hash;

mem_zone_ref log = { PTR_NULL };

struct string sign = { PTR_NULL };

uint64_t block_reward = 0, staking_reward = 0, nblks;

int ret = 1, is_staking;

mem_zone_ref lastPOSBlk = { PTR_NULL }, lastPOWBlk = { PTR_NULL }, lastBlk = { PTR_NULL };

 

if (!node_is_next_block(header, &lastBlk))

return 0;

 

tree_manager_get_child_value_i64(&self_node, NODE_HASH("block height"), &nblks);

compute_block_hash(header, blk_hash);

tree_manager_set_child_value_bhash(header, "blk hash", blk_hash);

 

if (strlen_c(pos_kernel.name) > 0)

{

mem_zone_ref sig = { PTR_NULL };

tree_manager_find_child_node (&self_node, NODE_HASH("last pos block"), NODE_BITCORE_BLK_HDR, &lastPOSBlk);

 

if (!tree_manager_find_child_node(header, NODE_HASH("signature"), NODE_BITCORE_ECDSA_SIG, &sig))

tree_manager_add_child_node (header, "signature", NODE_BITCORE_ECDSA_SIG, &sig);

 

tree_manager_write_node_sig (&sig, 0, signature->str, signature->len);

release_zone_ref (&sig);

 

ret = compute_blk_staking (&lastBlk, &lastPOSBlk, header, tx_list, &block_reward);

release_zone_ref (&lastPOSBlk);

}

tree_manager_find_child_node(&self_node, NODE_HASH("last pos block"), NODE_BITCORE_BLK_HDR, &lastPOSBlk);

 

if (find_hash(blk_hash))

remove_block(blk_hash);

 

if (ret)

{

hash_t out_diff;

unsigned int powbits;

if (block_reward == 0)

{

if (!tree_manager_get_child_value_i32(&self_node, NODE_HASH("current pow diff"), &powbits))

tree_manager_get_child_value_i32(header, NODE_HASH("bits"), &powbits);

 

SetCompact(powbits, out_diff);

ret = check_block_pow(header, out_diff);

if (ret)

block_reward = get_blockreward(nblks);

 

is_staking = 0;

}

else

{

is_staking = 1;

}

}

 

 

if (ret)

ret = node_add_block(header, tx_list, block_reward);

 

if (ret)

{

unsigned int blocktime = 0;

 

if (strlen_c(pos_kernel.name) > 0)

store_blk_staking(header, tx_list);

 

tree_manager_get_child_value_i32(header, NODE_HASH("time"), &blocktime);

 

if (is_staking)

{

mem_zone_ref last_blk = { PTR_NULL };

unsigned int pBits;

 

store_last_pos_hash(blk_hash);

 

if (!tree_manager_find_child_node(&self_node, NODE_HASH("last pos block"), NODE_BITCORE_BLK_HDR, &last_blk))

tree_manager_add_child_node(&self_node, "last pos block", NODE_BITCORE_BLK_HDR, &last_blk);

 

tree_manager_copy_children_ref(&last_blk, header);

release_zone_ref(&last_blk);

 

if (compute_last_pos_diff(header, &pBits))

tree_manager_set_child_value_i32(&self_node, "current pos diff", pBits);

else

tree_manager_set_child_value_i32(&self_node, "current pos diff", 0x1FFFFFFF);

}

else

{

unsigned int powbits;

 

if (compute_last_pow_diff(header, &powbits))

tree_manager_set_child_value_i32(&self_node, "current pow diff", powbits);

else

{

tree_manager_get_child_value_i32(header, NODE_HASH("bits"), &powbits);

tree_manager_set_child_value_i32(&self_node, "current pow diff", powbits);

}

 

}

node_add_block_index(blk_hash, blocktime);

add_moneysupply(block_reward);

}

release_zone_ref(&lastBlk);

return ret;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

int handle_getdata(mem_zone_ref_ptr node, mem_zone_ref_ptr payload)

{

mem_zone_ref hash_list = { PTR_NULL }, my_list = { PTR_NULL };

mem_zone_ref_ptr hash_node;

unsigned int data_type = 0;

if (!tree_manager_find_child_node(payload, NODE_HASH("hashes"), NODE_BITCORE_HASH_LIST, &hash_list))return 0;

 

for (

tree_manager_get_first_child(&hash_list, &my_list, &hash_node);

((hash_node != NULL) && (hash_node->zone != NULL));

tree_manager_get_next_child(&my_list, &hash_node))

{

char chash[65];

hash_t hash;

mem_zone_ref block = { PTR_NULL }, txs = { PTR_NULL };

unsigned char *hash_data;

hash_data = tree_mamanger_get_node_data_ptr(hash_node, 0);

if (tree_mamanger_get_node_type(hash_node) == NODE_BITCORE_BLOCK_HASH)

{

int n = 32;

while (n--)hash[n] = hash_data[31 - n];

n = 0;

while (n<32)

{

chash[n * 2 + 0] = hex_chars[hash_data[n] >> 4];

chash[n * 2 + 1] = hex_chars[hash_data[n] & 0x0F];

n++;

}

chash[64] = 0;

}

 

if (load_blk_hdr(&block, chash))

{

if (tree_manager_create_node("txs", NODE_BITCORE_TX_LIST, &txs))

{

struct string sign = { 0 };

get_blk_sign(chash, &sign);

 

if (load_blk_txs(chash, &txs))

queue_block_message (node, &block, &txs,&sign);

 

free_string(&sign);

release_zone_ref(&txs);

}

release_zone_ref(&block);

}

}

release_zone_ref(&hash_list);

return 1;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

int handle_block(mem_zone_ref_ptr node, mem_zone_ref_ptr payload)

{

mem_zone_ref header = { PTR_NULL }, tx_list = { PTR_NULL }, sig = { PTR_NULL };

mem_zone_ref log = { PTR_NULL };

size_t nz1 = 0, nz2 = 0;

struct string signature = { PTR_NULL };

int ret = 1;

uint64_t nblks;

 

if (!tree_manager_find_child_node(payload, NODE_HASH("header"), NODE_BITCORE_BLK_HDR, &header))return 0;

if (!tree_manager_find_child_node(payload, NODE_HASH("txs"), NODE_BITCORE_TX_LIST, &tx_list)){ release_zone_ref(&header); return 0; }

if (!tree_manager_find_child_node(payload, NODE_HASH("signature"), NODE_BITCORE_ECDSA_SIG, &sig)){ release_zone_ref(&tx_list); release_zone_ref(&header); return 0; }

 

tree_manager_get_node_istr (&sig, 0, &signature,0);

release_zone_ref (&sig);

 

ret = accept_block (&header, &tx_list, &signature);

 

 

if (ret)

log_message("accepted block: %blk hash% , %time% - %version% %merkle_root%\n", &header);

else

log_message("rejected block: %blk hash% , %time% - %version% %merkle_root%\n", &header);

 

tree_manager_set_child_value_i64(node, "next_check", get_time_c() + 10);

 

 

tree_manager_get_child_value_i64(&self_node, NODE_HASH("block height"), &nblks);

tree_manager_create_node("log", NODE_LOG_PARAMS, &log);

tree_manager_set_child_value_i32(&log, "nblocks", nblks);

log_message("block height : %nblocks%\n", &log);

release_zone_ref(&log);

 

free_string(&signature);

release_zone_ref(&header);

release_zone_ref(&tx_list);

 

return ret;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Sample processing of rpc request

 

 

OS_API_C_FUNC(int) liststaking(mem_zone_ref_const_ptr params, unsigned int rpc_mode, mem_zone_ref_ptr result)

{

mem_zone_ref_ptr addr;

mem_zone_ref minconf = { PTR_NULL }, maxconf = { PTR_NULL }, unspents = { PTR_NULL }, addrs = { PTR_NULL };

mem_zone_ref my_list = { PTR_NULL };

mem_zone_ref last_blk = { PTR_NULL };

struct string pos_hash_data = { PTR_NULL };

int max = 2000;

int ret = 0;

unsigned int block_time;

unsigned int target,iminconf=0;

if (!tree_manager_find_child_node(&my_node, NODE_HASH("last block"), NODE_BITCORE_BLK_HDR, &last_blk))return 0;

 

if (!tree_manager_add_child_node(result, "unspents", NODE_JSON_ARRAY, &unspents))

return 0;

 

if (tree_manager_get_child_at(params, 0, &minconf))

{

tree_mamanger_get_node_dword(&minconf, 0, &iminconf);

release_zone_ref (&minconf);

}

 

if (iminconf < min_staking_depth)

iminconf = min_staking_depth;

 

tree_manager_get_child_at (params, 1, &maxconf);

tree_manager_get_child_at (params, 2, &addrs);

 

get_target_spacing (&target);

tree_manager_get_child_value_i32(&last_blk, NODE_HASH("time"), &block_time);

 

tree_manager_set_child_value_i32(result, "block_target", target);

tree_manager_set_child_value_i32(result, "now", get_time_c());

tree_manager_set_child_value_i32(result, "last_block_time", block_time);

 

for (tree_manager_get_first_child(&addrs, &my_list, &addr); ((addr != NULL) && (addr->zone != NULL)); tree_manager_get_next_child(&my_list, &addr))

{

if (max > 0)

{

btc_addr_t my_addr;

tree_manager_get_node_btcaddr(addr, 0, my_addr);

list_staking_unspent(&last_blk, my_addr, &unspents, iminconf, &max);

}

}

release_zone_ref(&last_blk);

release_zone_ref(&unspents);

release_zone_ref(&addrs);

release_zone_ref(&maxconf);

 

 

return 1;

 

}

 

 

 

 

OS_API_C_FUNC(int) signstakeblock(mem_zone_ref_const_ptr params, unsigned int rpc_mode, mem_zone_ref_ptr result)

{

hash_t rblkHash, blkHash;

unsigned char chash[65];

struct string signature = { 0 }, vpubk = { 0 }, pubk = { 0 }, sign = { 0 };

mem_zone_ref pn = { PTR_NULL }, blk = { PTR_NULL }, node_blks = { PTR_NULL };

unsigned int n;

int ret=0;

tree_manager_get_child_at(params, 0, &pn);

tree_manager_get_node_str(&pn, 0, chash, 65, 0);

release_zone_ref(&pn);

 

tree_manager_get_child_at(params, 1, &pn);

tree_manager_get_node_istr(&pn, 0, &signature, 0);

release_zone_ref(&pn);

 

tree_manager_get_child_at(params, 2, &pn);

tree_manager_get_node_istr(&pn, 0, &vpubk, 0);

release_zone_ref(&pn);

 

n = 0;

while (n < 32)

{

char hex[3];

hex[0] = chash[n * 2 + 0];

hex[1] = chash[n * 2 + 1];

hex[2] = 0;

blkHash[n] = strtoul_c(hex, PTR_NULL, 16);

rblkHash[31 - n] = blkHash[n];

n++;

}

 

sign.len = signature.len / 2;

sign.size = sign.len + 1;

sign.str = malloc_c(sign.size);

n = 0;

while (n < sign.len)

{

char hex[3];

hex[0] = signature.str[n * 2 + 0];

hex[1] = signature.str[n * 2 + 1];

hex[2] = 0;

sign.str[n] = strtoul_c(hex, PTR_NULL, 16);

n++;

}

sign.str[sign.len] = 0;

free_string(&signature);

 

 

if (vpubk.len == 66)

{

pubk.len = 33;

pubk.size = pubk.len + 1;

pubk.str = malloc_c(pubk.size);

n = 0;

while (n < pubk.len)

{

char hex[3];

hex[0] = vpubk.str[n * 2 + 0];

hex[1] = vpubk.str[n * 2 + 1];

hex[2] = 0;

pubk.str[n] = strtoul_c(hex, PTR_NULL, 16);

n++;

}

pubk.str[pubk.len] = 0;

}

free_string(&vpubk);

 

if (tree_manager_find_child_node(&my_node, NODE_HASH("submitted blocks"), NODE_BITCORE_BLK_HDR_LIST, &node_blks))

{

if (tree_find_child_node_by_member_name_hash(&node_blks, NODE_BITCORE_BLK_HDR, "blk hash", blkHash, &blk))

{

mem_zone_ref txs = { PTR_NULL };

mem_zone_ref sig = { PTR_NULL };

 

if (pubk.len==0)

ret = 1;

else

{

unsigned char type;

struct string bsig = { 0 };

 

ret = parse_sig_seq(&sign, &bsig, &type, 1);

if (ret)

ret = blk_check_sign(&bsig, &pubk, blkHash);

}

if (ret)

{

tree_manager_add_child_node(&blk, "signature", NODE_BITCORE_ECDSA_SIG, &sig);

tree_manager_write_node_sig(&sig, 0, sign.str, sign.len);

release_zone_ref(&sig);

}

release_zone_ref (&blk);

}

release_zone_ref(&node_blks);

}

 

free_string(&sign);

free_string(&pubk);

 

 

return ret;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

OS_API_C_FUNC(int) signstaketx(mem_zone_ref_const_ptr params, unsigned int rpc_mode, mem_zone_ref_ptr result)

{

hash_t txHash;

unsigned char chash[65];

btc_addr_t pubAddr;

int ret = 0;

unsigned int n;

unsigned char hash_type = 1;

struct string bsign = { PTR_NULL }, sign = { PTR_NULL };

mem_zone_ref pn = { PTR_NULL }, node_txs = { PTR_NULL }, tx = { PTR_NULL };

 

tree_manager_get_child_at (params, 0, &pn);

tree_manager_get_node_str (&pn, 0, chash, 65, 0);

release_zone_ref (&pn);

 

n = 0;

while (n < 32)

{

char hex[3];

hex[0] = chash[n * 2 + 0];

hex[1] = chash[n * 2 + 1];

hex[2] = 0;

txHash[n] = strtoul_c(hex, PTR_NULL, 16);

n++;

}

 

tree_manager_get_child_at (params, 1, &pn);

tree_manager_get_node_istr (&pn, 0, &sign, 0);

release_zone_ref (&pn);

bsign.len = (sign.len / 2)+1;

bsign.size = bsign.len + 1;

bsign.str = malloc_c(bsign.size);

 

n = 0;

while (n < bsign.len)

{

char hex[3];

hex[0] = sign.str[n * 2 + 0];

hex[1] = sign.str[n * 2 + 1];

hex[2] = 0;

bsign.str[n] = strtoul_c(hex, PTR_NULL, 16);

n++;

}

free_string(&sign);

 

bsign.str[bsign.len-1] = hash_type;

 

 tree_manager_get_child_at (params, 2, &pn);

tree_manager_get_node_btcaddr (&pn, 0, pubAddr);

release_zone_ref (&pn);

 

 if (tree_manager_find_child_node(&my_node, NODE_HASH("tx mem pool"), NODE_BITCORE_TX_LIST, &node_txs))

{

if (tree_find_child_node_by_member_name_hash(&node_txs, NODE_BITCORE_TX, "tx hash", txHash, &tx))

{

mem_zone_ref last_blk = { PTR_NULL }, newBlock = { PTR_NULL };

ret = tx_sign(&tx, 0, hash_type, &bsign);

if (ret)

{

if (tree_manager_find_child_node(&my_node, NODE_HASH("last block"), NODE_BITCORE_BLK_HDR, &last_blk))

{

hash_t block_hash;

tree_manager_get_child_value_hash(&last_blk, NODE_HASH("blk hash"), block_hash);

if (create_pos_block(block_hash, &tx, &newBlock))

{

mem_zone_ref txs = { PTR_NULL }, blk_list = { PTR_NULL };

 

if (tree_manager_find_child_node(&my_node, NODE_HASH("submitted blocks"), NODE_BITCORE_BLK_HDR_LIST, &blk_list))

{

hash_t h,rblkh;

 

tree_manager_get_child_value_hash(&newBlock, NODE_HASH("blk hash"), h);

n = 32;

while (n--)rblkh[n] = h[31 - n];

 

tree_manager_set_child_value_hash (result , "newblockhash", rblkh);

tree_manager_node_add_child (&blk_list , &newBlock);

release_zone_ref (&blk_list);

}

release_zone_ref(&newBlock);

}

release_zone_ref(&last_blk);

}

}

release_zone_ref(&tx);

}

release_zone_ref(&node_txs);

}

free_string(&bsign);

return ret;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

OS_API_C_FUNC(int) getstaketx(mem_zone_ref_const_ptr params, unsigned int rpc_mode, mem_zone_ref_ptr result)

{

unsigned char chash[65];

hash_t txHash, blkhash;

btc_addr_t pubaddr;

char toto = 0;

mem_zone_ref vout = { PTR_NULL }, prevtx = { PTR_NULL }, newtx = { PTR_NULL }, pn = { PTR_NULL };

struct string sPubk = { PTR_NULL }, script = { PTR_NULL }, null_str = { PTR_NULL };

uint64_t amount;

unsigned int OutIdx, newTxTime,n;

int ret;

 

null_str.str = &toto;

null_str.len = 0;

null_str.size = 1;

 

tree_manager_get_child_at (params, 0, &pn);

tree_manager_get_node_str (&pn, 0, chash, 65, 0);

release_zone_ref (&pn);

 

n = 0;

while (n < 32)

{

char hex[3];

hex[0] = chash[n * 2 + 0];

hex[1] = chash[n * 2 + 1];

hex[2] = 0;

txHash[31 - n] = strtoul_c(hex, PTR_NULL, 16);

n++;

}

 

tree_manager_get_child_at (params, 1, &pn);

tree_mamanger_get_node_dword (&pn, 0, &OutIdx);

release_zone_ref (&pn);

 

tree_manager_get_child_at (params, 2, &pn);

tree_mamanger_get_node_dword (&pn, 0, &newTxTime);

release_zone_ref (&pn);

 

ret = load_tx(&prevtx, blkhash, txHash);

 

if (ret)

ret = get_tx_output(&prevtx, OutIdx, &vout);

if (ret)

ret = tree_manager_get_child_value_istr(&vout, NODE_HASH("script"), &script, 0);

if (ret)

ret = tree_manager_get_child_value_i64(&vout, NODE_HASH("value"), &amount);

 

get_out_script_address(&script, &sPubk, pubaddr);

 

if (ret)

{

uint64_t half_am,rew;

ret = 0;

get_stake_reward (&rew);

half_am = muldiv64 (amount+rew, 1, 2);

if (tree_manager_add_child_node(result, "transaction", NODE_BITCORE_TX, &newtx))

{

hash_t txh;

unsigned int hash_type = 1;

 

if (new_transaction(&newtx, newTxTime))

{

mem_zone_ref last_blk = { PTR_NULL };

hash_t StakeMod, pos_hash, out_diff;

hash_t prevOutHash;

uint64_t weight;

unsigned int prevOutIdx,last_diff;

unsigned int ModTime;

 

tx_add_input (&newtx, txHash, OutIdx, &script);

tx_add_output(&newtx, 0, &null_str);

tx_add_output(&newtx, half_am, &script);

tx_add_output(&newtx, half_am, &script);

tree_manager_find_child_node(&my_node, NODE_HASH("last block"), NODE_BITCORE_BLK_HDR, &last_blk))

get_last_stake_modifier(&last_blk, StakeMod, &ModTime);

compute_tx_pos(&newtx,StakeMod,newTxTime,pos_hash, prevOutHash, &prevOutIdx );

memset_c (out_diff, 0, sizeof(hash_t));

get_tx_output_amount (prevOutHash, prevOutIdx, &weight);

last_diff = get_current_pos_difficulty();

if (last_diff == 0xFFFFFFFF)

{

unsigned int nBits;

tree_manager_get_child_value_i32(&last_blk, NODE_HASH("bits"), &nBits);

mul_compact(nBits, weight, out_diff);

}

else

mul_compact(last_diff, weight, out_diff);

 

//check proof of stake

if (cmp_hashle(pos_hash, out_diff) >= 0)

{

hash_t rtxhash;

mem_zone_ref node_txs = { PTR_NULL };

 

compute_tx_sign_hash (&newtx, 0, &script, hash_type, txh);

 

n = 32;

while (n--)rtxhash[n] = txh[31 - n];

tree_manager_set_child_value_hash (result, "txhash" , rtxhash);

tree_manager_set_child_value_btcaddr(result, "addr" , pubaddr);

if (tree_manager_find_child_node(&my_node, NODE_HASH("tx mem pool"), NODE_BITCORE_TX_LIST, &node_txs))

{

tree_manager_set_child_value_bhash(&newtx, "tx hash", txh);

tree_manager_node_add_child (&node_txs, &newtx);

release_zone_ref (&node_txs);

}

ret = 1;

}

}

release_zone_ref(&newtx);

}

}

release_zone_ref(&vout);

release_zone_ref(&prevtx);

free_string(&script);

return ret;

}

 

 

OS_API_C_FUNC(int) getstaking(mem_zone_ref_const_ptr params, unsigned int rpc_mode, mem_zone_ref_ptr result)

{

mem_zone_ref last_blk = { PTR_NULL };

struct string pos_hash_data = { PTR_NULL };

int ret = 0;

 

if (tree_manager_find_child_node(&my_node, NODE_HASH("last block"), NODE_BITCORE_BLK_HDR, &last_blk))

{

unsigned char chash[65];

hash_t txHash, out_diff;

mem_zone_ref pn = { PTR_NULL };

unsigned int OutIdx, target, block_time,n;

uint64_t amount;

 

tree_manager_get_child_at (params, 0, &pn);

tree_manager_get_node_str (&pn, 0, chash,65, 0);

release_zone_ref (&pn);

 

n = 0;

while (n < 32)

{

char hex[3];

hex[0] = chash[n * 2 + 0];

hex[1] = chash[n * 2 + 1];

hex[2] = 0;

txHash[31-n]= strtoul_c(hex, PTR_NULL, 16);

n++;

}

 

tree_manager_get_child_at(params, 1, &pn);

tree_mamanger_get_node_dword(&pn, 0, &OutIdx);

release_zone_ref(&pn);

 

get_target_spacing (&target);

tree_manager_get_child_value_i32(&last_blk, NODE_HASH("time"), &block_time);

 

memset_c(out_diff, 0, sizeof(hash_t));

 

if (get_tx_pos_hash_data(&last_blk, txHash, OutIdx, &pos_hash_data, &amount, out_diff))

{

hash_t rout_diff;

 

n = 32;

while (n--)rout_diff[n]=out_diff[31 - n];

 

tree_manager_set_child_value_str (result , "hash_data" , pos_hash_data.str);

tree_manager_set_child_value_hash(result , "difficulty" , rout_diff);

tree_manager_set_child_value_i64(result , "weight" , amount);

tree_manager_set_child_value_i32 (result , "block_target" , target);

tree_manager_set_child_value_i32 (result , "now" , get_time_c());

tree_manager_set_child_value_i32 (result , "last_block_time", block_time);

ret = 1;

}

free_string (&pos_hash_data);

release_zone_ref(&last_blk);

}

return ret;

}

 

 

 

OS_API_C_FUNC(int) importkeypair(mem_zone_ref_const_ptr params, unsigned int rpc_mode, mem_zone_ref_ptr result)

{

btc_addr_t pubaddr;

dh_key_t pub, priv;

mem_zone_ref username_n = { PTR_NULL }, pubkey_n = { PTR_NULL }, privkey_n = { PTR_NULL };

struct string username = { PTR_NULL }, xpubkey = { PTR_NULL }, xprivkey = { PTR_NULL };

struct string user_key_file = { PTR_NULL };

size_t keys_data_len = 0;

unsigned char *keys_data = PTR_NULL;

int found;

 

tree_manager_get_child_at(params, 0, &username_n);

tree_manager_get_child_at(params, 1, &pubkey_n);

tree_manager_get_child_at(params, 2, &privkey_n);

tree_manager_get_node_istr(&username_n, 0, &username, 0);

tree_manager_get_node_istr(&pubkey_n, 0, &xpubkey, 0);

tree_manager_get_node_istr(&privkey_n, 0, &xprivkey, 0);

release_zone_ref(&privkey_n);

release_zone_ref(&pubkey_n);

release_zone_ref(&username_n);

 

if (xpubkey.len == 66)

{

int n = 33;

while (n--)

{

char hex[3];

hex[0] = xpubkey.str[n * 2 + 0];

hex[1] = xpubkey.str[n * 2 + 1];

hex[2] = 0;

pub[n] = strtoul_c(hex, PTR_NULL, 16);

}

key_to_addr(pub, pubaddr);

}

 

memset_c(priv, 0, sizeof(dh_key_t));

if ((xprivkey.len > 0) && (xprivkey.len <= sizeof(dh_key_t)))

{

int n = xprivkey.len;

while (n--)

{

char hex[3];

hex[0] = xprivkey.str[n * 2 + 0];

hex[1] = xprivkey.str[n * 2 + 1];

hex[2] = 0;

priv[n] = strtoul_c(hex, PTR_NULL, 16);

}

}

 

create_dir("keypairs");

make_string(&user_key_file, "keypairs");

cat_cstring_p(&user_key_file, username.str);

 

found = 0;

 

if (get_file(user_key_file.str, &keys_data, &keys_data_len))

{

mem_ptr keys_ptr = keys_data;

while (keys_data_len > 0)

{

if (!memcmp_c(keys_ptr, pubaddr, sizeof(btc_addr_t)))

{

found = 1;

break;

}

keys_ptr = mem_add(keys_ptr, (sizeof(btc_addr_t) + sizeof(dh_key_t)));

keys_data_len -= (sizeof(btc_addr_t) + sizeof(dh_key_t));

}

free_c(keys_data);

}

 

if (!found)

{

mem_zone_ref tx_list = { PTR_NULL }, my_list = { PTR_NULL };

mem_zone_ref_ptr tx = PTR_NULL;

 

append_file(user_key_file.str, pubaddr, sizeof(btc_addr_t));

append_file(user_key_file.str, priv, sizeof(dh_key_t));

if (tree_manager_create_node("txs", NODE_BITCORE_HASH_LIST, &tx_list))

{

struct string adr_path = { 0 };

make_string(&adr_path, "adrs");

cat_ncstring_p(&adr_path, pubaddr, 34);

if (stat_file(adr_path.str) == 0)

{

struct string path = { 0 };

clone_string(&path, &adr_path);

cat_cstring_p(&path, "spent");

rm_dir(path.str);

free_string(&path);

 

clone_string(&path, &adr_path);

cat_cstring_p(&path, "unspent");

rm_dir(path.str);

free_string(&path);

 

clone_string(&path, &adr_path);

cat_cstring_p(&path, "stakes");

del_file(path.str);

free_string(&path);

}

 

create_dir(adr_path.str);

free_string(&adr_path);

 

load_tx_addresses(pubaddr, &tx_list);

for (

tree_manager_get_first_child(&tx_list, &my_list, &tx);

((tx != NULL) && (tx->zone != NULL));

tree_manager_get_next_child(&my_list, &tx))

{

hash_t tx_hash;

 

tree_manager_get_node_hash(tx, 0, tx_hash);

store_tx_wallet(pubaddr, tx_hash);

}

release_zone_ref(&tx_list);

}

 

}

free_string(&user_key_file);

free_string(&username);

free_string(&xpubkey);

free_string(&xprivkey);

return 1;

}

 

 

OS_API_C_FUNC(int) getprivaddr(mem_zone_ref_const_ptr params, unsigned int rpc_mode, mem_zone_ref_ptr result)

{

mem_zone_ref pn = { PTR_NULL }, addr_list = { PTR_NULL };

struct string pubaddr = { PTR_NULL }, username = { PTR_NULL };

struct string user_key_file = { PTR_NULL };

unsigned char *keys_data = PTR_NULL;

size_t keys_data_len = 0;

int ret = 0;

 

tree_manager_get_child_at (params, 0, &pn);

tree_manager_get_node_istr (&pn, 0, &username, 0);

release_zone_ref (&pn);

 

tree_manager_get_child_at (params, 1, &pn);

tree_manager_get_node_istr (&pn, 0, &pubaddr, 0);

release_zone_ref (&pn);

 

make_string (&user_key_file, "keypairs");

cat_cstring_p (&user_key_file, username.str);

if (get_file(user_key_file.str, &keys_data, &keys_data_len))

{

unsigned char *keys_ptr = keys_data;

while (keys_data_len > 0)

{

if (!strncmp_c(keys_ptr, pubaddr.str , sizeof(btc_addr_t)))

{

char hexk[129];

int n=0;

while (n < 64)

{

hexk[n * 2 + 0] = hex_chars[keys_ptr[sizeof(btc_addr_t) + n] >> 4];

hexk[n * 2 + 1] = hex_chars[keys_ptr[sizeof(btc_addr_t) + n] & 0x0F];

n++;

}

hexk[64] = 0;

ret = 1;

tree_manager_set_child_value_str(result, "privkey", hexk);

break;

}

keys_ptr = mem_add(keys_ptr, (sizeof(btc_addr_t) + sizeof(dh_key_t)));

keys_data_len -= (sizeof(btc_addr_t) + sizeof(dh_key_t));

}

free_c(keys_data);

}

free_string(&pubaddr);

free_string(&username);

free_string(&user_key_file);

return ret;

}

 

 

 

OS_API_C_FUNC(int) getpubaddrs(mem_zone_ref_const_ptr params, unsigned int rpc_mode, mem_zone_ref_ptr result)

{

mem_zone_ref username_n = { PTR_NULL }, addr_list = { PTR_NULL };

struct string username = { PTR_NULL };

struct string user_key_file = { PTR_NULL };

size_t keys_data_len = 0;

uint64_t conf_amount, unconf_amount, minconf;

unsigned char *keys_data = PTR_NULL;

 

if (!tree_manager_add_child_node(result, "addrs", NODE_JSON_ARRAY, &addr_list))

return 0;

 

tree_manager_get_child_at(params, 0, &username_n);

tree_manager_get_node_istr(&username_n, 0, &username, 0);

release_zone_ref(&username_n);

 

make_string(&user_key_file, "keypairs");

cat_cstring_p(&user_key_file, username.str);

 

minconf = 1;

 

if (get_file(user_key_file.str, &keys_data, &keys_data_len))

{

mem_ptr keys_ptr=keys_data;

while (keys_data_len > 0)

{

mem_zone_ref new_addr = { PTR_NULL };

conf_amount = 0;

unconf_amount = 0;

 

get_balance (keys_ptr, &conf_amount, &unconf_amount, minconf);

if(tree_manager_add_child_node(&addr_list, "addr" , NODE_GFX_OBJECT, &new_addr))

{

tree_manager_set_child_value_btcaddr(&new_addr , "address", keys_ptr);

tree_manager_set_child_value_i64(&new_addr, "amount" , conf_amount);

tree_manager_set_child_value_i64(&new_addr, "unconf_amount", unconf_amount);

release_zone_ref(&new_addr);

}

keys_ptr = mem_add(keys_ptr ,(sizeof(btc_addr_t) + sizeof(dh_key_t)));

keys_data_len -= (sizeof(btc_addr_t) + sizeof(dh_key_t));

}

free_c(keys_data);

}

 

release_zone_ref (&addr_list);

free_string (&user_key_file);

free_string (&username);

return 1;

}

 

 

 

 

 

 

 

 

 

 

Sample javascript staking code in the browser

 

 

<script src="/ecdsa_bundle.js">script>

<script src="/jsSHA-2.2.0/src/sha_dev.js">script>

<script src="/jquery-3.1.1.min.js">script>

<script language="javascript">

var username = h0bby1 ;

var secret= 1234 ;

var ec;

var addrs = null;

var unspents = null;

var stake_unspents = null;

var totalweight = 0;

var pubkey;

var privkey;

var unit = 1;

var staketimer = null;

var block_target, now, last_block_time;

var nHashes=0;

 

 

function rpc_call(in_method, in_params, in_success) {

$.ajax({

url: /jsonrpc ,

data: JSON.stringify({ jsonrpc: 2.0 , method: in_method, params: in_params, id: 1 }), // id is needed !!

type: "POST",

dataType: "json",

success: in_success,

error: function (err) { alert("Error"); }

});

}

 

function staking_loop(hash_data, time_start, time_end, diff) {

var ct;

for (ct = time_start; ct < time_end; ct+=16)

{

str = hex32(ct);

total = hash_data + str;

h = sha256(total);

h2 = sha256(h);

 

if (compare_hash(h2, diff))

{

console.log( staking found + ct + + h2 + + diff);

$( #newhash ).html(h2);

return ct;

}

nHashes++;

}

return 0;

}

 

 

 

 

 

 

 

 

 

function check_all_staking() {

if ($( #do_staking ).prop( checked ))

{

if (stake_unspents != null)

{

var n;

var time_start, time_end;

var timeStart = Math.floor(new Date().getTime() / 1000);

var timeBegin = Math.floor((timeStart + 15) / 16) * 16;

var num_stake_unspents = stake_unspents.length;

if (last_block_time > (now - block_target)) {

time_start = Math.floor((last_block_time + 15) / 16) * 16;

time_end = time_start + block_target;

}

else {

time_start = timeBegin - 16;

time_end = timeBegin + 16;

}

nHashes = 0;

for (n = 0; n < num_stake_unspents; n++)

{

var txtime,staking;

staking = stake_unspents[n];

txtime=staking_loop(staking.hash_data, time_start, time_end, staking.difficulty);

if (txtime > 0)

{

rpc_call( getstaketx , [staking.txid, staking.vout, txtime], function (staketx)

{

var txh,txa;

txh = staketx.result.txhash;

txa = staketx.result.addr;

rpc_call( getprivaddr , [username, txa], function (keyData) {

var skey = decryptKey (keyData.result.privkey,secret);

keys = ec.keyPair({ priv: skey, privEnc: hex });

// Sign message (must be an array, or it ll be treated as a hex sequence)

var signature = keys.sign(txh, hex );

// Export DER encoded signature in Array

var derSign = signature.toLowS();

rpc_call( signstaketx , [txh, derSign], function (txsign) {

var hash = txsign.result.newblockhash;

var blocksignature = keys.sign(hash, hex );

// Export DER encoded signature in Array

var derSign = blocksignature.toLowS();

var pubk=keys.getPublic().encodeCompressed( hex );

rpc_call( signstakeblock , [hash, derSign, pubk], function (blksign) {});

});

});

});

$( #do_staking ).prop( checked , false);

return 0;

}

}

var timeEnd = Math.ceil(new Date().getTime() / 1000);

var timespan = (timeEnd-timeStart);

var hashrate = nHashes / timespan;

$( #hashrate ).html(nHashes + hashes in + timespan + secs ( + hashrate + hashes/sec) );

}

}

staketimer = setTimeout(check_all_staking, 10000);

}

 

function list_staking(addresses) {

var old_tbody = document.getElementById("list_table").tBodies[0];

var new_tbody = document.createElement( tbody );

old_tbody.parentNode.replaceChild(new_tbody, old_tbody);

rpc_call( liststaking , [0, 9999999, addresses], function (data) {

var total = 0;

var n;

stake_unspents = data.result.unspents;

block_target = data.result.block_target;

now = data.result.now;

last_block_time = last_block_time;

$( #do_staking ).prop( disabled , false);

 

for (n = 0; n < stake_unspents.length; n++)

{

total += stake_unspents[n].weight;

}

totalweight = total;

$( #stakeweight ).html(totalweight / unit);

$( #nstaketxs ).html(stake_unspents.length);

staketimer = setTimeout(check_all_staking, 10000);

 

});

}

 

function get_addrs(username) {

rpc_call( getpubaddrs , [username], function (data) {

var n;

var arAddr=[];

addrs = data.result.addrs;

update_addrs();

 

for (n = 0; n < addrs.length; n++) {

arAddr[n] = addrs[n].address;

}

list_unspent(arAddr);

list_staking(arAddr);

});

}

 

 

$(document).ready(function () {

ec = new EC( secp256k1 );

generateKeys();

get_addrs(username);

});

 

 

script>




0 coms.
Why C and not C++   avatarBitAdmin (9 articles)
posted on 25/01/17 23:09 13 views

At this time where everything goes OO, one can wonder why C is used in the core programming of the nodes instead of using an OO language like c++.

 

The first motivation for this choice is cross compiler binary compatibility, the system must be able to load and execute binary code regardless of the compiler used to compile it, and c++ is not a good choice for this for mainly two base reason, the calling convention used to compile class methods is not standard across compilers, and neither the decoration used for exported method name.

 

With C, all compiler for x86 recognize at least two function calling convention, "stdcall" and "cdecl", and for x64 two standard exist, one from microsoft and the one of gcc, but gcc can be forced to use the microsoft calling convention. These calling convention tell how parameters are passed across function call, and is vital to the modular approach used in the node. C++ doesn't define how the "this" pointer should be passed to method call on the binary/assembly level, so it would make binaries compiled with different compilers imcompatible with each others, which is not the case with C.

 

Exported functions name decoration is also important to consider, as for a module to call a function of another module, it need to know the name of the function as it's exported by the linker, the framework already require module to declare the function decoration scheme used with C, to make the match transparently between different name decoration used by different compilers, it recognize the gcc stdcall and cdcel and the visual studio style, there can be an underscore added, and the @ to tell the stack size with std call (_function@N), but functions can be imported and referenced from their base name transparently. But the scheme used to decorated c++ class's methods is more complex, has more attribute and is less standard.

 

Another reason why c++ can be bothering for cross compiler binary compatibility is the use of virtual method, of which pointer will be stored in a table of method pointer, the vtable, and the way the vtable is handled at binary level can be different between compiler, which would preclude sharing a pointer to a class instance with virtual method between different modules compiled with different compilers, because the vtable would not be stored the same.

 

Now the design is still made entierely around the component concept, the memory system and dynamic data tree make it very easy to deal with complex data hierarchy and references, and the systeme of cross compiler binary module in cunjunction with this dynamic data tree can make the framework very suitable for OO design. In the principle it's closer to how binary module work on RISCOS, each module define a set of function that use a specific register to hold a pointer to its instance data, which make the systeme very OO like albeit being made in ARM assembler, the binary module systeme in cunjunction to the dynamic data tree push the concept even further, because complex structured data can be passed across binary modules without depending on the particular memory agencement of the compiler or cpu. So it completly remove the whole burden of memory allocation, string manipulation and manipulation of hierarchized data structure from the C runtime.

 

Also C++ will mostly work with boost or the stdc++ library, which is also compiled differently on different platforms, and would most likely break binary compatibility. If two modules compiled with differents compilers on different hosts would share data structures used in calls to the framework, it would probably break in thousands manners.

 

For all these reason, i prefered to leave the object oriented design partern based on binary modules, rather than on c++ class. A binary module is essentially a static class, you could just add a class {} around the code and have a c++ static class with its methods being the function exported by the modules, and the static data members being the global variable in the data section of the module.

 

The only restriction of the binary module is that it doesn't support non initialized data section, so all global variables need to be initialized to non zero values, if you need large area of non initialized memory, use a memory allocation function. The binary module can be loaded 'in place', it can be included in a binary assembly file, and relocated 'in place' , as well as it's symbol imported and exported 'in place', without needing any memory allocation, so references to local addresses in the program must point to data included in the binary, which is not the case for non initialized data section, which are not stored in the binary but allocated when the dynamic loader load the binary module.

 

 

0 coms.
posted on 25/01/17 23:04 69 views

TPO BINARY MODULES

 

1. Why tpo modules ?

 

The motivation for developping my own dynamically linked position independant binary module was in the course of developping an operating system project, and i wanted to avoid dependency on a particular compiler or systeme architecture but still being able to compile and link binary executable and dynamically loaded binary libraries able to be loaded and executed by simplistic micro kernel architecture.

 

The main issue with both dll and elf (.so) files is that they are both tightly related to an operating system, and C or C++ code using standard c library and runtime depend on a particular compiler runtime, which depend on the host system kernel api, it's the case for both gcc whose major requirement is to be able to compile linux kernel, and linux or unix binaries, with gcc runtime using syscall and kernel calls specific to unix, or visual studio producing dll also dependent on their own runtime, it's a problem well known that it's often very hard to link a binary library produced with one compiler environment with an executable compiled with another compiler and runtime version, even when the ABI used is the same, and it become even more complex if a binary .so compiled under linux would have to be loaded and linked with a binary dll produced with visual studio on windows.

 

Tpo module are an effort to work around the tight relation between operating system, compiler, and binary code, to have binary code that can be loaded without having the need of a particular runtime or kernel.

 

 

2. How to create tpo modules ?

 

The only tool needed to produce tpo module is "modmaker", which is a command line tools that convert a dll or a .so into a binary module. It read all the sections, the imported and exported symbol, as well as rellocation table, and write it into a binary format that can be loaded by the libcon runtime on any intel x86 32 bit system (or x64 with x32 emulation, no support for x64 yet).

 

 

To create a tpo from a .so or dll, just run the command 'modmaker myfile.so/dll [output directory]' and it will output a tpo file. The only restriction is the dynamic loader doesn't handle non initialized section, because code reference to non initialized data point to location that are not in the binary, and it had to be loaded 'in place' as position independant code without any allocation (the allocator is in a tpo module).

 

 

The output should look like this for example for the rpc module that handle the request for the javascript wallet :

 

using file : C:/bitstream/serv/export/rpc_wallet.dll -> C:/bitstream/serv/export/modz/ 

 

PE HEADER Symbols : 0 , 0 flag : 2102

import table : 68b8 - 80

function name : _tree_manager_get_child_value_i64@12
reloc addr : 00000080@00006000 => 6ec2
function name : _tree_manager_get_node_hash@12
reloc addr : 00000084@00006000 => 6ea0
function name : _tree_manager_write_node_btcaddr@12
reloc addr : 00000088@00006000 => 6e7a
function name : _tree_manager_set_child_value_float@16
reloc addr : 0000008c@00006000 => 6e50
function name : _tree_manager_node_add_child@8
reloc addr : 00000090@00006000 => 6e2e
function name : _tree_manager_create_node@12
reloc addr : 00000094@00006000 => 6e0e
function name : _tree_manager_set_child_value_hash@12
reloc addr : 00000098@00006000 => 6de6
function name : _tree_manager_get_node_istr@16
reloc addr : 0000009c@00006000 => 6dc4
function name : _tree_manager_get_child_value_i16@12
reloc addr : 000000a0@00006000 => 6d9c
function name : _tree_manager_add_child_node@16
reloc addr : 000000a4@00006000 => 6d7a
function name : _tree_manager_write_node_sig@16
reloc addr : 000000a8@00006000 => 6d58
function name : _tree_manager_set_child_value_btcaddr@12
reloc addr : 000000ac@00006000 => 6d2c
function name : _tree_manager_get_child_value_i32@12
reloc addr : 000000b0@00006000 => 6d04
function name : _tree_manager_set_child_value_bhash@12
reloc addr : 000000b4@00006000 => 6a74
function name : _tree_mamanger_get_node_dword@12
reloc addr : 000000b8@00006000 => 6ce0
function name : _tree_manager_set_child_value_i32@12
reloc addr : 000000bc@00006000 => 6cb8
function name : _tree_find_child_node_by_member_name_hash@20
reloc addr : 000000c0@00006000 => 6c88
function name : _tree_manager_set_child_value_str@12
reloc addr : 000000c4@00006000 => 6c60
function name : _tree_manager_get_node_num_children@4
reloc addr : 000000c8@00006000 => 6c38
function name : _tree_manager_get_child_value_str@20
reloc addr : 000000cc@00006000 => 6c10
function name : _tree_manager_find_child_node@16
reloc addr : 000000d0@00006000 => 6bec
function name : _tree_manager_set_child_value_i64@16
reloc addr : 000000d4@00006000 => 6bc4
function name : _tree_manager_get_child_value_btcaddr@12
reloc addr : 000000d8@00006000 => 6b98
function name : _tree_manager_get_child_at@12
reloc addr : 000000dc@00006000 => 6b78
function name : _tree_manager_get_child_value_istr@16
reloc addr : 000000e0@00006000 => 6b50
function name : _tree_manager_get_next_child@8
reloc addr : 000000e4@00006000 => 6b2e
function name : _tree_manager_get_first_child@12
reloc addr : 000000e8@00006000 => 6b0a
function name : _tree_manager_get_node_btcaddr@12
reloc addr : 000000ec@00006000 => 6ae6
function name : _tree_manager_get_node_str@20
reloc addr : 000000f0@00006000 => 6ac6
function name : _tree_manager_get_child_value_hash@12
reloc addr : 000000f4@00006000 => 6a9e
function name : _rm_dir@4
reloc addr : 000000fc@00006000 => 70c0
function name : _malloc_c@4
reloc addr : 00000100@00006000 => 70b2
function name : _strncmp_c@12
reloc addr : 00000104@00006000 => 70a2
function name : _free_c@4
reloc addr : 00000108@00006000 => 7096
function name : _cat_cstring_p@8
reloc addr : 0000010c@00006000 => 7082
function name : _memchr_c@12
reloc addr : 00000110@00006000 => 7072
function name : _get_sub_files@8
reloc addr : 00000114@00006000 => 705e
function name : _get_tpo_mod_exp_addr_name@12
reloc addr : 00000118@00006000 => 703e
function name : _create_dir@4
reloc addr : 0000011c@00006000 => 702e
function name : _clone_string@8
reloc addr : 00000120@00006000 => 701c
function name : _get_time_c@0
reloc addr : 00000124@00006000 => 700c
function name : calc_crc32_c
reloc addr : 00000128@00006000 => 6ffc
function name : _get_sub_dirs@8
reloc addr : 0000012c@00006000 => 6fda
function name : _del_file@4
reloc addr : 00000130@00006000 => 6fcc
function name : _memcmp_c@12
reloc addr : 00000134@00006000 => 6fbc
function name : _strtoul_c@12
reloc addr : 00000138@00006000 => 6fac
function name : _cat_ncstring_p@12
reloc addr : 0000013c@00006000 => 6f96
function name : _free_string@4
reloc addr : 00000140@00006000 => 6f84
function name : _memset_c@12
reloc addr : 00000144@00006000 => 6f74
function name : _memcpy_c@12
reloc addr : 00000148@00006000 => 6f64
function name : _copy_zone_ref@8
reloc addr : 0000014c@00006000 => 6f50
function name : _stat_file@4
reloc addr : 00000150@00006000 => 6f40
function name : _make_string@8
reloc addr : 00000154@00006000 => 6f2e
function name : _append_file@12
reloc addr : 00000158@00006000 => 6f1c
function name : _muldiv64@24
reloc addr : 0000015c@00006000 => 6f0c
function name : _release_zone_ref@4
reloc addr : 00000160@00006000 => 6ef6
function name : _get_file@12
reloc addr : 00000164@00006000 => 6fec
function name : _get_block_size@8
reloc addr : 00000000@00006000 => 7108
function name : _compute_tx_sign_hash@20
reloc addr : 00000004@00006000 => 70ec
function name : _tx_add_input@16
reloc addr : 00000008@00006000 => 70d8
function name : _get_blk_height@8
reloc addr : 0000000c@00006000 => 7134
function name : _is_vout_null@8
reloc addr : 00000010@00006000 => 7148
function name : _mul_compact@16
reloc addr : 00000014@00006000 => 715a
function name : _cmp_hashle@8
reloc addr : 00000018@00006000 => 716c
function name : _compute_block_hash@8
reloc addr : 0000001c@00006000 => 717c
function name : _get_tx_output@12
reloc addr : 00000020@00006000 => 7194
function name : _new_transaction@12
reloc addr : 00000024@00006000 => 71a8
function name : _get_tx_output_amount@12
reloc addr : 00000028@00006000 => 71be
function name : _add_unspent@28
reloc addr : 0000002c@00006000 => 71da
function name : _parse_sig_seq@16
reloc addr : 00000030@00006000 => 71ec
function name : _get_out_script_address@12
reloc addr : 00000034@00006000 => 7200
function name : _is_pow_block@4
reloc addr : 00000038@00006000 => 721e
function name : _get_last_block_height@0
reloc addr : 0000003c@00006000 => 7230
function name : _load_tx_addresses@8
reloc addr : 00000040@00006000 => 724c
function name : _get_pow_block@8
reloc addr : 00000044@00006000 => 7264
function name : _is_tx_null@4
reloc addr : 00000048@00006000 => 7278
function name : _get_tx_input@12
reloc addr : 0000004c@00006000 => 7288
function name : _key_to_addr@8
reloc addr : 00000050@00006000 => 729c
function name : _get_moneysupply@4
reloc addr : 00000054@00006000 => 72ae
function name : _load_tx@12
reloc addr : 00000058@00006000 => 72c4
function name : _spend_tx_addr@28
reloc addr : 0000005c@00006000 => 72d2
function name : _tx_sign@16
reloc addr : 00000060@00006000 => 72e6
function name : _get_blk_txs@8
reloc addr : 00000064@00006000 => 72f4
function name : _tx_add_output@16
reloc addr : 00000068@00006000 => 7306
function name : _blk_check_sign@12
reloc addr : 0000006c@00006000 => 731a
function name : _SetCompact@8
reloc addr : 00000070@00006000 => 7330
function name : _get_tx_output_addr@12
reloc addr : 00000074@00006000 => 7340
function name : _get_tx_blk_height@16
reloc addr : 00000078@00006000 => 711c

export table : 6630 - 647

export table name : rpc_wallet - functions : 22 - names : 22 

name : _getaddressscanstatus@12@rpc_wallet - func addr: 0x00001e80 0x00001000 - ordinal : 1
name : _getblockcount@12@rpc_wallet - func addr: 0x000026a0 0x00001000 - ordinal : 2
name : _getinfo@12@rpc_wallet - func addr: 0x00002380 0x00001000 - ordinal : 3
name : _getlastblock@12@rpc_wallet - func addr: 0x00002070 0x00001000 - ordinal : 4
name : _getprivaddr@12@rpc_wallet - func addr: 0x00005580 0x00001000 - ordinal : 5
name : _getpubaddrs@12@rpc_wallet - func addr: 0x00005710 0x00001000 - ordinal : 6
name : _getstaketx@12@rpc_wallet - func addr: 0x00004ac0 0x00001000 - ordinal : 7
name : _getstaking@12@rpc_wallet - func addr: 0x00004f60 0x00001000 - ordinal : 8
name : _importaddress@12@rpc_wallet - func addr: 0x000026d0 0x00001000 - ordinal : 9
name : _importkeypair@12@rpc_wallet - func addr: 0x00005150 0x00001000 - ordinal : 10
name : _listreceived@12@rpc_wallet - func addr: 0x00002ee0 0x00001000 - ordinal : 11
name : _listreceivedbyaddress@12@rpc_wallet - func addr: 0x00003650 0x00001000 - ordinal : 12
name : _listspent@12@rpc_wallet - func addr: 0x00003000 0x00001000 - ordinal : 13
name : _liststaking@12@rpc_wallet - func addr: 0x000042d0 0x00001000 - ordinal : 14
name : _listtransactions@12@rpc_wallet - func addr: 0x00002840 0x00001000 - ordinal : 15
name : _listunspent@12@rpc_wallet - func addr: 0x00003520 0x00001000 - ordinal : 16
name : _pubkeytoaddr@12@rpc_wallet - func addr: 0x000037a0 0x00001000 - ordinal : 18
name : _set_node@8@rpc_wallet - func addr: 0x00001010 0x00001000 - ordinal : 19
name : _signstakeblock@12@rpc_wallet - func addr: 0x000044d0 0x00001000 - ordinal : 20
name : _signstaketx@12@rpc_wallet - func addr: 0x000047c0 0x00001000 - ordinal : 21
name : mod_name_deco_type@rpc_wallet - func addr: 0x00008000 0x00008000 - ordinal : 17


text section :
name : .text
section header flags : 60000020
relocations : 0
relocations ptr: 0
vaddr : 00001000
paddr : 000048cd
size : 18944
externs : 0
syms : 0
imports : 0

 

rdata section :

name : .rdata
section header flags : 40000040
relocations : 0
relocations ptr: 0
vaddr : 00006000
paddr : 00001368
size : 5120
externs : 0
syms : 0

symboles :

imports : 88 
module : libbase - function : _tree_manager_get_child_value_i64@12 - reloc addr : 0x00000080
module : libbase - function : _tree_manager_get_node_hash@12 - reloc addr : 0x00000084
module : libbase - function : _tree_manager_write_node_btcaddr@12 - reloc addr : 0x00000088
module : libbase - function : _tree_manager_set_child_value_float@16 - reloc addr : 0x0000008c
module : libbase - function : _tree_manager_node_add_child@8 - reloc addr : 0x00000090
module : libbase - function : _tree_manager_create_node@12 - reloc addr : 0x00000094
module : libbase - function : _tree_manager_set_child_value_hash@12 - reloc addr : 0x00000098
module : libbase - function : _tree_manager_get_node_istr@16 - reloc addr : 0x0000009c
module : libbase - function : _tree_manager_get_child_value_i16@12 - reloc addr : 0x000000a0
module : libbase - function : _tree_manager_add_child_node@16 - reloc addr : 0x000000a4
module : libbase - function : _tree_manager_write_node_sig@16 - reloc addr : 0x000000a8
module : libbase - function : _tree_manager_set_child_value_btcaddr@12 - reloc addr : 0x000000ac
module : libbase - function : _tree_manager_get_child_value_i32@12 - reloc addr : 0x000000b0
module : libbase - function : _tree_manager_set_child_value_bhash@12 - reloc addr : 0x000000b4
module : libbase - function : _tree_mamanger_get_node_dword@12 - reloc addr : 0x000000b8
module : libbase - function : _tree_manager_set_child_value_i32@12 - reloc addr : 0x000000bc
module : libbase - function : _tree_find_child_node_by_member_name_hash@20 - reloc addr : 0x000000c0
module : libbase - function : _tree_manager_set_child_value_str@12 - reloc addr : 0x000000c4
module : libbase - function : _tree_manager_get_node_num_children@4 - reloc addr : 0x000000c8
module : libbase - function : _tree_manager_get_child_value_str@20 - reloc addr : 0x000000cc
module : libbase - function : _tree_manager_find_child_node@16 - reloc addr : 0x000000d0
module : libbase - function : _tree_manager_set_child_value_i64@16 - reloc addr : 0x000000d4
module : libbase - function : _tree_manager_get_child_value_btcaddr@12 - reloc addr : 0x000000d8
module : libbase - function : _tree_manager_get_child_at@12 - reloc addr : 0x000000dc
module : libbase - function : _tree_manager_get_child_value_istr@16 - reloc addr : 0x000000e0
module : libbase - function : _tree_manager_get_next_child@8 - reloc addr : 0x000000e4
module : libbase - function : _tree_manager_get_first_child@12 - reloc addr : 0x000000e8
module : libbase - function : _tree_manager_get_node_btcaddr@12 - reloc addr : 0x000000ec
module : libbase - function : _tree_manager_get_node_str@20 - reloc addr : 0x000000f0
module : libbase - function : _tree_manager_get_child_value_hash@12 - reloc addr : 0x000000f4
module : libcon - function : _rm_dir@4 - reloc addr : 0x000000fc
module : libcon - function : _malloc_c@4 - reloc addr : 0x00000100
module : libcon - function : _strncmp_c@12 - reloc addr : 0x00000104
module : libcon - function : _free_c@4 - reloc addr : 0x00000108
module : libcon - function : _cat_cstring_p@8 - reloc addr : 0x0000010c
module : libcon - function : _memchr_c@12 - reloc addr : 0x00000110
module : libcon - function : _get_sub_files@8 - reloc addr : 0x00000114
module : libcon - function : _get_tpo_mod_exp_addr_name@12 - reloc addr : 0x00000118
module : libcon - function : _create_dir@4 - reloc addr : 0x0000011c
module : libcon - function : _clone_string@8 - reloc addr : 0x00000120
module : libcon - function : _get_time_c@0 - reloc addr : 0x00000124
module : libcon - function : calc_crc32_c - reloc addr : 0x00000128
module : libcon - function : _get_sub_dirs@8 - reloc addr : 0x0000012c
module : libcon - function : _del_file@4 - reloc addr : 0x00000130
module : libcon - function : _memcmp_c@12 - reloc addr : 0x00000134
module : libcon - function : _strtoul_c@12 - reloc addr : 0x00000138
module : libcon - function : _cat_ncstring_p@12 - reloc addr : 0x0000013c
module : libcon - function : _free_string@4 - reloc addr : 0x00000140
module : libcon - function : _memset_c@12 - reloc addr : 0x00000144
module : libcon - function : _memcpy_c@12 - reloc addr : 0x00000148
module : libcon - function : _copy_zone_ref@8 - reloc addr : 0x0000014c
module : libcon - function : _stat_file@4 - reloc addr : 0x00000150
module : libcon - function : _make_string@8 - reloc addr : 0x00000154
module : libcon - function : _append_file@12 - reloc addr : 0x00000158
module : libcon - function : _muldiv64@24 - reloc addr : 0x0000015c
module : libcon - function : _release_zone_ref@4 - reloc addr : 0x00000160
module : libcon - function : _get_file@12 - reloc addr : 0x00000164
module : block_adx - function : _get_block_size@8 - reloc addr : 0x00000000
module : block_adx - function : _compute_tx_sign_hash@20 - reloc addr : 0x00000004
module : block_adx - function : _tx_add_input@16 - reloc addr : 0x00000008
module : block_adx - function : _get_blk_height@8 - reloc addr : 0x0000000c
module : block_adx - function : _is_vout_null@8 - reloc addr : 0x00000010
module : block_adx - function : _mul_compact@16 - reloc addr : 0x00000014
module : block_adx - function : _cmp_hashle@8 - reloc addr : 0x00000018
module : block_adx - function : _compute_block_hash@8 - reloc addr : 0x0000001c
module : block_adx - function : _get_tx_output@12 - reloc addr : 0x00000020
module : block_adx - function : _new_transaction@12 - reloc addr : 0x00000024
module : block_adx - function : _get_tx_output_amount@12 - reloc addr : 0x00000028
module : block_adx - function : _add_unspent@28 - reloc addr : 0x0000002c
module : block_adx - function : _parse_sig_seq@16 - reloc addr : 0x00000030
module : block_adx - function : _get_out_script_address@12 - reloc addr : 0x00000034
module : block_adx - function : _is_pow_block@4 - reloc addr : 0x00000038
module : block_adx - function : _get_last_block_height@0 - reloc addr : 0x0000003c
module : block_adx - function : _load_tx_addresses@8 - reloc addr : 0x00000040
module : block_adx - function : _get_pow_block@8 - reloc addr : 0x00000044
module : block_adx - function : _is_tx_null@4 - reloc addr : 0x00000048
module : block_adx - function : _get_tx_input@12 - reloc addr : 0x0000004c
module : block_adx - function : _key_to_addr@8 - reloc addr : 0x00000050
module : block_adx - function : _get_moneysupply@4 - reloc addr : 0x00000054
module : block_adx - function : _load_tx@12 - reloc addr : 0x00000058
module : block_adx - function : _spend_tx_addr@28 - reloc addr : 0x0000005c
module : block_adx - function : _tx_sign@16 - reloc addr : 0x00000060
module : block_adx - function : _get_blk_txs@8 - reloc addr : 0x00000064
module : block_adx - function : _tx_add_output@16 - reloc addr : 0x00000068
module : block_adx - function : _blk_check_sign@12 - reloc addr : 0x0000006c
module : block_adx - function : _SetCompact@8 - reloc addr : 0x00000070
module : block_adx - function : _get_tx_output_addr@12 - reloc addr : 0x00000074
module : block_adx - function : _get_tx_blk_height@16 - reloc addr : 0x00000078


data section :
name : .data
section header flags : c0000040
relocations : 0
relocations ptr: 0
vaddr : 00008000
paddr : 00008830
size : 35328
externs : 0
syms : 0

symboles :

imports : 0


init section :


res section :


ew section :


bss section :


check relocs :
section idx: '0' mem ofset 0 total ofset 26
section : '.text' (0x00001000) [0x004204e0 + 26] = 10010828 (10000000)
section idx: '0' mem ofset 0 total ofset 35
section : '.text' (0x00001000) [0x004204e0 + 35] = 10010828 (10000000)
section idx: '0' mem ofset 0 total ofset 41
section : '.text' (0x00001000) [0x004204e0 + 41] = 1000614c (10000000)
section idx: '0' mem ofset 0 total ofset 50
section : '.text' (0x00001000) [0x004204e0 + 50] = 10006118 (10000000)
section idx: '0' mem ofset 0 total ofset 57
section : '.text' (0x00001000) [0x004204e0 + 57] = 10006170 (10000000)
section idx: '0' mem ofset 0 total ofset 67
section : '.text' (0x00001000) [0x004204e0 + 67] = 10006188 (10000000)

[...]

num remaps : 824 1000 5a00
relocation, section addr 1a 00008000 addr final 00010828
relocation, section addr 23 00008000 addr final 00010828
relocation, section addr 29 00006000 addr final 0000614c
relocation, section addr 32 00006000 addr final 00006118
relocation, section addr 39 00006000 addr final 00006170

[...]

num remaps : 0 6000 7400
num remaps : 0 8000 10a00
module decoration type found 1
data pos : 2625
data padding : 15
write import 0 name
write export 21 name
name : _getaddressscanstatus@12[9986323a]@rpc_wallet[41102b07] - func addr: 0x00000e80
name : _getblockcount@12[31547d5d]@rpc_wallet[41102b07] - func addr: 0x000016a0
name : _getinfo@12[8ccb68f3]@rpc_wallet[41102b07] - func addr: 0x00001380
name : _getlastblock@12[a4bdff2e]@rpc_wallet[41102b07] - func addr: 0x00001070
name : _getprivaddr@12[8d60e8ea]@rpc_wallet[41102b07] - func addr: 0x00004580
name : _getpubaddrs@12[ac4c14f7]@rpc_wallet[41102b07] - func addr: 0x00004710
name : _getstaketx@12[dbfb0731]@rpc_wallet[41102b07] - func addr: 0x00003ac0
name : _getstaking@12[c2894f46]@rpc_wallet[41102b07] - func addr: 0x00003f60
name : _importaddress@12[b28731f3]@rpc_wallet[41102b07] - func addr: 0x000016d0
name : _importkeypair@12[8b75b915]@rpc_wallet[41102b07] - func addr: 0x00004150
name : _listreceived@12[fffe0fe9]@rpc_wallet[41102b07] - func addr: 0x00001ee0
name : _listreceivedbyaddress@12[89a400f3]@rpc_wallet[41102b07] - func addr: 0x00002650
name : _listspent@12[5b33c934]@rpc_wallet[41102b07] - func addr: 0x00002000
name : _liststaking@12[61658631]@rpc_wallet[41102b07] - func addr: 0x000032d0
name : _listtransactions@12[21d5fb75]@rpc_wallet[41102b07] - func addr: 0x00001840
name : _listunspent@12[d844ae77]@rpc_wallet[41102b07] - func addr: 0x00002520
name : _pubkeytoaddr@12[966f22b2]@rpc_wallet[41102b07] - func addr: 0x000027a0
name : _set_node@8[db61c4e6]@rpc_wallet[41102b07] - func addr: 0x00000010
name : _signstakeblock@12[c823a9de]@rpc_wallet[41102b07] - func addr: 0x000034d0
name : _signstaketx@12[2cffe441]@rpc_wallet[41102b07] - func addr: 0x000037c0
name : EntryPoint[04ca6e53]@rpc_wallet[41102b07] - func addr: 0x00000000
data pos : 28476
data padding : 4

write import 88 name
string index 1768 => '_make_string@8'
name : _make_string@8[bfb939a5]@libcon[3ddf3671] - func addr: 0x00000154 => 6f2e
string index 1436 => 'libcon'
string index 1783 => '_append_file@12'
name : _append_file@12[99a0ed2a]@libcon[3ddf3671] - func addr: 0x00000158 => 6f1c
string index 1436 => 'libcon'
string index 1799 => '_muldiv64@24'
name : _muldiv64@24[82da4eeb]@libcon[3ddf3671] - func addr: 0x0000015c => 6f0c
string index 1436 => 'libcon'
string index 1812 => '_release_zone_ref@4'
name : _release_zone_ref@4[2b7f522a]@libcon[3ddf3671] - func addr: 0x00000160 => 6ef6
string index 1436 => 'libcon'
string index 1832 => '_get_file@12'
name : _get_file@12[5c6fa1d3]@libcon[3ddf3671] - func addr: 0x00000164 => 6fec
string index 1845 => 'block_adx'
string index 1855 => '_get_block_size@8'
name : _get_block_size@8[94664944]@block_adx[fe093354] - func addr: 0x00000000 => 7108
string index 1845 => 'block_adx'
string index 1873 => '_compute_tx_sign_hash@20'
name : _compute_tx_sign_hash@20[0643e4d7]@block_adx[fe093354] - func addr: 0x00000004 => 70ec
string index 1845 => 'block_adx'
string index 1898 => '_tx_add_input@16'
name : _tx_add_input@16[7704f87e]@block_adx[fe093354] - func addr: 0x00000008 => 70d8
string index 1845 => 'block_adx'
string index 1915 => '_get_blk_height@8'
name : _get_blk_height@8[3f57daea]@block_adx[fe093354] - func addr: 0x0000000c => 7134
string index 1845 => 'block_adx'
string index 1933 => '_is_vout_null@8'
name : _is_vout_null@8[acd95b77]@block_adx[fe093354] - func addr: 0x00000010 => 7148
string index 1845 => 'block_adx'
string index 1949 => '_mul_compact@16'
name : _mul_compact@16[f45be4d8]@block_adx[fe093354] - func addr: 0x00000014 => 715a
string index 1845 => 'block_adx'
string index 1965 => '_cmp_hashle@8'
name : _cmp_hashle@8[8fa59d06]@block_adx[fe093354] - func addr: 0x00000018 => 716c
string index 1845 => 'block_adx'
string index 1979 => '_compute_block_hash@8'
name : _compute_block_hash@8[8cd5acb0]@block_adx[fe093354] - func addr: 0x0000001c => 717c
string index 1845 => 'block_adx'
string index 2001 => '_get_tx_output@12'
name : _get_tx_output@12[29b67459]@block_adx[fe093354] - func addr: 0x00000020 => 7194
string index 1845 => 'block_adx'
string index 2019 => '_new_transaction@12'
name : _new_transaction@12[64fdada7]@block_adx[fe093354] - func addr: 0x00000024 => 71a8
string index 1845 => 'block_adx'
string index 2039 => '_get_tx_output_amount@12'
name : _get_tx_output_amount@12[bda11d89]@block_adx[fe093354] - func addr: 0x00000028 => 71be
string index 1845 => 'block_adx'
string index 2064 => '_add_unspent@28'
name : _add_unspent@28[2256835b]@block_adx[fe093354] - func addr: 0x0000002c => 71da
string index 1845 => 'block_adx'
string index 2080 => '_parse_sig_seq@16'
name : _parse_sig_seq@16[eeae2d45]@block_adx[fe093354] - func addr: 0x00000030 => 71ec
string index 1845 => 'block_adx'
string index 2098 => '_get_out_script_address@12'
name : _get_out_script_address@12[1d8359db]@block_adx[fe093354] - func addr: 0x00000034 => 7200
string index 1845 => 'block_adx'
string index 2125 => '_is_pow_block@4'
name : _is_pow_block@4[e61b937a]@block_adx[fe093354] - func addr: 0x00000038 => 721e
string index 1845 => 'block_adx'
string index 2141 => '_get_last_block_height@0'
name : _get_last_block_height@0[9109c8c9]@block_adx[fe093354] - func addr: 0x0000003c => 7230
string index 1845 => 'block_adx'
string index 2166 => '_load_tx_addresses@8'
name : _load_tx_addresses@8[d66f2f62]@block_adx[fe093354] - func addr: 0x00000040 => 724c
string index 1845 => 'block_adx'
string index 2187 => '_get_pow_block@8'
name : _get_pow_block@8[f900d7a8]@block_adx[fe093354] - func addr: 0x00000044 => 7264
string index 1845 => 'block_adx'
string index 2204 => '_is_tx_null@4'
name : _is_tx_null@4[8db0f4c6]@block_adx[fe093354] - func addr: 0x00000048 => 7278
string index 1845 => 'block_adx'
string index 2218 => '_get_tx_input@12'
name : _get_tx_input@12[3e9f0c9f]@block_adx[fe093354] - func addr: 0x0000004c => 7288
string index 1845 => 'block_adx'
string index 2235 => '_key_to_addr@8'
name : _key_to_addr@8[7d5d3ed2]@block_adx[fe093354] - func addr: 0x00000050 => 729c
string index 1845 => 'block_adx'
string index 2250 => '_get_moneysupply@4'
name : _get_moneysupply@4[174bd4c4]@block_adx[fe093354] - func addr: 0x00000054 => 72ae
string index 1845 => 'block_adx'
string index 2269 => '_load_tx@12'
name : _load_tx@12[4c0c7578]@block_adx[fe093354] - func addr: 0x00000058 => 72c4
string index 1845 => 'block_adx'
string index 2281 => '_spend_tx_addr@28'
name : _spend_tx_addr@28[b53bfd6b]@block_adx[fe093354] - func addr: 0x0000005c => 72d2
string index 1845 => 'block_adx'
string index 2299 => '_tx_sign@16'
name : _tx_sign@16[b6fefac9]@block_adx[fe093354] - func addr: 0x00000060 => 72e6
string index 1845 => 'block_adx'
string index 2311 => '_get_blk_txs@8'
name : _get_blk_txs@8[e870b593]@block_adx[fe093354] - func addr: 0x00000064 => 72f4
string index 1845 => 'block_adx'
string index 2326 => '_tx_add_output@16'
name : _tx_add_output@16[40476bf9]@block_adx[fe093354] - func addr: 0x00000068 => 7306
string index 1845 => 'block_adx'
string index 2344 => '_blk_check_sign@12'
name : _blk_check_sign@12[dddd9195]@block_adx[fe093354] - func addr: 0x0000006c => 731a
string index 1845 => 'block_adx'
string index 2363 => '_SetCompact@8'
name : _SetCompact@8[ab7e0101]@block_adx[fe093354] - func addr: 0x00000070 => 7330
string index 1845 => 'block_adx'
string index 2377 => '_get_tx_output_addr@12'
name : _get_tx_output_addr@12[53b0f5ce]@block_adx[fe093354] - func addr: 0x00000074 => 7340
string index 1845 => 'block_adx'
string index 2400 => '_get_tx_blk_height@16'
name : _get_tx_blk_height@16[a517fd67]@block_adx[fe093354] - func addr: 0x00000078 => 711c
write export 0 name
data pos : 34704
write import 0 name
write export 2 name
name : _fltused[618381b1]@rpc_wallet[41102b07] - func addr: 0x0000882c
name : mod_name_deco_type[30d5d717]@rpc_wallet[41102b07] - func addr: 0x00000000

 

3. How to use tpo modules ?

 

To load and execute a tpo module in C, need to link with the libcon library, then it can be loaded with this code :

 

#include <base/std_def.h>
#include <base/std_mem.h>
#include <base/mem_base.h>
#include <base/std_str.h>
#include <fsio.h>
#include <mem_stream.h>
#include <tpo_mod.h>

 

 

int load_module(const char *file, const char *mod_name, tpo_mod_file *mod)

{


mem_stream mod_file;
mem_zone_ref tpo_file_data = { PTR_NULL };
unsigned char *data;
size_t data_len;

 //read tpo mod file data

if (get_file(file, &data, &data_len) <= 0)return 0;

//initialize memory stream with the data

allocate_new_zone(0, data_len, &tpo_file_data);
memcpy_c(get_zone_ptr(&tpo_file_data, 0), data, data_len);
memset_c(&mod_file, 0, sizeof(mem_stream));
mem_stream_init(&mod_file, &tpo_file_data, 0);

//initialize tpo module
tpo_mod_init(mod);
tpo_mod_load_tpo(&mod_file, mod, 0);

//register global export if others module's imports depend on this module

register_tpo_exports(mod, mod_name);

//free the memory

release_zone_ref(&tpo_file_data);
free_c(data);

}

 

int main(int argc, char **argv)

{

int done = 0;

//base initialization
init_mem_system ();

//init 8Mo of memory
init_default_mem_area (8 * 1024 * 1024);

 

//init network
network_init ();

//set home dir
set_exe_path ();
set_home_path ("purenode");

 

//load node modules

load_module("modz/libbase.tpo", "libbase", &libbase_mod);
load_module("modz/protocol_adx.tpo", "protocol_adx", &protocol_mod);
load_module("modz/block_adx.tpo", "block_adx", &block_mod);
load_module("modz/iadixcoin.tpo", "iadixcoin", &iadix_mod);

 

//load application entry points

app_init = get_tpo_mod_exp_addr_name(&iadix_mod, "app_init", 0);

app_start = get_tpo_mod_exp_addr_name(&iadix_mod, "app_start", 0);
app_loop = get_tpo_mod_exp_addr_name(&iadix_mod, "app_loop", 0);
app_stop = get_tpo_mod_exp_addr_name(&iadix_mod, "app_stop", 0);

if (!app_init(PTR_NULL))
{

console_print("could not initialize app ");
console_print(iadix_mod.name);
console_print("\n");
return 0;

}

//initialize application context

daemonize ("purenode");

 

//start application
app_start (PTR_NULL);

while (isRunning())
{

app_loop(PTR_NULL);

}

app_stop(PTR_NULL);

}

 

 

 

 

The dynamic loader take care of registering export, and matching import symbol decoration between compilers as long as the calling convention is identical. and relocate data reference to the dynamically allocated area. The same binary module can be loaded and executed from any operating system host, provided it can execute x86 machine code from memory.

0 coms.

tags


HTML 5 DOC