From b9ada2c8e7d6d572b11e11e96d36576162dd02c0 Mon Sep 17 00:00:00 2001
From: Aleksey Feoktistov <aleksey@synestproject.com>
Date: Wed, 24 Nov 2021 23:11:12 +0500
Subject: [PATCH] [+] add division functions for 256bit and not native 128bit;
 minor fixes;

---
 dap-sdk/core/include/dap_math_ops.h       | 400 +++++++++++-----------
 dap-sdk/core/test/uint256_t/unit_test.cpp |  30 +-
 modules/chain/dap_chain_ledger.c          |  11 +-
 modules/common/dap_chain_common.c         |   2 +-
 modules/common/dap_chain_datum_tx.c       |   2 +-
 modules/common/include/dap_chain_common.h |   6 +-
 modules/net/dap_chain_node_cli_cmd_tx.c   |  71 +++-
 modules/type/blocks/dap_chain_cs_blocks.c |   4 +
 modules/type/dag/dap_chain_cs_dag.c       |   5 +
 9 files changed, 298 insertions(+), 233 deletions(-)

diff --git a/dap-sdk/core/include/dap_math_ops.h b/dap-sdk/core/include/dap_math_ops.h
index 806624e470..adc7dc060b 100755
--- a/dap-sdk/core/include/dap_math_ops.h
+++ b/dap-sdk/core/include/dap_math_ops.h
@@ -74,23 +74,45 @@ const  uint128_t two_power_64={ .hi = 1, .lo = 0};
 const  uint128_t lo_64={ .hi = 0, .lo = 0xffffffffffffffff};
 const  uint128_t hi_64={ .hi = 0xffffffffffffffff, .lo = 0};
 // const  uint128_t zero_128={.hi=0,.lo=0};
-#define zero_128 ((uint128_t){.hi=0,.lo=0})
+// #define zero_128 ((uint128_t){.hi=0,.lo=0})
+
+#define uint128_0 ((uint128_t){.hi=0,.lo=0})
+#define uint128_1 ((uint128_t){.hi=0,.lo=1})
 
 // const uint64_t lo_32=0xffffffff;
 // const uint64_t hi_32=0xffffffff00000000;
 // const uint64_t ones_64=0xffffffffffffffff;
 
 #else // DAP_GLOBAL_IS_INT128
-#define zero_128 ((uint128_t)0)
+
+// #define zero_128 ((uint128_t)0)
+#define uint128_0 ((uint128_t)0)
+#define uint128_1 ((uint128_t)1)
+
 #endif // DAP_GLOBAL_IS_INT128
 
-//const uint256_t zero_256={.hi=zero_128,.lo=zero_128};
-#define zero_256 ((uint256_t){.hi=zero_128,.lo=zero_128})
+// const uint256_t zero_256={.hi=zero_128,.lo=zero_128};
+// #define zero_256 ((uint256_t){.hi=zero_128,.lo=zero_128})
+#define uint256_0 ((uint256_t){.hi=uint128_0,.lo=uint128_0})
+#define uint256_1 ((uint256_t){.hi=uint128_0,.lo=uint128_1})
+#define uint512_0 ((uint512_t){.hi=uint256_0,.lo=uint256_0})
 #define lo_32 ((uint64_t)0xffffffff)
 #define hi_32 ((uint64_t)0xffffffff00000000)
 #define ones_64 ((uint64_t)0xffffffffffffffff)
 
 
+static inline uint128_t GET_128(uint64_t n) {
+#ifdef DAP_GLOBAL_IS_INT128
+    return (uint128_t) n;
+#else
+    return (uint128_t){.hi=0,.lo=n};
+#endif
+}
+
+static inline uint256_t GET_256(uint64_t n) {
+    return (uint256_t){.hi=uint128_0,.lo=GET_128(n)};
+}
+
 static inline bool EQUAL_128(uint128_t a_128_bit, uint128_t b_128_bit){
 #ifdef DAP_GLOBAL_IS_INT128
     return a_128_bit == b_128_bit;
@@ -116,13 +138,11 @@ static inline uint128_t AND_128(uint128_t a_128_bit,uint128_t b_128_bit){
 
 #ifdef DAP_GLOBAL_IS_INT128
     return a_128_bit&b_128_bit;
-    
 #else    
-    uint128_t output={ .hi = 0, .lo = 0};
+    uint128_t output=uint128_0;
     output.hi= a_128_bit.hi & b_128_bit.hi;  
     output.lo= a_128_bit.lo & b_128_bit.lo;
     return output;
-
 #endif
 }
 
@@ -131,69 +151,46 @@ static inline uint128_t OR_128(uint128_t a_128_bit,uint128_t b_128_bit){
 #ifdef DAP_GLOBAL_IS_INT128
     return a_128_bit|b_128_bit;
 
-#else    
-    uint128_t output={ .hi = 0, .lo = 0};
+#else
+    uint128_t output=uint128_0;
     output.hi= a_128_bit.hi | b_128_bit.hi;  
     output.lo= a_128_bit.lo | b_128_bit.lo;
     return output;
-
 #endif
 }
 
 static inline uint256_t AND_256(uint256_t a_256_bit,uint256_t b_256_bit){
-
-#ifdef DAP_GLOBAL_IS_INT128
-    uint256_t output = {};
-    output.hi= a_256_bit.hi & b_256_bit.hi;  
-    output.lo= a_256_bit.lo & b_256_bit.lo;
+    uint256_t output = uint256_0;
+    output.hi = AND_128(a_256_bit.hi, b_256_bit.hi);  
+    output.lo = AND_128(a_256_bit.lo, b_256_bit.lo);
     return output;
-
-#else 
-    uint256_t output={ .hi = zero_128, .lo = zero_128};
-    output.hi= AND_128(a_256_bit.hi, b_256_bit.hi);  
-    output.lo= AND_128(a_256_bit.lo, b_256_bit.lo);
-    return output;
-
-#endif
 }
 
 static inline uint256_t OR_256(uint256_t a_256_bit,uint256_t b_256_bit){
-
-#ifdef DAP_GLOBAL_IS_INT128
-    uint256_t output= {};
-    output.hi= a_256_bit.hi | b_256_bit.hi;  
-    output.lo= a_256_bit.lo | b_256_bit.lo;
+    uint256_t output = uint256_0;
+    output.hi = OR_128(a_256_bit.hi, b_256_bit.hi); 
+    output.lo = OR_128(a_256_bit.lo, b_256_bit.lo); 
     return output;
-
-#else 
-    uint256_t output={ .hi = zero_128, .lo = zero_128};
-    output.hi= OR_128(a_256_bit.hi, b_256_bit.hi); 
-    output.lo= OR_128(a_256_bit.lo, b_256_bit.lo); 
-    return output;
-
-#endif
 }
 
 static inline void LEFT_SHIFT_128(uint128_t a_128_bit,uint128_t* b_128_bit,int n){
     assert (n <= 128);
 
 #ifdef DAP_GLOBAL_IS_INT128
-    *b_128_bit=a_128_bit<<n;
+    *b_128_bit= a_128_bit << n;
 
 #else 
-    if (n >= 64) // shifting 64-bit integer by more than 63 bits is not defined
-    {   
+    if (n >= 64) { // shifting 64-bit integer by more than 63 bits is not defined   
         a_128_bit.hi=a_128_bit.lo;
         a_128_bit.lo=0;
         LEFT_SHIFT_128(a_128_bit,b_128_bit,n-64);
     }
-    if (n == 0)
-    {
+    if (n == 0) {
        b_128_bit->hi=a_128_bit.hi;
        b_128_bit->lo=a_128_bit.lo;
     } 
-    else
-    {   uint64_t shift_temp;
+    else {
+        uint64_t shift_temp;
         shift_temp=a_128_bit.lo<<n;
         b_128_bit->lo=shift_temp;
         b_128_bit->hi=(a_128_bit.hi<<n)|(a_128_bit.lo>>(64-n));
@@ -207,9 +204,7 @@ static inline void RIGHT_SHIFT_128(uint128_t a_128_bit,uint128_t* b_128_bit,int
 
 #ifdef DAP_GLOBAL_IS_INT128
     (*b_128_bit) = a_128_bit >> n;
-
 #else 
-    
     if (n >= 64) // shifting 64-bit integer by more than 63 bits is not defined
     {   
         a_128_bit.lo=a_128_bit.hi;
@@ -235,94 +230,48 @@ static inline void LEFT_SHIFT_256(uint256_t a_256_bit,uint256_t* b_256_bit,int n
  
     assert (n <= 256);
 
-#ifdef DAP_GLOBAL_IS_INT128
-
-    if (n >= 128) 
-    {   
-        a_256_bit.hi=a_256_bit.lo;
-        a_256_bit.lo=0;
-        LEFT_SHIFT_256(a_256_bit,b_256_bit,n-128);
-    }
-    if (n == 0)
-    {
-       b_256_bit->hi=a_256_bit.hi;
-       b_256_bit->lo=a_256_bit.lo;
-    } 
-    else
-    {   uint128_t shift_temp;
-        shift_temp=a_256_bit.lo<<n;
-        b_256_bit->lo=shift_temp;
-        b_256_bit->hi=(a_256_bit.hi<<n)|(a_256_bit.lo>>(128-n));
-    }
-
-#else 
-    if (n >= 128) // shifting 64-bit integer by more than 63 bits is not defined
-    {   
+    if (n >= 128) { // shifting 64-bit integer by more than 63 bits is not defined 
         a_256_bit.hi=a_256_bit.lo;
-        a_256_bit.lo=zero_128;
+        a_256_bit.lo=uint128_0;
         LEFT_SHIFT_256(a_256_bit,b_256_bit,n-128);
     }
-    if (n == 0)
-    {
+    if (n == 0) {
        b_256_bit->hi=a_256_bit.hi;
        b_256_bit->lo=a_256_bit.lo;
     } 
-    if (n<128)
-    {   uint128_t shift_temp={.hi=0, .lo=0};
+    if (n<128) {
+        uint128_t shift_temp=uint128_0;
         LEFT_SHIFT_128(a_256_bit.lo,&shift_temp,n);
         b_256_bit->lo=shift_temp;   
-        uint128_t shift_temp_or_left={.hi=0, .lo=0};
-        uint128_t shift_temp_or_right={.hi=0, .lo=0};
+        uint128_t shift_temp_or_left=uint128_0;
+        uint128_t shift_temp_or_right=uint128_0;
         LEFT_SHIFT_128(a_256_bit.hi,&shift_temp_or_left,n);
         RIGHT_SHIFT_128(a_256_bit.lo,&shift_temp_or_right,128-n);
         b_256_bit->hi=OR_128(shift_temp_or_left,shift_temp_or_right);
     }
-#endif
 }
 
 static inline void RIGHT_SHIFT_256(uint256_t a_256_bit,uint256_t* b_256_bit,int n){
     assert (n <= 256);
-
-#ifdef DAP_GLOBAL_IS_INT128
-    if (n >= 128) {   
+    if (n >= 128) { // shifting 64-bit integer by more than 63 bits is not defined   
         a_256_bit.lo=a_256_bit.hi;
-        a_256_bit.hi=0;
+        a_256_bit.hi=uint128_0;
         RIGHT_SHIFT_256(a_256_bit,b_256_bit,n-128);
     }
     if (n == 0) {
        b_256_bit->hi=a_256_bit.hi;
        b_256_bit->lo=a_256_bit.lo;
     } 
-    else {
-        uint64_t shift_temp;
-        shift_temp=a_256_bit.hi>>n;
-        b_256_bit->hi=shift_temp;
-        b_256_bit->lo=(a_256_bit.lo>>n)|(a_256_bit.hi<<(128-n));
-    }
-
-#else 
-    if (n >= 128) // shifting 64-bit integer by more than 63 bits is not defined
-    {   
-        a_256_bit.lo=a_256_bit.hi;
-        a_256_bit.hi=zero_128;
-        RIGHT_SHIFT_256(a_256_bit,b_256_bit,n-128);
-    }
-    if (n == 0)
-    {
-       b_256_bit->hi=a_256_bit.hi;
-       b_256_bit->lo=a_256_bit.lo;
-    } 
-    if (n<128)
-    {   uint128_t shift_temp={.hi=0, .lo=0};
+    if (n<128) {
+        uint128_t shift_temp=uint128_0;
         RIGHT_SHIFT_128(a_256_bit.hi,&shift_temp,n);
         b_256_bit->hi=shift_temp;   
-        uint128_t shift_temp_or_left={.hi=0, .lo=0};
-        uint128_t shift_temp_or_right={.hi=0, .lo=0};
+        uint128_t shift_temp_or_left=uint128_0;
+        uint128_t shift_temp_or_right=uint128_0;
         RIGHT_SHIFT_128(a_256_bit.lo,&shift_temp_or_left,n);
         LEFT_SHIFT_128(a_256_bit.hi,&shift_temp_or_right,128-n);
         b_256_bit->lo=OR_128(shift_temp_or_left,shift_temp_or_right);
     }
-#endif
 }
 
 static inline void INCR_128(uint128_t *a_128_bit){
@@ -364,7 +313,7 @@ static inline void INCR_256(uint256_t* a_256_bit){
 
 #else 
     INCR_128(&a_256_bit->lo);
-    if(EQUAL_128(a_256_bit->lo, zero_128))
+    if(EQUAL_128(a_256_bit->lo, uint128_0))
     {
         INCR_128(&a_256_bit->hi);
     }  
@@ -462,32 +411,12 @@ static inline int SUBTRACT_128_128(uint128_t a_128_bit, uint128_t b_128_bit, uin
 }
 
 
-// static inline int SUBTRACT_256_256(uint256_t a_256_bit, uint256_t b_256_bit,uint256_t* c_256_bit){
-//     int carry=0;
-//     carry=SUBTRACT_128_128(a_256_bit.lo, b_256_bit.lo, &c_256_bit->lo);
-//     uint64_t carry_64=carry;
-//     uint128_t carry_128={.hi=0,.lo=carry_64};
-//     uint128_t intermediate_val={.hi=0,.lo=0};
-//     int dummy_overflow=0;
-//     dummy_overflow=SUM_128_128(b_256_bit.hi,carry_128,&intermediate_val);
-//     carry=SUBTRACT_128_128(a_256_bit.hi, intermediate_val,&c_256_bit->hi );
-//     return carry;
-// }
-
-
 //
 //Mixed precision: add a uint128_t into a uint256_t
 static inline int ADD_128_INTO_256(uint128_t a_128_bit,uint256_t* c_256_bit) {
     int overflow_flag=0;
-
-#ifdef DAP_GLOBAL_IS_INT128
-    uint128_t overflow_128=0;
-    uint128_t temp=0;
-#else
-    uint128_t overflow_128={.hi=0,.lo=0};
-    uint128_t temp={.hi=0,.lo=0};
-#endif
-
+    uint128_t overflow_128 = uint128_0;
+    uint128_t temp = uint128_0;
     temp=c_256_bit->lo;
     overflow_flag=SUM_128_128(a_128_bit,temp,&c_256_bit->lo);
 
@@ -542,8 +471,7 @@ static inline int SUBTRACT_256_256(uint256_t a_256_bit,uint256_t b_256_bit,uint2
     underflow_flag=carry;
     return underflow_flag;
 
-#else    
-//(u64 rd[4], const u64 ad[4], const u64 bd[4])
+#else
     uint64_t t, r, borrow;
 
     t = a_256_bit.lo.lo;
@@ -579,8 +507,8 @@ static inline int SUBTRACT_256_256(uint256_t a_256_bit,uint256_t b_256_bit,uint2
 //Mixed precision: add a uint256_t into a uint512_t
 static inline int ADD_256_INTO_512(uint256_t a_256_bit,uint512_t* c_512_bit) {
     int overflow_flag=0;
-    uint256_t overflow_256={.hi=zero_128,.lo=zero_128};
-    uint256_t temp={.hi=zero_128,.lo=zero_128};
+    uint256_t overflow_256=uint256_0;
+    uint256_t temp=uint256_0;
     temp=c_512_bit->lo;
     overflow_flag=SUM_256_256(a_256_bit,temp,&c_512_bit->lo);
 #ifdef DAP_GLOBAL_IS_INT128
@@ -685,10 +613,10 @@ static inline int MULT_128_128(uint128_t a_128_bit, uint128_t b_128_bit, uint128
     overflow_flag=(a_128_bit>((uint128_t)-1)/b_128_bit);
 #else
     int equal_flag=0;
-    uint256_t full_product_256={.hi=zero_128, .lo=zero_128};
+    uint256_t full_product_256={.hi=uint128_0, .lo=uint128_0};
     MULT_128_256(a_128_bit,b_128_bit,&full_product_256);
     *c_128_bit=full_product_256.lo;
-    equal_flag=EQUAL_128(full_product_256.hi,zero_128);
+    equal_flag=EQUAL_128(full_product_256.hi,uint128_0);
     if (!equal_flag) {
         overflow_flag=1;
     }
@@ -770,12 +698,12 @@ static inline void MULT_256_512(uint256_t a_256_bit,uint256_t b_256_bit,uint512_
     MULT_128_256(a_256_bit.lo,b_256_bit.lo, &c_512_bit->lo);
 
     //cross product of .hi and .lo terms
-    uint256_t cross_product_first_term={ .hi = zero_128, .lo = zero_128};
-    uint256_t cross_product_second_term={ .hi = zero_128, .lo = zero_128};
-    uint256_t cross_product={ .hi = zero_128, .lo = zero_128};
-    uint256_t cross_product_shift_128={ .hi = zero_128, .lo = zero_128};
-    uint256_t c_512_bit_lo_copy={ .hi = zero_128, .lo = zero_128};
-    uint256_t c_512_bit_hi_copy={ .hi = zero_128, .lo = zero_128};
+    uint256_t cross_product_first_term=uint256_0;
+    uint256_t cross_product_second_term=uint256_0;
+    uint256_t cross_product=uint256_0;
+    uint256_t cross_product_shift_128=uint256_0;
+    uint256_t c_512_bit_lo_copy=uint256_0;
+    uint256_t c_512_bit_hi_copy=uint256_0;
     int overflow=0;
 
     MULT_128_256(a_256_bit.hi,b_256_bit.lo,&cross_product_first_term);
@@ -787,8 +715,8 @@ static inline void MULT_256_512(uint256_t a_256_bit,uint256_t b_256_bit,uint512_
     c_512_bit_lo_copy=c_512_bit->lo; 
     dummy_overflow=SUM_256_256(c_512_bit_lo_copy,cross_product_shift_128,&c_512_bit->lo);    
  
-    cross_product_shift_128.hi = zero_128; 
-    cross_product_shift_128.lo = zero_128;
+    cross_product_shift_128.hi = uint128_0; 
+    cross_product_shift_128.lo = uint128_0;
     RIGHT_SHIFT_256(cross_product,&cross_product_shift_128,128);
     c_512_bit_hi_copy=c_512_bit->hi;    
     dummy_overflow=SUM_256_256(c_512_bit_hi_copy,cross_product_shift_128,&c_512_bit->hi);
@@ -797,10 +725,10 @@ static inline void MULT_256_512(uint256_t a_256_bit,uint256_t b_256_bit,uint512_
 static inline int MULT_256_256(uint256_t a_256_bit,uint256_t b_256_bit,uint256_t* accum_256_bit){
     int overflow=0; 
     int equal_flag=0;
-    uint512_t full_product_512={.hi=zero_256,.lo=zero_256,};
+    uint512_t full_product_512={.hi=uint256_0,.lo=uint256_0,};
     MULT_256_512(a_256_bit,b_256_bit,&full_product_512);
     *accum_256_bit=full_product_512.lo;
-    equal_flag=EQUAL_256(full_product_512.hi,zero_256);
+    equal_flag=EQUAL_256(full_product_512.hi,uint256_0);
     if (!equal_flag)
     {
         overflow=1;
@@ -883,17 +811,24 @@ static inline int MULT_256_256(uint256_t a_256_bit,uint256_t b_256_bit,uint256_t
 // }
 
 //#ifndef DAP_GLOBAL_IS_INT128
-
-static inline int compare128(uint128_t N1, uint128_t N2)
+// > ret 1
+// == ret 0
+// < ret -1
+static inline int compare128(uint128_t a, uint128_t b)
 {
 #ifdef DAP_GLOBAL_IS_INT128
-    return ( N1 > N2 ? 1 : 0 ) - ( N1 < N2 ? 1 : 0 );
+    return ( a > b ? 1 : 0 ) - ( a < b ? 1 : 0 );
 #else
-    return    (((N1.hi > N2.hi) || ((N1.hi == N2.hi) && (N1.lo > N2.lo))) ? 1 : 0) 
-         -    (((N1.hi < N2.hi) || ((N1.hi == N2.hi) && (N1.lo < N2.lo))) ? 1 : 0);
+    return    (((a.hi > b.hi) || ((a.hi == b.hi) && (a.lo > b.lo))) ? 1 : 0) 
+         -    (((a.hi < b.hi) || ((a.hi == b.hi) && (a.lo < b.lo))) ? 1 : 0);
 #endif
 }
 
+static inline int compare256(uint256_t a, uint256_t b)
+{
+    return    (( compare128(a.hi, b.hi) == 1 || (compare128(a.hi, b.hi) == 0 && compare128(a.lo, b.lo) == 1)) ? 1 : 0) 
+         -    (( compare128(a.hi, b.hi) == -1 || (compare128(a.hi, b.hi) == 0 && compare128(a.lo, b.lo) == -1)) ? 1 : 0);
+}
 
 static inline int nlz64(uint64_t N)
 {
@@ -928,7 +863,6 @@ static inline int nlz64(uint64_t N)
     return C;
 }
 
-//static inline size_t nlz128(uint128_t N)
 static inline int nlz128(uint128_t N)
 {
 #ifdef DAP_GLOBAL_IS_INT128
@@ -938,69 +872,124 @@ static inline int nlz128(uint128_t N)
 #endif
 }
 
-// void shiftleft128(uint128_t N, unsigned S, uint128_t* A)
-// {
-//     uint64_t M1, M2;
-//     S &= 127;
-
-//     M1 = ((((S + 127) | S) & 64) >> 6) - 1llu;
-//     M2 = (S >> 6) - 1llu;
-//     S &= 63;
-//     A->hi = (N.lo << S) & (~M2);
-//     A->lo = (N.lo << S) & M2;
-//     A->hi |= ((N.hi << S) | ((N.lo >> (64 - S)) & M1)) & M2;
-// }
+static inline int nlz256(uint256_t N)
+{
+    return EQUAL_128(N.hi, uint128_0) ? nlz128(N.lo) + 128 : nlz128(N.hi);
+}
 
-// void shiftright128(uint128_t N, unsigned S, uint128_t* A)
-// {
-//     uint64_t M1, M2;
-//     S &= 127;
-
-//     M1 = ((((S + 127) | S) & 64) >> 6) - 1llu;
-//     M2 = (S >> 6) - 1llu;
-//     S &= 63;
-//     A->lo = (N.hi >> S) & (~M2);
-//     A->hi = (N.hi >> S) & M2;
-//     A->lo |= ((N.lo >> S) | ((N.hi << (64 - S)) & M1)) & M2;
-// } 
-
-// void sub128(uint128_t* Ans, uint128_t N, uint128_t M)
-// {
-//     Ans->lo = N.lo - M.lo;
-//     uint64_t C = (((Ans->lo & M.lo) & 1) + (M.lo >> 1) + (Ans->lo >> 1)) >> 63;
-//     Ans->hi = N.hi - (M.hi + C);
-// }
-// void bindivmod128(uint128_t M, uint128_t N, uint128_t* Q, uint128_t* R)
-// {
-//     Q->hi = Q->lo = 0;
-//     size_t Shift = nlz128(N) - nlz128(M);
-//     shiftleft128(N, Shift, &N);
-
-//     do
-//     {
-//         shiftleft128(*Q, 1, Q);
-//         if(compare128(M, N) >= 0)
-//         {
-//             sub128(&M, N, M);
-//             Q->lo |= 1;
-//         }
-
-//         shiftright128(N, 1, &N);
-//     }while(Shift-- != 0);
-
-//     R->hi = M.hi;
-//     R->lo = M.lo;
-// }
 
-//#ifdef DAP_GLOBAL_IS_INT128
-//#else
+#ifndef DAP_GLOBAL_IS_INT128
+static inline int fls128(uint128_t n) {
+    if ( n.hi != 0 ) {
+        return 127 - nlz64(n.hi);
+    }
+    return 63 - nlz64(n.lo);
+}
+
+static inline void divmod_impl_128(uint128_t a_dividend, uint128_t a_divisor, uint128_t *a_quotient, uint128_t *a_remainder)
+{
+    assert( compare128(a_divisor, uint128_0) ); // a_divisor != 0
+    if ( compare128(a_divisor, a_dividend) == 1 ) { // a_divisor > a_dividend
+        *a_quotient = uint128_0;
+        *a_remainder = a_dividend;
+        return;
+    }
+    if ( compare128(a_divisor, a_dividend) == 0 ) { // a_divisor == a_dividend
+        *a_quotient = uint128_1;
+        *a_remainder = uint128_0;
+        return;
+    }
+
+    uint128_t l_denominator = a_divisor;
+    uint128_t l_quotient = uint128_0;    
+    int l_shift = fls128(a_dividend) - fls128(l_denominator);
+
+    LEFT_SHIFT_128(l_denominator, &l_denominator, l_shift);
+
+    for (int i = 0; i <= l_shift; ++i) {
+        LEFT_SHIFT_128(l_quotient, &l_quotient, 1);
+
+        if( compare128(a_dividend, l_denominator) >= 0 ) {
+            SUBTRACT_128_128(a_dividend, l_denominator, &a_dividend);
+            l_quotient = OR_128(l_quotient, uint128_1);  //l_quotient.lo |= 1;
+        }
+        RIGHT_SHIFT_128(l_denominator, &l_denominator, 1);
+    }
+    *a_quotient = l_quotient;
+    *a_remainder = a_dividend;
+}
+#endif
+
+
+static inline int fls256(uint256_t n) {
+    if ( compare128(n.hi, uint128_0) != 0 ) {
+        return 255 - nlz128(n.hi);
+    }
+    return 127 - nlz128(n.lo);
+}
+
+static inline void divmod_impl_256(uint256_t a_dividend, uint256_t a_divisor, uint256_t *a_quotient, uint256_t *a_remainder)
+{
+    assert( compare256(a_divisor, uint256_0) ); // a_divisor != 0
+    if ( compare256(a_divisor, a_dividend) == 1 ) { // a_divisor > a_dividend
+        *a_quotient = uint256_0;
+        *a_remainder = a_dividend;
+        return;
+    }
+    if ( compare256(a_divisor, a_dividend) == 0 ) { // a_divisor == a_dividend
+        *a_quotient = uint256_1;
+        *a_remainder = uint256_0;
+        return;
+    }
+
+    uint256_t l_denominator = a_divisor;
+    uint256_t l_quotient = uint256_0;    
+    // int l_shift = nlz256(a_dividend) - nlz256(l_denominator);
+    int l_shift = fls256(a_dividend) - fls256(l_denominator);
+    LEFT_SHIFT_256(l_denominator, &l_denominator, l_shift);
+
+    for (int i = 0; i <= l_shift; ++i) {
+        LEFT_SHIFT_256(l_quotient, &l_quotient, 1);
+
+        if( compare256(a_dividend, l_denominator) >= 0 ) {
+            SUBTRACT_256_256(a_dividend, l_denominator, &a_dividend);
+            l_quotient = OR_256(l_quotient, uint256_1); 
+        }
+        RIGHT_SHIFT_256(l_denominator, &l_denominator, 1);
+    }
+    *a_quotient = l_quotient;
+    *a_remainder = a_dividend;
+}
+
+
+static inline void DIV_128(uint128_t a_128_bit, uint128_t b_128_bit, uint128_t* c_128_bit){
+    uint128_t l_ret = uint128_0;
+#ifdef DAP_GLOBAL_IS_INT128
+    l_ret = a_128_bit / b_128_bit;
+#else
+    uint128_t l_remainder = uint128_0;
+    divmod_impl_128(a_128_bit, b_128_bit, &l_ret, &l_remainder);
+#endif
+    *c_128_bit = l_ret;
+}
+
+static inline void DIV_256(uint256_t a_256_bit, uint256_t b_256_bit, uint256_t* c_256_bit){
+    uint256_t l_ret = uint256_0;
+    uint256_t l_remainder = uint256_0;
+    divmod_impl_256(a_256_bit, b_256_bit, &l_ret, &l_remainder);
+    *c_256_bit = l_ret;
+}
+
+
+//
+// dap_uint128_substract, dap_uint128_add, dap_uint128_check_equal - temporarily, for compatibility
 static inline uint128_t dap_uint128_substract(uint128_t a, uint128_t b)
 {
     // if (a < b) {
     //     return 0;
     // }
     // return a - b;
-    uint128_t c = zero_128;
+    uint128_t c = uint128_0;
     SUBTRACT_128_128(a, b, &c);
     return c;
 }
@@ -1018,7 +1007,7 @@ static inline uint128_t dap_uint128_add(uint128_t a, uint128_t b)
     //     return 0;
     // }
     // return l_ret;
-    uint128_t c = zero_128;
+    uint128_t c = uint128_0;
     SUM_128_128( a, b, &c);
     return c;
 }
@@ -1034,4 +1023,3 @@ static inline bool dap_uint128_check_equal(uint128_t a, uint128_t b)
     //return a == b;
     return EQUAL_128(a, b);
 }
-//#endif
diff --git a/dap-sdk/core/test/uint256_t/unit_test.cpp b/dap-sdk/core/test/uint256_t/unit_test.cpp
index ac4371c00f..064d0810b9 100644
--- a/dap-sdk/core/test/uint256_t/unit_test.cpp
+++ b/dap-sdk/core/test/uint256_t/unit_test.cpp
@@ -39,17 +39,17 @@ int main()
    
    int error_counter_sum_64_128=0;
     
-   uint128_t dap_test_128_shift={.hi=0, .lo=0}; 
-   uint128_t dap_test_128_one={.hi=0, .lo=0};
-   uint128_t dap_test_128_two={.hi=0, .lo=0};
-   uint128_t dap_test_128_sub={.hi=0, .lo=0};
-   uint256_t dap_test_256_one={.hi=zero_128, .lo=zero_128};
-   uint256_t dap_test_256_two={.hi=zero_128, .lo=zero_128};
-   uint256_t dap_test_256_sum={.hi=zero_128, .lo=zero_128}; 
-   uint256_t dap_test_256_sub={.hi=zero_128, .lo=zero_128}; 
-   uint256_t dap_test_256_prod={.hi=zero_128, .lo=zero_128};
-   uint256_t dap_test_256_shift={.hi=zero_128, .lo=zero_128};
-   uint512_t dap_test_512_prod={.hi=zero_256, .lo=zero_256};
+   uint128_t dap_test_128_shift=uint128_0; 
+   uint128_t dap_test_128_one=uint128_0;
+   uint128_t dap_test_128_two=uint128_0;
+   uint128_t dap_test_128_sub=uint128_0;
+   uint256_t dap_test_256_one=uint256_0;
+   uint256_t dap_test_256_two=uint256_0;
+   uint256_t dap_test_256_sum=uint256_0; 
+   uint256_t dap_test_256_sub=uint256_0; 
+   uint256_t dap_test_256_prod=uint256_0;
+   uint256_t dap_test_256_shift=uint256_0;
+   uint512_t dap_test_512_prod=uint512_0;
    int overflow_flag;
    int overflow_flag_prod;
    int borrow_flag_128;
@@ -308,8 +308,8 @@ if (division_enabled==1){
         prod_256_256_file << density_index << std::endl;}
 
         /////////////////////output of 256*256-->512//////////////////////
-        dap_test_512_prod.lo=zero_256;
-        dap_test_512_prod.hi=zero_256;
+        dap_test_512_prod.lo=uint256_0;
+        dap_test_512_prod.hi=uint256_0;
         uint256_t intermed_lo_prod;
         uint256_t intermed_hi_prod;
         MULT_128_256(dap_test_256_one.lo,dap_test_256_two.lo,&intermed_lo_prod);
@@ -442,8 +442,8 @@ if (division_enabled==1){
         dap_test_128_256_prod_one.hi=j;
         dap_test_128_256_prod_two.lo=max_64-(i+1);
         dap_test_128_256_prod_two.hi=max_64-2*(j+1);
-        dap_test_128_256_prod_prod.lo=zero_128;
-        dap_test_128_256_prod_prod.hi=zero_128;
+        dap_test_128_256_prod_prod.lo=uint128_0;
+        dap_test_128_256_prod_prod.hi=uint128_0;
         
         boost::multiprecision::uint256_t boost_test_128_256_prod;
         boost::multiprecision::uint128_t boost_test_128_256_one;
diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c
index 2e5879c897..9539f01355 100644
--- a/modules/chain/dap_chain_ledger.c
+++ b/modules/chain/dap_chain_ledger.c
@@ -132,11 +132,12 @@ typedef struct dap_chain_ledger_tx_bound {
     } in;
     union {
         dap_chain_tx_out_t *tx_prev_out;
-        dap_chain_256_tx_out_t *tx_prev_out_256; // 256
         dap_chain_tx_out_ext_t *tx_prev_out_ext;
-        dap_chain_256_tx_out_ext_t *tx_prev_out_ext_256; // 256
         dap_chain_tx_out_cond_t *tx_prev_out_cond;
-        dap_chain_256_tx_out_cond_t *tx_prev_out_cond_256; // 256
+        // 256
+        dap_chain_256_tx_out_t *tx_prev_out_256;
+        dap_chain_256_tx_out_ext_t *tx_prev_out_ext_256;
+        dap_chain_256_tx_out_cond_t *tx_prev_out_cond_256;
     } out;
     dap_chain_ledger_tx_item_t *item_out;
 } dap_chain_ledger_tx_bound_t;
@@ -2616,7 +2617,7 @@ uint128_t dap_chain_ledger_calc_balance(dap_ledger_t *a_ledger, const dap_chain_
 // #else
 //     uint128_t l_ret = {};
 // #endif
-    uint128_t l_ret = zero_128;
+    uint128_t l_ret = uint128_0;
 
     dap_ledger_wallet_balance_t *l_balance_item = NULL;// ,* l_balance_item_tmp = NULL;
     char *l_addr = dap_chain_addr_to_str(a_addr);
@@ -2646,7 +2647,7 @@ uint128_t dap_chain_ledger_calc_balance_full(dap_ledger_t *a_ledger, const dap_c
 // #else
 //     uint128_t balance = {0};
 // #endif
-    uint128_t balance = zero_128;
+    uint128_t balance = uint128_0;
 
     if(!a_addr || !dap_chain_addr_check_sum(a_addr))
         return balance;
diff --git a/modules/common/dap_chain_common.c b/modules/common/dap_chain_common.c
index 370cd38b86..f9d1e8180b 100644
--- a/modules/common/dap_chain_common.c
+++ b/modules/common/dap_chain_common.c
@@ -285,7 +285,7 @@ int dap_chain_addr_check_sum(const dap_chain_addr_t *a_addr)
 // 256
 uint128_t dap_chain_uint128_from_uint256(uint256_t a_from)
 {
-    if ( !( EQUAL_128(a_from.hi, zero_128) ) ) {
+    if ( !( EQUAL_128(a_from.hi, uint128_0) ) ) {
         log_it(L_ERROR, "Can't convert to uint128_t. It's too big.");
     }
     return a_from.lo;
diff --git a/modules/common/dap_chain_datum_tx.c b/modules/common/dap_chain_datum_tx.c
index 9349461c9c..7cb301e07e 100644
--- a/modules/common/dap_chain_datum_tx.c
+++ b/modules/common/dap_chain_datum_tx.c
@@ -122,7 +122,7 @@ uint64_t dap_chain_datum_tx_add_in_item_list(dap_chain_datum_tx_t **a_tx, dap_li
 uint256_t dap_chain_datum_256_tx_add_in_item_list(dap_chain_datum_tx_t **a_tx, dap_list_t *a_list_used_out)
 {
     dap_list_t *l_list_tmp = a_list_used_out;
-    uint256_t l_value_to_items = zero_256; // how many datoshi to transfer
+    uint256_t l_value_to_items = uint256_0; // how many datoshi to transfer
     while (l_list_tmp) {
         list_used_item_256_t *item = l_list_tmp->data;
         if (dap_chain_datum_tx_add_in_item(a_tx, &item->tx_hash_fast, item->num_idx_out) == 1) {
diff --git a/modules/common/include/dap_chain_common.h b/modules/common/include/dap_chain_common.h
index 38300c9415..68e85ce5a2 100644
--- a/modules/common/include/dap_chain_common.h
+++ b/modules/common/include/dap_chain_common.h
@@ -264,7 +264,7 @@ DAP_STATIC_INLINE uint128_t dap_chain_uint128_from(uint64_t a_from)
 //     uint128_t l_ret = {{ .0, a_from}};
 //     return l_ret;
 // #endif
-    uint128_t l_ret = zero_128;
+    uint128_t l_ret = uint128_0;
     ADD_64_INTO_128(a_from, &l_ret );
     return l_ret;
 }
@@ -275,8 +275,8 @@ uint128_t dap_chain_uint128_from_uint256(uint256_t a_from);
 // 256
 DAP_STATIC_INLINE uint256_t dap_chain_uint256_from(uint64_t a_from)
 {
-    uint128_t l_temp_128 = zero_128;
-    uint256_t l_ret_256 = zero_256;
+    uint128_t l_temp_128 = uint128_0;
+    uint256_t l_ret_256 = uint256_0;
     ADD_64_INTO_128(a_from, &l_temp_128);
     ADD_128_INTO_256(l_temp_128, &l_ret_256);
     return l_ret_256;
diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c
index f23209fd78..68f9099a5a 100644
--- a/modules/net/dap_chain_node_cli_cmd_tx.c
+++ b/modules/net/dap_chain_node_cli_cmd_tx.c
@@ -1321,7 +1321,7 @@ static char* dap_db_history_filter(dap_chain_t * a_chain, dap_ledger_t *a_ledger
         }
             break;
 
-            // emission
+        // emission
         case DAP_CHAIN_DATUM_TOKEN_EMISSION: {
             // datum out of page
             if(a_datum_start >= 0 && (l_datum_num+l_datum_num_global < (size_t)a_datum_start || l_datum_num+l_datum_num_global >= (size_t)a_datum_end)) {
@@ -1373,7 +1373,74 @@ static char* dap_db_history_filter(dap_chain_t * a_chain, dap_ledger_t *a_ledger
                 l_emission_num++;
             }
         }
-            break;
+        break;
+
+
+        // emission
+        case DAP_CHAIN_DATUM_256_TOKEN_EMISSION: {
+            // datum out of page
+            if(a_datum_start >= 0 && (l_datum_num+l_datum_num_global < (size_t)a_datum_start || l_datum_num+l_datum_num_global >= (size_t)a_datum_end)) {
+                 l_token_num++;
+                 break;
+            }
+            dap_chain_datum_256_token_emission_t *l_token_em = (dap_chain_datum_256_token_emission_t*) l_datum->data;
+            if(!a_filter_token_name || !dap_strcmp(l_token_em->hdr.ticker, a_filter_token_name)) {
+                char * l_token_emission_address_str = dap_chain_addr_to_str(&(l_token_em->hdr.address));
+                // filter for addr
+                if(dap_strcmp(a_filtr_addr_base58,l_token_emission_address_str)) {
+                     break;
+                }
+
+                // it is temporary :-)
+                uint256_t value_start = uint256_0;
+                uint256_t emission_value = uint256_0;
+                DIV_256(l_token_em->hdr.value, GET_256(DATOSHI_LD), &emission_value);
+
+                dap_string_append_printf(l_str_out, "emission: %.0Lf(%"DAP_UINT64_FORMAT_U") %s, type: %s, version: %d\n",
+                        dap_chain_uint128_from_uint256(emission_value),
+                        dap_chain_uint128_from_uint256(l_token_em->hdr.value),
+                        l_token_em->hdr.ticker,
+                        c_dap_chain_datum_token_emission_type_str[l_token_em->hdr.type],
+                        l_token_em->hdr.version);
+                dap_string_append_printf(l_str_out, "  to addr: %s\n", l_token_emission_address_str);
+
+                DAP_DELETE(l_token_emission_address_str);
+                switch (l_token_em->hdr.type) {
+                case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_UNDEFINED:
+                    break;
+                case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_AUTH:
+                    dap_string_append_printf(l_str_out, "  signs_count: %d\n", l_token_em->data.type_auth.signs_count);
+                    break;
+                case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ALGO:
+                    dap_string_append_printf(l_str_out, "  codename: %s\n", l_token_em->data.type_algo.codename);
+                    break;
+                case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ATOM_OWNER:
+                    
+                    // it is temporary :-)
+                    DIV_256(l_token_em->data.type_atom_owner.value_start, GET_256(DATOSHI_LD), &value_start);
+
+                    dap_string_append_printf(l_str_out, " value_start: %.0Lf(%"DAP_UINT64_FORMAT_U"), codename: %s\n",
+                            dap_chain_uint128_from_uint256(value_start),
+                            dap_chain_uint128_from_uint256(l_token_em->data.type_atom_owner.value_start),
+                            l_token_em->data.type_atom_owner.value_change_algo_codename);
+                    break;
+                case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_SMART_CONTRACT: {
+                    char *l_addr = dap_chain_addr_to_str(&l_token_em->data.type_presale.addr);
+                    // get time of create datum
+                    if(dap_time_to_str_rfc822(l_time_str, 71, l_token_em->data.type_presale.lock_time) < 1)
+                            l_time_str[0] = '\0';
+                    dap_string_append_printf(l_str_out, "  flags: 0x%x, lock_time: %s\n", l_token_em->data.type_presale.flags, l_time_str);
+                    dap_string_append_printf(l_str_out, "  addr: %s\n", l_addr);
+                    DAP_DELETE(l_addr);
+                }
+                    break;
+                }
+                dap_string_append_printf(l_str_out, "\n");
+                l_emission_num++;
+            }
+        }
+        break;
+
 
             // transaction
         case DAP_CHAIN_DATUM_TX:{
diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
index 7829cd030c..4f5d5d6252 100644
--- a/modules/type/blocks/dap_chain_cs_blocks.c
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -623,6 +623,10 @@ static int  s_add_atom_to_ledger(dap_chain_cs_blocks_t * a_blocks, dap_ledger_t
                 dap_chain_datum_token_emission_t *l_token_emission = (dap_chain_datum_token_emission_t*) l_datum->data;
                 l_ret=dap_chain_ledger_token_emission_load(a_ledger, l_token_emission, l_datum->header.data_size);
             } break;
+            case DAP_CHAIN_DATUM_256_TOKEN_EMISSION: { // 256
+                dap_chain_datum_256_token_emission_t *l_token_emission = (dap_chain_datum_256_token_emission_t*) l_datum->data;
+                l_ret=dap_chain_ledger_token_emission_load(a_ledger, l_token_emission, l_datum->header.data_size);
+            } break;
             case DAP_CHAIN_DATUM_TX: {
                 dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*) l_datum->data;
                 // Check tx correcntess
diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c
index 04436de8ec..6357613e3b 100644
--- a/modules/type/dag/dap_chain_cs_dag.c
+++ b/modules/type/dag/dap_chain_cs_dag.c
@@ -308,6 +308,11 @@ static int s_dap_chain_add_atom_to_ledger(dap_chain_cs_dag_t * a_dag, dap_ledger
             return dap_chain_ledger_token_emission_load(a_ledger, l_token_emission, l_datum->header.data_size);
         }
         break;
+        case DAP_CHAIN_DATUM_256_TOKEN_EMISSION: { // 256
+            dap_chain_datum_256_token_emission_t *l_token_emission = (dap_chain_datum_256_token_emission_t*) l_datum->data;
+            return dap_chain_ledger_token_emission_load(a_ledger, l_token_emission, l_datum->header.data_size);
+        }
+        break;
         case DAP_CHAIN_DATUM_TX: {
             dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*) l_datum->data;
             // don't save bad transactions to base
-- 
GitLab