From 2c276e21dd373ccab62b5f81ec25a07b60162c54 Mon Sep 17 00:00:00 2001
From: Roman Khlopkov <roman.khlopkov@demlabs.net>
Date: Fri, 18 Mar 2022 19:26:08 +0000
Subject: [PATCH] Support 5341++

---
 .gitmodules                                   |   2 +-
 .../plugins/customDatum/manifest.json         |   2 +-
 .../__pycache__/demoCustomCMD.cpython-39.pyc  | Bin 1043 -> 0 bytes
 .../plugins/demoCustomCMD/manifest.json       |   2 +-
 .../examples/plugins/demoOrder/manifest.json  |   2 +-
 .../demoServiceClient/demoServiceClient.py    |  49 ++++++++
 .../plugins/demoServiceClient/manifest.json   |   8 ++
 .../demoServiceServer/demoServiceServer.py    |  35 ++++++
 .../plugins/demoServiceServer/manifest.json   |   8 ++
 .../exampleCreateTx.cpython-39.pyc            | Bin 888 -> 0 bytes
 .../plugins/exampleCreateTx/manifest.json     |   2 +-
 .../chain/src/wrapping_dap_chain_ledger.c     |   4 +-
 .../include/wrapping_dap_chain_datum_tx.h     |   4 +-
 .../include/wrapping_dap_chain_tx_out.h       |   2 +-
 .../include/wrapping_dap_chain_tx_receipt.h   |   3 +-
 .../common/src/wrapping_dap_chain_datum_tx.c  |  21 ++--
 .../src/wrapping_dap_chain_tx_receipt.c       | 105 ++++++++++++------
 modules/dap-sdk/crypto/src/wrapping_cert.c    |  17 ++-
 .../dap-sdk/crypto/src/wrapping_dap_hash.c    |  11 +-
 19 files changed, 213 insertions(+), 64 deletions(-)
 delete mode 100644 dists/examples/plugins/demoCustomCMD/__pycache__/demoCustomCMD.cpython-39.pyc
 create mode 100644 dists/examples/plugins/demoServiceClient/demoServiceClient.py
 create mode 100644 dists/examples/plugins/demoServiceClient/manifest.json
 create mode 100644 dists/examples/plugins/demoServiceServer/demoServiceServer.py
 create mode 100644 dists/examples/plugins/demoServiceServer/manifest.json
 delete mode 100644 dists/examples/plugins/exampleCreateTx/__pycache__/exampleCreateTx.cpython-39.pyc

diff --git a/.gitmodules b/.gitmodules
index aedea207..7cf3b99a 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,4 +1,4 @@
 [submodule "cellframe-sdk"]
 	path = cellframe-sdk
-	url = https://gitlab.demlabs.net/cellframe/cellframe-sdk
+	url = ../cellframe-sdk
 	branch = master
diff --git a/dists/examples/plugins/customDatum/manifest.json b/dists/examples/plugins/customDatum/manifest.json
index 35a2c195..8a063a97 100644
--- a/dists/examples/plugins/customDatum/manifest.json
+++ b/dists/examples/plugins/customDatum/manifest.json
@@ -2,6 +2,6 @@
         "name": "customDatum",
         "version": "1.0",
         "author": "DEMLABS (C) 2021",
-        "dependencys": [],
+        "dependencies": [],
         "description": "This plugin does the work of the backend for the blockchain explorer."
 }
diff --git a/dists/examples/plugins/demoCustomCMD/__pycache__/demoCustomCMD.cpython-39.pyc b/dists/examples/plugins/demoCustomCMD/__pycache__/demoCustomCMD.cpython-39.pyc
deleted file mode 100644
index 30945060df00ff47bd9d7d39f2ff158f21cc9c04..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1043
zcmZuv&2G~`5Z+zescRAle+pdC3URSS8>tth3L%QCN;wc!O;14;a=qKs!rnFOO=&Fm
z6kY?VJ@OE|h_9S@g<fEG)1Opgq#e)LJN~};X5vmKKw!TvpB?^i5&CVCWh0Qhhf}@=
z#}LCA%JCTIWK1w(ggM{Q*kLa7;OVj!TY;y?{1FOQ|3C!_NpmlglYt&eohH0#Zxuz9
zr6aCRxJu05uMN<V2PcA4?to+XjA*2Bjplfcx6#3?Gp8nuXi__K+(XRip&HfBa|E&5
zLvPR-`P$Xaxm%MOUl@J}czDCAy`?78oC{sj&7g8)HThII2b;9PLFhG}ip7LCPR2#!
zlv*hVz?*i-^&T&>**-tjq1%|Mlctjj#!p9D*-ubvZZtUkiBt!wE<f~Tq5BEXvLhAe
zd`(Ek`zNvLXX#<T$flE2lzql?8BI$q^XTLD-E6&>H7iNZw&BXE5yA(Du#3C+B~}k0
zzN4AZ&*)|~>q4N>Ic9jNdorw^4rrO?MaHQCrisk+Sg?@TK9vE0*nlas3bv1hyANsO
zU$NOR;H4cHRt748bH`ecSt4dtG>mVKF^uorjLc!MBp2>g?rFO!CSR<|uzIpL6(SWA
zx)6y<#khiv0>)K4T2Qw9t2Cfs`^RZ{-3o;;6`I3n7}e5V6EMhFbE=Oy{U+5HDvxMl
zHNUMA_G<*g+A+hTTe|~#Bo*DA>0>F@16X8$->4pscp?S6DYT?s+|mGet1PHWH7_-^
z5hx5Igq|{jS)s=r5OSb-9w`pQ>@2O0OM;sfQdV_06{&s%X=$WJ*k1`S`Rlq1uO7m?
nVc2RqK>71c1GivHe>YeE3*o=bC7Wjaoncy<;dOn#<vafX0!Z~*

diff --git a/dists/examples/plugins/demoCustomCMD/manifest.json b/dists/examples/plugins/demoCustomCMD/manifest.json
index bf34c363..4e4f290d 100644
--- a/dists/examples/plugins/demoCustomCMD/manifest.json
+++ b/dists/examples/plugins/demoCustomCMD/manifest.json
@@ -2,7 +2,7 @@
         "name": "demoCustomCMD",
         "version": "1.0",
         "author": "DEMLABS (C) 2022",
-        "dependencys": [],
+        "dependencies": [],
         "description": "This is a plugin example for working custom command."
 }
 
diff --git a/dists/examples/plugins/demoOrder/manifest.json b/dists/examples/plugins/demoOrder/manifest.json
index 5ce8cb56..561d9e75 100644
--- a/dists/examples/plugins/demoOrder/manifest.json
+++ b/dists/examples/plugins/demoOrder/manifest.json
@@ -2,7 +2,7 @@
         "name": "demoOrder",
         "version": "1.0",
         "author": "DEMLABS (C) 2022",
-        "dependencys": [],
+        "dependencies": [],
         "description": "This is a plugin with examples for working with orders."
 }
 
diff --git a/dists/examples/plugins/demoServiceClient/demoServiceClient.py b/dists/examples/plugins/demoServiceClient/demoServiceClient.py
new file mode 100644
index 00000000..e46df06b
--- /dev/null
+++ b/dists/examples/plugins/demoServiceClient/demoServiceClient.py
@@ -0,0 +1,49 @@
+from API_CellFrame import ChainNetSrvClient, logIt, NOTICE, WARNING, ChainNet, ChainNetSrvUID, Cert, ChainTxReceipt, ChainHashFast
+
+def callback_connected(serviceClient, arg):
+    logIt(NOTICE, "Python client connected")
+    ch_uid = ChainNetSrvUID(123)
+    net = ChainNet.byName("private")
+    #serviceClient.write(ch_uid, "Greetings from test client".encode('utf-8'))
+    #serviceClient.check(net, ch_uid, "Any data".encode('utf-8'))
+    condHash = ChainHashFast.fromString("0xAF14CB70DB383A4FB840F8BD531A7B58C300B65AD3B3F418DC0713B0F6648643");
+    serviceClient.request(net, ch_uid, condHash)
+
+def callback_disconnected(serviceClient, arg):
+    logIt(NOTICE, "Python client disconnected")
+
+def callback_deleted(serviceClient, arg):
+    logIt(NOTICE, "Python client deleted")
+
+def callback_check(serviceClient, arg):
+    logIt(NOTICE, "Python client successfully checked the service")
+
+def callback_sign(serviceClient, txCondRec, arg):
+    logIt(NOTICE, "Siging receipt by python client")
+    signCert = Cert.load("svc_client")
+    return txCondRec.sign(signCert)
+
+def callback_success(serviceClient, txCondHash, arg):
+    logIt(NOTICE, "Python client successfully requested the service")
+
+def callback_error(serviceClient, errorNum, arg):
+    logIt(WARNING, f"Python client got error {errorNum:#x}")
+
+def callback_data(serviceClient, data, arg):
+    logIt(NOTICE, f"Python client custom data read back \'{data.decode('utf-8')}\'")
+
+def init():
+    logIt(NOTICE, "Init demoClient")
+#    Command for working cmd client
+#    AppCliServer.cmdItemCreate("myClient", clientCMD, "Command for working cmd",
+    net = ChainNet.byName("private")
+    client = ChainNetSrvClient(net, "127.0.0.1", 8089, callback_connected,
+                                                       callback_disconnected,
+                                                       callback_deleted,
+                                                       callback_check,
+                                                       callback_sign,
+                                                       callback_success,
+                                                       callback_error,
+                                                       callback_data,
+                                                       0)
+    return 0
diff --git a/dists/examples/plugins/demoServiceClient/manifest.json b/dists/examples/plugins/demoServiceClient/manifest.json
new file mode 100644
index 00000000..906a4710
--- /dev/null
+++ b/dists/examples/plugins/demoServiceClient/manifest.json
@@ -0,0 +1,8 @@
+{ 
+        "name": "demoServiceClient",
+        "version": "1.0",
+        "author": "DEMLABS (C) 2022",
+        "dependencies": [],
+        "description": "This plugin have demo service client."
+}
+
diff --git a/dists/examples/plugins/demoServiceServer/demoServiceServer.py b/dists/examples/plugins/demoServiceServer/demoServiceServer.py
new file mode 100644
index 00000000..67ba1f87
--- /dev/null
+++ b/dists/examples/plugins/demoServiceServer/demoServiceServer.py
@@ -0,0 +1,35 @@
+from API_CellFrame import logItInfo, logItNotice, logItWarning, ChainNet, ChainNetSrv, ChainNetSrvUID
+
+def requested(srv, usage_id, client_remote, data):
+    logItInfo("[server] func requested")
+    return 0
+
+def response_success(srv, usage_id, client_remote, data):
+    logItNotice("[server] func response success")
+    return 0
+
+def response_error(srv, usage_id, client_remote, data):
+    logItWarning("[server] func response error")
+
+def next_success(srv, usage_id, client_remote, data):
+    logItNotice("[server] func next success")
+    return 0
+
+def custom_data(srv, usage_id, client_remote, data):
+    logItNotice("[server] Input data: " + data.decode("utf-8"))
+    return data
+
+
+def init():
+    logItNotice("Init demoServer")
+    ch_uid = ChainNetSrvUID(123)
+    srv_object = ChainNetSrv(
+        ch_uid,
+        "py_service",
+        requested,
+        response_success,
+        response_error,
+        next_success,
+        custom_data
+    )
+    return 0
diff --git a/dists/examples/plugins/demoServiceServer/manifest.json b/dists/examples/plugins/demoServiceServer/manifest.json
new file mode 100644
index 00000000..1dca7160
--- /dev/null
+++ b/dists/examples/plugins/demoServiceServer/manifest.json
@@ -0,0 +1,8 @@
+{ 
+        "name": "demoServiceServer",
+        "version": "1.0",
+        "author": "DEMLABS (C) 2022",
+        "dependencies": [],
+        "description": "This plugin is an example of a service server plugin."
+}
+
diff --git a/dists/examples/plugins/exampleCreateTx/__pycache__/exampleCreateTx.cpython-39.pyc b/dists/examples/plugins/exampleCreateTx/__pycache__/exampleCreateTx.cpython-39.pyc
deleted file mode 100644
index 7990e721a45d87bd5cf65a6c36790bff05fd7599..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 888
zcmZ8g&2AGh5cd9OlZG1<aq2Y^5Va~uMF`QRw6rCwR7wBLA=+JglTFs~;&s}lN>1fL
z(j(8oTlmU}SK!2WBcuvj9)F*`<C*zJ8`kSp1mkP?B8n`8erfV}m_R<lDqeyih!`1S
z1~!<9O=e+>+1O?dc9@G@0}+#0-x2nR-9-)OH+Z0itGqU4Ip>+GwT59jxd^k2N>$7F
z;7A5srZH9Zm`{>)a7g8mq)b)H4+HqhFVQX`BG#|{8#-qjRtr{<fRT_HG4IU<k_NHn
zXdT@f29oB|BK90Tm<vPNONTfQ#=@MNOP9ESthurDhzH09RGFJ2AFv~<%NnTwatT^^
z#9vg1xA2JvHB|%b3tI50h-rb>Zpu=Mejdu<U46wiG<mmyeKuPiY$~sqMt4+j4f31|
zDGW#%583hA+41=8)p%>L*X@ns7K?6<xA@&?zxSncf_toY-rm_gn-%TkLT>ZZIJg<f
zR`4krAM#Cdan8oUWq5iOb!7V+`MkfK$b&cC<aV3!oub$g+oN#Wz1$z3r=6eBh&ACr
zRH0=P78qsooKA$Rp&QMDkWuwyKxL`;-io`xPv}f}u<Ir$GbO^)9$q3i>q^n6;@Yat
zQU&a;i1K6I>;43K=#)@dV>-ir2(R?DFZN0(Ij*eEC{@mNm`y46%dMYK`U8ol5be)F
zljpJ-(=1B_<oRmC32k17qM4;pGtZ`jbW$|wZOHPBwge3&?cM&*U*|Jrr;}9b;)~~C
zkWn?(U{=eicUw<KtixT<sHpmG=cwO;s0TW#(Emay-Acq#PAy-lNa<8&`^Y?lTUB|_
QIGJYjgYJ5vAK5Vf0>kb0YXATM

diff --git a/dists/examples/plugins/exampleCreateTx/manifest.json b/dists/examples/plugins/exampleCreateTx/manifest.json
index 38a328aa..2aefaf88 100644
--- a/dists/examples/plugins/exampleCreateTx/manifest.json
+++ b/dists/examples/plugins/exampleCreateTx/manifest.json
@@ -2,7 +2,7 @@
         "name": "exampleCreateTx",
         "version": "1.0",
         "author": "DEMLABS (C) 2022",
-        "dependencys": [],
+        "dependencies": [],
         "description": "This plugin is an example of a service plugin."
 }
 
diff --git a/modules/cellframe-sdk/chain/src/wrapping_dap_chain_ledger.c b/modules/cellframe-sdk/chain/src/wrapping_dap_chain_ledger.c
index 5a62dbb3..d35cc2b1 100644
--- a/modules/cellframe-sdk/chain/src/wrapping_dap_chain_ledger.c
+++ b/modules/cellframe-sdk/chain/src/wrapping_dap_chain_ledger.c
@@ -196,7 +196,9 @@ PyObject *dap_chain_ledger_tx_cache_check_py(PyObject *self, PyObject *args){
         dap_list_t *l = pyListToDapList(obj);
         tx_out[i] = l;
     }
-    int res = dap_chain_ledger_tx_cache_check(((PyDapChainLedgerObject*)self)->ledger, ((PyDapChainDatumTxObject*)obj_datum_tx)->datum_tx, bound_items, tx_out);
+    int res = dap_chain_ledger_tx_cache_check(((PyDapChainLedgerObject*)self)->ledger,
+                                              ((PyDapChainDatumTxObject*)obj_datum_tx)->datum_tx,
+                                              false, bound_items, tx_out);
     return PyLong_FromLong(res);
 }
 PyObject *dap_chain_node_datum_tx_cache_check_py(PyObject *self, PyObject *args){
diff --git a/modules/cellframe-sdk/common/include/wrapping_dap_chain_datum_tx.h b/modules/cellframe-sdk/common/include/wrapping_dap_chain_datum_tx.h
index 747cfd3a..6afa0be4 100644
--- a/modules/cellframe-sdk/common/include/wrapping_dap_chain_datum_tx.h
+++ b/modules/cellframe-sdk/common/include/wrapping_dap_chain_datum_tx.h
@@ -58,12 +58,12 @@ typedef struct PyDapChainTxItemType{
 }PyDapChainTxItemTypeObject;
 
 PyObject *TX_ITEM_TYPE_IN_PY(void);
-PyObject *TX_ITEM_TYPE_OUT_OLD_PY(void);
+PyObject *TX_ITEM_TYPE_OUT_PY(void);
 PyObject *TX_ITEM_TYPE_PKEY_PY(void);
 PyObject *TX_ITEM_TYPE_SIG_PY(void);
 PyObject *TX_ITEM_TYPE_TOKEN_PY(void);
 PyObject *TX_ITEM_TYPE_IN_COND_PY(void);
-PyObject *TX_ITEM_TYPE_OUT_COND_OLD_PY(void);
+PyObject *TX_ITEM_TYPE_OUT_COND_PY(void);
 PyObject *TX_ITEM_TYPE_RECEIPT_PY(void);
 
 extern PyTypeObject DapChainTxItemObject_DapChainTxItemTypeObjectType;
diff --git a/modules/cellframe-sdk/common/include/wrapping_dap_chain_tx_out.h b/modules/cellframe-sdk/common/include/wrapping_dap_chain_tx_out.h
index 5dab6f2d..e9a839a2 100644
--- a/modules/cellframe-sdk/common/include/wrapping_dap_chain_tx_out.h
+++ b/modules/cellframe-sdk/common/include/wrapping_dap_chain_tx_out.h
@@ -35,7 +35,7 @@
 
 typedef struct PyDapChainTXOut{
     PyObject_HEAD
-    dap_chain_tx_out_old_t *tx_out;
+    dap_chain_tx_out_t *tx_out;
 }PyDapChainTXOutObject;
 
 PyObject *wrapping_dap_chain_tx_out_get_addr(PyObject *self, void *closure);
diff --git a/modules/cellframe-sdk/common/include/wrapping_dap_chain_tx_receipt.h b/modules/cellframe-sdk/common/include/wrapping_dap_chain_tx_receipt.h
index 528634ba..17cc8093 100644
--- a/modules/cellframe-sdk/common/include/wrapping_dap_chain_tx_receipt.h
+++ b/modules/cellframe-sdk/common/include/wrapping_dap_chain_tx_receipt.h
@@ -50,6 +50,7 @@ PyObject *wrapping_dap_chain_tx_receipt_get_units_type(PyObject *self, void *clo
 PyObject *wrapping_dap_chain_tx_receipt_get_value(PyObject *self, void *closure);
 PyObject *wrapping_dap_chain_tx_receipt_get_sig_provider(PyObject *self, void *closure);
 PyObject *wrapping_dap_chain_tx_receipt_get_sig_client(PyObject *self, void *closure);
+PyObject *wrapping_dap_chain_tx_receipt_sign(PyObject *self, PyObject *sign);
 
 extern PyTypeObject DapChainTxReceiptObject_DapChainTxReceiptTypeObjectType;
 
@@ -57,4 +58,4 @@ extern PyTypeObject DapChainTxReceiptObject_DapChainTxReceiptTypeObjectType;
 extern "C"{
 #endif
 
-#endif //_WRAPPING_DAP_CHAIN_TX_RECEIPT_
\ No newline at end of file
+#endif //_WRAPPING_DAP_CHAIN_TX_RECEIPT_
diff --git a/modules/cellframe-sdk/common/src/wrapping_dap_chain_datum_tx.c b/modules/cellframe-sdk/common/src/wrapping_dap_chain_datum_tx.c
index f9b309dc..102417f4 100644
--- a/modules/cellframe-sdk/common/src/wrapping_dap_chain_datum_tx.c
+++ b/modules/cellframe-sdk/common/src/wrapping_dap_chain_datum_tx.c
@@ -4,14 +4,13 @@
 
 PyMethodDef PyDapChainTxItemTypeObjectMethods[] ={
         {"TX_ITEM_TYPE_IN", (PyCFunction)TX_ITEM_TYPE_IN_PY, METH_NOARGS | METH_STATIC, ""},
-        {"TX_ITEM_TYPE_OUT_OLD", (PyCFunction)TX_ITEM_TYPE_OUT_OLD_PY, METH_NOARGS | METH_STATIC, ""},
+        {"TX_ITEM_TYPE_OUT", (PyCFunction)TX_ITEM_TYPE_OUT_PY, METH_NOARGS | METH_STATIC, ""},
         {"TX_ITEM_TYPE_PKEY", (PyCFunction)TX_ITEM_TYPE_PKEY_PY, METH_NOARGS | METH_STATIC, ""},
         {"TX_ITEM_TYPE_SIG", (PyCFunction)TX_ITEM_TYPE_SIG_PY, METH_NOARGS | METH_STATIC, ""},
         {"TX_ITEM_TYPE_TOKEN", (PyCFunction)TX_ITEM_TYPE_TOKEN_PY, METH_NOARGS | METH_STATIC, ""},
         {"TX_ITEM_TYPE_IN_COND", (PyCFunction)TX_ITEM_TYPE_IN_COND_PY, METH_NOARGS | METH_STATIC, ""},
-        {"TX_ITEM_TYPE_OUT_COND_OLD", (PyCFunction)TX_ITEM_TYPE_OUT_COND_OLD_PY, METH_NOARGS | METH_STATIC, ""},
-        {"TX_ITEM_TYPE_RECEIPT", (PyCFunction)TX_ITEM_TYPE_RECEIPT_PY,
-                METH_NOARGS | METH_STATIC, ""},
+        {"TX_ITEM_TYPE_OUT_COND", (PyCFunction)TX_ITEM_TYPE_OUT_COND_PY, METH_NOARGS | METH_STATIC, ""},
+        {"TX_ITEM_TYPE_RECEIPT", (PyCFunction)TX_ITEM_TYPE_RECEIPT_PY, METH_NOARGS | METH_STATIC, ""},
         {NULL, NULL, 0, NULL}
 };
 
@@ -60,8 +59,8 @@ PyTypeObject DapChainTxItemObject_DapChainTxItemTypeObjectType = {
 PyObject *TX_ITEM_TYPE_IN_PY(void){
     return PyLong_FromLong(TX_ITEM_TYPE_IN);
 }
-PyObject *TX_ITEM_TYPE_OUT_OLD_PY(void){
-        return PyLong_FromLong(TX_ITEM_TYPE_OUT_OLD);
+PyObject *TX_ITEM_TYPE_OUT_PY(void){
+        return PyLong_FromLong(TX_ITEM_TYPE_OUT);
 }
 PyObject *TX_ITEM_TYPE_PKEY_PY(void){
         return PyLong_FromLong(TX_ITEM_TYPE_PKEY);
@@ -75,8 +74,8 @@ PyObject *TX_ITEM_TYPE_TOKEN_PY(void){
 PyObject *TX_ITEM_TYPE_IN_COND_PY(void){
         return PyLong_FromLong(TX_ITEM_TYPE_IN_COND);
 }
-PyObject *TX_ITEM_TYPE_OUT_COND_OLD_PY(void){
-        return PyLong_FromLong(TX_ITEM_TYPE_OUT_COND_OLD);
+PyObject *TX_ITEM_TYPE_OUT_COND_PY(void){
+        return PyLong_FromLong(TX_ITEM_TYPE_OUT_COND);
 }
 PyObject *TX_ITEM_TYPE_RECEIPT_PY(void){
         return PyLong_FromLong(TX_ITEM_TYPE_RECEIPT);
@@ -333,9 +332,9 @@ PyObject *wrapping_dap_chain_datum_tx_get_items(PyObject *self, PyObject *args){
                 obj_tx_item = (PyObject*)PyObject_New(PyDapChainTXInObject, &DapChainTxInObject_DapChainTxInTypeObjectType);
                 ((PyDapChainTXInObject*)obj_tx_item)->tx_in = ((dap_chain_tx_in_t*)item);
                 break;
-            case TX_ITEM_TYPE_OUT_OLD:
+            case TX_ITEM_TYPE_OUT:
                 obj_tx_item = (PyObject*)PyObject_New(PyDapChainTXOutObject, &DapChainTxOutObject_DapChainTxOutTypeObjectType);
-                ((PyDapChainTXOutObject*)obj_tx_item)->tx_out = ((dap_chain_tx_out_old_t*)item);
+                ((PyDapChainTXOutObject*)obj_tx_item)->tx_out = ((dap_chain_tx_out_t*)item);
                 break;
             case TX_ITEM_TYPE_TOKEN:
                 obj_tx_item = (PyObject*)PyObject_New(PyDapChainTxTokenObject, &DapChainTxToken_DapChainTxTokenType);
@@ -361,7 +360,7 @@ PyObject *wrapping_dap_chain_datum_tx_get_items(PyObject *self, PyObject *args){
                 obj_tx_item = (PyObject*)PyObject_New(PyDapChainTXInCondObject, &DapChainTxInCondObject_DapChainTxInCondTypeObjectType);
                 ((PyDapChainTXInCondObject*)obj_tx_item)->tx_in_cond = (dap_chain_tx_in_cond_t*)item;
                 break;
-            case TX_ITEM_TYPE_OUT_COND_OLD:
+            case TX_ITEM_TYPE_OUT_COND:
                 switch (((dap_chain_tx_out_cond_t*)item)->header.subtype) {
                     case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY:
                         obj_tx_item = (PyObject*)PyObject_New(PyDapChainTxOutCondObject, &DapChainTxOutCondSubTypeSrvPay_DapChainTxOutCondSubTypeSrvPayObject);
diff --git a/modules/cellframe-sdk/common/src/wrapping_dap_chain_tx_receipt.c b/modules/cellframe-sdk/common/src/wrapping_dap_chain_tx_receipt.c
index ee6c57d6..d95ec5e6 100644
--- a/modules/cellframe-sdk/common/src/wrapping_dap_chain_tx_receipt.c
+++ b/modules/cellframe-sdk/common/src/wrapping_dap_chain_tx_receipt.c
@@ -1,4 +1,7 @@
 #include "wrapping_dap_chain_tx_receipt.h"
+#include "wrapping_cert.h"
+
+#define LOG_TAG "wrapping_dap_chain_tx_receipt"
 
 PyGetSetDef DapChainTxReceiptGetSetDefs[] = {
         {"size", (getter)wrapping_dap_chain_tx_receipt_get_size, NULL, NULL, NULL},
@@ -12,6 +15,11 @@ PyGetSetDef DapChainTxReceiptGetSetDefs[] = {
         {NULL}
 };
 
+PyMethodDef DapChainTxReceiptMethods[] = {
+        {"sign", (PyCFunction)wrapping_dap_chain_tx_receipt_sign, METH_VARARGS, ""},
+        {NULL, NULL, 0, NULL}
+};
+
 PyTypeObject DapChainTxReceiptObject_DapChainTxReceiptTypeObjectType = {
         PyVarObject_HEAD_INIT(NULL, 0)
         "CellFrame.ChainTxReceipt",        /* tp_name */
@@ -33,17 +41,17 @@ PyTypeObject DapChainTxReceiptObject_DapChainTxReceiptTypeObjectType = {
         0,                                  /* tp_setattro */
         0,                                  /* tp_as_buffer */
         Py_TPFLAGS_DEFAULT |
-        Py_TPFLAGS_BASETYPE,            /* tp_flags */
-        "Chain tx item receipt object",        /* tp_doc */
-        0,		                            /* tp_traverse */
-        0,		                            /* tp_clear */
-        0,		                            /* tp_richcompare */
+        Py_TPFLAGS_BASETYPE,                /* tp_flags */
+        "Chain tx item receipt object",     /* tp_doc */
+        0,                                  /* tp_traverse */
+        0,                                  /* tp_clear */
+        0,                                  /* tp_richcompare */
         0,                                  /* tp_weaklistoffset */
-        0,		                            /* tp_iter */
-        0,		                            /* tp_iternext */
-        0,  /* tp_methods */
+        0,                                  /* tp_iter */
+        0,                                  /* tp_iternext */
+        DapChainTxReceiptMethods,           /* tp_methods */
         0,                                  /* tp_members */
-        DapChainTxReceiptGetSetDefs,                                  /* tp_getset */
+        DapChainTxReceiptGetSetDefs,        /* tp_getset */
         0,                                  /* tp_base */
         0,                                  /* tp_dict */
         0,                                  /* tp_descr_get */
@@ -79,35 +87,66 @@ PyObject *wrapping_dap_chain_tx_receipt_get_value(PyObject *self, void *closure)
     (void)closure;
     return Py_BuildValue("k", ((PyDapChainTXReceiptObject*)self)->tx_receipt->receipt_info.value_datoshi);
 }
+
 PyObject *wrapping_dap_chain_tx_receipt_get_sig_provider(PyObject *self, void *closure){
-    (void)closure;
-    uint16_t l_exts_size = ((PyDapChainTXReceiptObject*)self)->tx_receipt->exts_size;
-    if (l_exts_size == sizeof(dap_sign_t) + sizeof(dap_sign_t) || l_exts_size == sizeof(dap_sign_t)){
-        PyObject *obj_sign_provider = _PyObject_New(&DapSignObject_DapSignObjectType);
-        obj_sign_provider = PyObject_Init(obj_sign_provider, &DapSignObject_DapSignObjectType);
-        PyObject_Dir(obj_sign_provider);
-        ((PyDapSignObject*)obj_sign_provider)->sign = DAP_NEW(dap_sign_t);
-        memcpy(
-                ((PyDapSignObject*)obj_sign_provider)->sign,
-                ((PyDapChainTXReceiptObject*)self)->tx_receipt->exts_n_signs,
-                sizeof(dap_sign_t));
-        return obj_sign_provider;
+    UNUSED(closure);
+    dap_chain_datum_tx_receipt_t *l_receipt = ((PyDapChainTXReceiptObject*)self)->tx_receipt;
+    uint64_t l_signs_size = l_receipt->size - l_receipt->exts_size;
+    if (l_signs_size) {
+        dap_sign_t *l_sign = (dap_sign_t *)&l_receipt->exts_n_signs[l_receipt->exts_size];
+        if (!dap_sign_verify_size(l_sign, l_signs_size))
+            return Py_None;
+        size_t l_sign_size = dap_sign_get_size(l_sign);
+        PyDapSignObject *obj_sign_provider = PyObject_New(PyDapSignObject, &DapSignObject_DapSignObjectType);
+        obj_sign_provider = (PyDapSignObject *)PyObject_Init((PyObject *)obj_sign_provider,
+                                                             &DapSignObject_DapSignObjectType);
+        PyObject_Dir((PyObject *)obj_sign_provider);
+        obj_sign_provider->sign = DAP_DUP_SIZE(l_sign, l_sign_size);
+        return (PyObject *)obj_sign_provider;
     }
     return Py_None;
 }
+
 PyObject *wrapping_dap_chain_tx_receipt_get_sig_client(PyObject *self, void *closure){
-    (void)closure;
-    uint16_t l_exts_size = ((PyDapChainTXReceiptObject*)self)->tx_receipt->exts_size;
-    if (l_exts_size == sizeof(dap_sign_t) + sizeof(dap_sign_t)){
-        PyObject *obj_sign_client = _PyObject_New(&DapSignObject_DapSignObjectType);
-        obj_sign_client = PyObject_Init(obj_sign_client, &DapSignObject_DapSignObjectType);
-        PyObject_Dir(obj_sign_client);
-        ((PyDapSignObject*)obj_sign_client)->sign = DAP_NEW(dap_sign_t);
-        memcpy(
-                ((PyDapSignObject*)obj_sign_client)->sign,
-               ((PyDapChainTXReceiptObject*)self)->tx_receipt->exts_n_signs + sizeof(dap_sign_t),
-               sizeof(dap_sign_t));
-        return obj_sign_client;
+    UNUSED(closure);
+    dap_chain_datum_tx_receipt_t *l_receipt = ((PyDapChainTXReceiptObject*)self)->tx_receipt;
+    uint64_t l_signs_size = l_receipt->size - l_receipt->exts_size;
+    if (l_signs_size) {
+        dap_sign_t *l_sign = (dap_sign_t *)&l_receipt->exts_n_signs[l_receipt->exts_size];
+        if (!dap_sign_verify_size(l_sign, l_signs_size))
+            return Py_None;
+        size_t l_sign_size = dap_sign_get_size(l_sign);
+        if (l_receipt->exts_size + l_sign_size >= l_receipt->size)
+            return Py_None;
+        l_sign = (dap_sign_t *)&l_receipt->exts_n_signs[l_receipt->exts_size + l_sign_size];
+        if (!dap_sign_verify_size(l_sign, l_signs_size - l_sign_size))
+            return Py_None;
+        l_sign_size = dap_sign_get_size(l_sign);
+        PyDapSignObject *obj_sign_client = PyObject_New(PyDapSignObject, &DapSignObject_DapSignObjectType);
+        obj_sign_client = (PyDapSignObject *)PyObject_Init((PyObject *)obj_sign_client,
+                                                             &DapSignObject_DapSignObjectType);
+        PyObject_Dir((PyObject *)obj_sign_client);
+        obj_sign_client->sign = DAP_DUP_SIZE(l_sign, l_sign_size);
+        return (PyObject *)obj_sign_client;
     }
     return Py_None;
 }
+
+PyObject *wrapping_dap_chain_tx_receipt_sign(PyObject *self, PyObject *sign) {
+    PyCryptoCertObject *obj_cert;
+    if (!PyArg_ParseTuple(sign, "O", &obj_cert)) {
+        log_it(L_ERROR, "Certificate for receipt signing not provided");
+        return Py_None;
+    }
+    if (!PyObject_TypeCheck(obj_cert, &g_crypto_cert_type_py)) {
+        log_it(L_ERROR, "Certificate for receipt signing has invalid object type");
+        return Py_None;
+    }
+    if (!obj_cert->cert || !obj_cert->cert->enc_key) {
+        log_it(L_ERROR, "Certificate for receipt signing has no cert object or private key");
+        return Py_None;
+    }
+    dap_chain_datum_tx_receipt_t *l_receipt = ((PyDapChainTXReceiptObject*)self)->tx_receipt;
+    ((PyDapChainTXReceiptObject*)self)->tx_receipt = dap_chain_datum_tx_receipt_sign_add(l_receipt, obj_cert->cert->enc_key);
+    return self;
+}
diff --git a/modules/dap-sdk/crypto/src/wrapping_cert.c b/modules/dap-sdk/crypto/src/wrapping_cert.c
index c11f8ac7..421b735a 100644
--- a/modules/dap-sdk/crypto/src/wrapping_cert.c
+++ b/modules/dap-sdk/crypto/src/wrapping_cert.c
@@ -200,11 +200,18 @@ PyObject* dap_cert_save_py(PyObject *self, PyObject *args)
 
 PyObject* dap_cert_load_py(PyObject *self, PyObject *args)
 {
-    (void) self;
-    (void) args;
-    /// TODO: Implement it!
-    PyErr_SetString(PyExc_TypeError, "Unimplemented function");
-    return NULL;
+    const char *l_cert_name;
+    if (!PyArg_ParseTuple(args, "s", &l_cert_name)) {
+        return Py_None;
+    }
+    dap_cert_t *l_ret = dap_cert_find_by_name(l_cert_name);
+    if (!l_ret)
+        return self;
+    if (!self) {
+        self = _PyObject_New(&g_crypto_cert_type_py);
+    }
+    ((PyCryptoCertObject *)self)->cert = l_ret;
+    return self;
 }
 
 PyObject* dap_cert_close_py(PyObject *self, PyObject *args)
diff --git a/modules/dap-sdk/crypto/src/wrapping_dap_hash.c b/modules/dap-sdk/crypto/src/wrapping_dap_hash.c
index 9e47c199..aa5b6122 100644
--- a/modules/dap-sdk/crypto/src/wrapping_dap_hash.c
+++ b/modules/dap-sdk/crypto/src/wrapping_dap_hash.c
@@ -62,7 +62,7 @@ PyObject *DAP_HASH_TYPE_SLOW_0_PY(){
 
 /* Chain hash fast */
 PyMethodDef DapHashFastMethods[] = {
-        {"strToHashFast", (PyCFunction)dap_chain_str_to_hash_fast_py, METH_VARARGS | METH_STATIC, ""},
+        {"fromString", (PyCFunction)dap_chain_str_to_hash_fast_py, METH_VARARGS | METH_STATIC, ""},
         {"hashFast", (PyCFunction)dap_hash_fast_py, METH_VARARGS, ""},
         {"compare", (PyCFunction)dap_hash_fast_compare_py, METH_VARARGS | METH_STATIC, ""},
         {"isBlank", (PyCFunction)dap_hash_fast_is_blank_py, METH_VARARGS, ""},
@@ -118,11 +118,12 @@ PyObject *dap_chain_str_to_hash_fast_py(PyObject *self, PyObject *args){
     const char *hash_str;
     if (!PyArg_ParseTuple(args, "s", &hash_str))
         return NULL;
-    PyDapHashFastObject *obj_hash_fast = PyObject_New(PyDapHashFastObject, &DapHashFastObject_DapHashFastObjectType);
-    PyObject_Dir((PyObject*)obj_hash_fast);
+    PyDapHashFastObject *obj_hash_fast = self ? (PyDapHashFastObject *)self :
+                                                 PyObject_New(PyDapHashFastObject, &DapHashFastObject_DapHashFastObjectType);
     obj_hash_fast->hash_fast = DAP_NEW(dap_hash_fast_t);
-    int res = dap_chain_hash_fast_from_str(hash_str, obj_hash_fast->hash_fast);
-    return Py_BuildValue("nO", res, (PyObject*)obj_hash_fast);
+    if (dap_chain_hash_fast_from_str(hash_str, obj_hash_fast->hash_fast))
+        DAP_DEL_Z(obj_hash_fast->hash_fast);
+    return (PyObject*)obj_hash_fast;
 }
 
 PyObject *dap_hash_fast_py(PyObject *self, PyObject *args){
-- 
GitLab