diff --git a/libdap-chain-cs-dag b/libdap-chain-cs-dag
deleted file mode 160000
index bbd281914143a492607a73000c47ff676d513860..0000000000000000000000000000000000000000
--- a/libdap-chain-cs-dag
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit bbd281914143a492607a73000c47ff676d513860
diff --git a/libdap-chain-cs-dag/.gitignore b/libdap-chain-cs-dag/.gitignore
new file mode 100755
index 0000000000000000000000000000000000000000..c6127b38c1aa25968a88db3940604d41529e4cf5
--- /dev/null
+++ b/libdap-chain-cs-dag/.gitignore
@@ -0,0 +1,52 @@
+# Prerequisites
+*.d
+
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+
+# Linker output
+*.ilk
+*.map
+*.exp
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+# Debug files
+*.dSYM/
+*.su
+*.idb
+*.pdb
+
+# Kernel Module Compile Results
+*.mod*
+*.cmd
+.tmp_versions/
+modules.order
+Module.symvers
+Mkfile.old
+dkms.conf
diff --git a/libdap-chain-cs-dag/CMakeLists.txt b/libdap-chain-cs-dag/CMakeLists.txt
new file mode 100755
index 0000000000000000000000000000000000000000..75dd7672d3e44f281aa8f77d5c6b8792bde6e405
--- /dev/null
+++ b/libdap-chain-cs-dag/CMakeLists.txt
@@ -0,0 +1,23 @@
+cmake_minimum_required(VERSION 2.8)
+project (dap_chain_cs_dag)
+  
+set(DAP_CHAIN_DAG_SRCS 
+  dap_chain_cs_dag.c 
+        dap_chain_cs_dag_event.c
+        )
+
+set(DAP_CHAIN_DAG_HEADERS
+        dap_chain_cs_dag.h
+        dap_chain_cs_dag_event.h
+    )
+
+if(WIN32)
+  include_directories(../3rdparty/wepoll/)
+  include_directories(../3rdparty/uthash/src/)
+endif()
+
+add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_DAG_SRCS} ${DAP_CHAIN_DAG_HEADERS})
+
+target_link_libraries(dap_chain_cs_dag dap_core dap_crypto dap_chain dap_chain_net dap_chain_crypto dap_chain_global_db)
+target_include_directories(dap_chain_cs_dag INTERFACE .)
+
diff --git a/libdap-chain-cs-dag/LICENSE b/libdap-chain-cs-dag/LICENSE
new file mode 100755
index 0000000000000000000000000000000000000000..94a9ed024d3859793618152ea559a168bbcbb5e2
--- /dev/null
+++ b/libdap-chain-cs-dag/LICENSE
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/libdap-chain-cs-dag/README.md b/libdap-chain-cs-dag/README.md
new file mode 100755
index 0000000000000000000000000000000000000000..9785952ad36d8f33dcf200524e83ff723598bb38
--- /dev/null
+++ b/libdap-chain-cs-dag/README.md
@@ -0,0 +1,2 @@
+# libdap-chain-dag
+Blockchain datum organized in Directed Acyclic Graph (DAG)
diff --git a/libdap-chain-cs-dag/dap_chain_cs_dag.c b/libdap-chain-cs-dag/dap_chain_cs_dag.c
new file mode 100755
index 0000000000000000000000000000000000000000..29a3887054113c5211d3fdec933c433ab9f705e0
--- /dev/null
+++ b/libdap-chain-cs-dag/dap_chain_cs_dag.c
@@ -0,0 +1,1292 @@
+/*
+ * Authors:
+ * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * Kelvin Project https://github.com/kelvinblockchain
+ * Copyright  (c) 2017-2018
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+    DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    DAP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <stdlib.h>
+#include <time.h>
+#include <pthread.h>
+#include "uthash.h"
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <windows.h>
+#include <mswsock.h>
+#include <ws2tcpip.h>
+#include <io.h>
+#include <time.h>
+#include <pthread.h>
+#endif
+
+#include "dap_common.h"
+#include "dap_string.h"
+#include "dap_strfuncs.h"
+#include "dap_hash.h"
+#include "dap_chain_datum.h"
+#include "dap_chain_cs.h"
+#include "dap_chain_cs_dag.h"
+#include "dap_chain_global_db.h"
+#include "dap_chain_node_cli.h"
+#include "dap_chain_cell.h"
+#include "dap_chain_net.h"
+
+#define LOG_TAG "dap_chain_cs_dag"
+
+
+typedef struct dap_chain_cs_dag_event_item {
+    dap_chain_hash_fast_t hash;
+    time_t ts_added;
+    dap_chain_cs_dag_event_t *event;
+    UT_hash_handle hh;
+} dap_chain_cs_dag_event_item_t;
+
+
+typedef struct dap_chain_cs_dag_pvt {
+    dap_enc_key_t* datum_add_sign_key;
+
+
+    pthread_rwlock_t events_rwlock;
+
+    dap_chain_cs_dag_event_item_t * events;
+
+    dap_chain_cs_dag_event_item_t * tx_events;
+    dap_chain_cs_dag_event_item_t * events_treshold;
+    dap_chain_cs_dag_event_item_t * events_lasts_unlinked;
+
+} dap_chain_cs_dag_pvt_t;
+
+#define PVT(a) ((dap_chain_cs_dag_pvt_t *) a->_pvt )
+
+// Atomic element organization callbacks
+static int s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t );                      //    Accept new event in dag
+static int s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t );                   //    Verify new event in dag
+static size_t s_chain_callback_atom_hdr_get_size(dap_chain_atom_ptr_t );                                 //    Get dag event size
+static size_t s_chain_callback_atom_get_static_hdr_size(void);                               //    Get dag event header size
+
+static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create(dap_chain_t * a_chain );
+static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create_from(dap_chain_t * a_chain ,
+                                                                     dap_chain_atom_ptr_t a);
+
+
+static dap_chain_atom_ptr_t s_chain_callback_atom_iter_find_by_hash(dap_chain_atom_iter_t * a_atom_iter ,
+                                                                       dap_chain_hash_fast_t * a_atom_hash);
+static dap_chain_datum_tx_t* s_chain_callback_atom_iter_find_by_tx_hash(dap_chain_t * a_chain ,
+                                                                       dap_chain_hash_fast_t * a_atom_hash);
+
+static dap_chain_datum_t* s_chain_callback_atom_get_datum(dap_chain_atom_ptr_t a_event);
+//    Get event(s) from dag
+static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_first( dap_chain_atom_iter_t * a_atom_iter ); //    Get the fisrt event from dag
+static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_next( dap_chain_atom_iter_t * a_atom_iter );  //    Get the next event from dag
+static dap_chain_atom_ptr_t *s_chain_callback_atom_iter_get_links( dap_chain_atom_iter_t * a_atom_iter ,
+                                                                  size_t * a_links_size_ptr );  //    Get list of linked events
+static dap_chain_atom_ptr_t *s_chain_callback_atom_iter_get_lasts( dap_chain_atom_iter_t * a_atom_iter ,
+                                                                  size_t * a_lasts_size_ptr );  //    Get list of linked events
+
+// Delete iterator
+static void s_chain_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_iter );                  //    Get the fisrt event from dag
+
+static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain_datum_t ** a_datums, size_t a_datums_size);
+// Datum ops
+/*
+static dap_chain_datum_iter_t* s_chain_callback_datum_iter_create(dap_chain_t * a_chain );
+static void s_chain_callback_datum_iter_delete(dap_chain_datum_iter_t * a_iter );
+static dap_chain_datum_t* s_chain_callback_datum_iter_get_first( dap_chain_datum_iter_t * a_datum_iter ); // Get the fisrt datum from dag
+static dap_chain_datum_t* s_chain_callback_datum_iter_get_next( dap_chain_datum_iter_t * a_datum_iter ); // Get the next datum from dag
+*/
+
+static int s_cli_dag(int argc, char ** argv, void *arg_func, char **str_reply);
+
+static bool s_seed_mode = false;
+/**
+ * @brief dap_chain_cs_dag_init
+ * @return
+ */
+int dap_chain_cs_dag_init(void)
+{
+    srand((unsigned int) time(NULL));
+    dap_chain_class_add( "dag", dap_chain_cs_dag_new );
+    s_seed_mode = dap_config_get_item_bool_default(g_config,"general","seed_mode",false);
+    dap_chain_node_cli_cmd_item_create ("dag", s_cli_dag, NULL, "DAG commands",
+        "dag -net <chain net name> -chain <chain name> event create -datum <datum hash>\n"
+            "\tCreate event from datum mempool element\n\n"
+        "dag -net <chain net name> -chain <chain name> event cancel -event <event hash>\n"
+            "\tRemove event from forming new round and put back its datum to mempool\n\n"
+        "dag -net <chain net name> -chain <chain name> event sign -event <event hash>\n"
+            "\tAdd sign to event <event hash> in round.new. Hash doesn't include other signs so event hash\n"
+            "\tdoesn't changes after sign add to event. \n\n"
+        "dag -net <chain net name> -chain <chain name> event dump -event <event hash> -from < events | events_lasts | round.new  | round.<Round id in hex> >\n"
+            "\tDump event info\n\n"
+        "dag -net <chain net name> -chain <chain name> event list -from < events | events_lasts | round.new  | round.<Round id in hex> \n\n"
+            "\tShow event list \n\n"
+        "dag -net <chain net name> -chain <chain name> round complete\n\n"
+                                        "\tComplete the current new round, verify it and if everything is ok - publish new events in chain\n\n"
+                                        );
+    log_it(L_NOTICE,"Initialized DAG chain items organization class");
+    return 0;
+}
+
+/**
+ * @brief dap_chain_cs_dag_deinit
+ */
+void dap_chain_cs_dag_deinit(void)
+{
+
+}
+
+/**
+ * @brief dap_chain_cs_dag_new
+ * @param a_chain
+ * @param a_chain_cfg
+ */
+int dap_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
+{
+    dap_chain_cs_dag_t * l_dag = DAP_NEW_Z(dap_chain_cs_dag_t);
+    l_dag->_pvt = DAP_NEW_Z(dap_chain_cs_dag_pvt_t);
+    l_dag->chain = a_chain;
+
+    pthread_rwlock_init(& PVT(l_dag)->events_rwlock,NULL);
+
+    a_chain->callback_delete = dap_chain_cs_dag_delete;
+
+    // Atom element callbacks
+    a_chain->callback_atom_add = s_chain_callback_atom_add ;  // Accept new element in chain
+    a_chain->callback_atom_verify = s_chain_callback_atom_verify ;  // Verify new element in chain
+    a_chain->callback_atom_get_size  = s_chain_callback_atom_hdr_get_size; // Get dag event size
+    a_chain->callback_atom_get_hdr_static_size = s_chain_callback_atom_get_static_hdr_size; // Get dag event hdr size
+
+    a_chain->callback_atom_iter_create = s_chain_callback_atom_iter_create;
+    a_chain->callback_atom_iter_create_from = s_chain_callback_atom_iter_create_from;
+    a_chain->callback_atom_iter_delete = s_chain_callback_atom_iter_delete;
+
+    // Linear pass through
+    a_chain->callback_atom_iter_get_first = s_chain_callback_atom_iter_get_first; // Get the fisrt element from chain
+    a_chain->callback_atom_iter_get_next = s_chain_callback_atom_iter_get_next; // Get the next element from chain from the current one
+    a_chain->callback_atom_get_datum = s_chain_callback_atom_get_datum;
+
+    a_chain->callback_atom_iter_get_links = s_chain_callback_atom_iter_get_links; // Get the next element from chain from the current one
+    a_chain->callback_atom_iter_get_lasts = s_chain_callback_atom_iter_get_lasts;
+
+    a_chain->callback_atom_find_by_hash = s_chain_callback_atom_iter_find_by_hash;
+    a_chain->callback_tx_find_by_hash = s_chain_callback_atom_iter_find_by_tx_hash;
+
+
+    a_chain->callback_datums_pool_proc = s_chain_callback_datums_pool_proc;
+
+    // Datum operations callbacks
+/*
+    a_chain->callback_datum_iter_create = s_chain_callback_datum_iter_create; // Datum iterator create
+    a_chain->callback_datum_iter_delete = s_chain_callback_datum_iter_delete; // Datum iterator delete
+    a_chain->callback_datum_iter_get_first = s_chain_callback_datum_iter_get_first; // Get the fisrt datum from chain
+    a_chain->callback_datum_iter_get_next = s_chain_callback_datum_iter_get_next; // Get the next datum from chain from the current one
+*/
+    // Others
+    a_chain->_inheritor = l_dag;
+
+    const char * l_static_genesis_event_hash_str = dap_config_get_item_str_default(a_chain_cfg,"dag","static_genesis_event",NULL);
+    if ( l_static_genesis_event_hash_str ){
+        int lhr;
+        if ( (lhr= dap_chain_str_to_hash_fast(l_static_genesis_event_hash_str,&l_dag->static_genesis_event_hash) )!= 0 ){
+            log_it( L_ERROR, "Can't read hash from static_genesis_event \"%s\", ret code %d ", l_static_genesis_event_hash_str, lhr);
+        }
+    }
+
+    l_dag->is_static_genesis_event = dap_config_get_item_bool_default(a_chain_cfg,"dag","is_static_genesis_event",false);
+    l_dag->is_single_line = dap_config_get_item_bool_default(a_chain_cfg,"dag","is_single_line",false);
+    l_dag->is_celled = dap_config_get_item_bool_default(a_chain_cfg,"dag","is_celled",false);
+    l_dag->is_add_directy = dap_config_get_item_bool_default(a_chain_cfg,"dag","is_add_directly",false);
+    l_dag->datum_add_hashes_count = dap_config_get_item_uint16_default(a_chain_cfg,"dag","datum_add_hashes_count",1);
+    l_dag->gdb_group_events_round_new = dap_strdup( dap_config_get_item_str_default(a_chain_cfg,"dag","gdb_group_events_round_new",
+                                                                        "events.round.new"));
+    if ( l_dag->is_single_line ) {
+        log_it (L_NOTICE, "DAG chain initialized (single line)");
+    } else {
+        log_it (L_NOTICE, "DAG chain initialized (multichain)");
+    }
+
+    return 0;
+}
+
+/**
+ * @brief dap_chain_cs_dag_delete
+ * @param a_dag
+ * @return
+ */
+void dap_chain_cs_dag_delete(dap_chain_t * a_chain)
+{
+    dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG ( a_chain );
+    pthread_rwlock_destroy(& PVT(l_dag)->events_rwlock);
+
+    if(l_dag->callback_delete )
+        l_dag->callback_delete(l_dag);
+    if(l_dag->_inheritor)
+        DAP_DELETE(l_dag->_inheritor);
+    if(l_dag->_pvt)
+        DAP_DELETE(l_dag->_pvt);
+}
+
+/**
+ * @brief s_chain_callback_atom_add Accept new event in dag
+ * @param a_chain DAG object
+ * @param a_atom
+ * @return 0 if verified and added well, otherwise if not
+ */
+static int s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom)
+{
+    int ret = s_chain_callback_atom_verify (a_chain, a_atom);
+    if ( ret < 0 ){
+        log_it(L_WARNING,"Wrong event, can't accept, verification returned %d",ret);
+        return  -1;
+    }
+    dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG(a_chain);
+    dap_chain_cs_dag_event_t * l_event = (dap_chain_cs_dag_event_t *) a_atom;
+
+    // verification was already in s_chain_callback_atom_verify()
+    ret = l_dag->callback_cs_verify(l_dag,l_event);
+    if ( ret != 0 ){
+        log_it(L_WARNING,"Consensus can't accept the event, verification returned %d",ret);
+        return  -2;
+    }
+    dap_chain_cs_dag_event_item_t * l_event_item = DAP_NEW_Z(dap_chain_cs_dag_event_item_t);
+    l_event_item->event = l_event;
+    l_event_item->ts_added = time(NULL);
+    dap_hash_fast(l_event, dap_chain_cs_dag_event_calc_size(l_event),&l_event_item->hash );
+
+    // Put in main table or in the treshhold if not all the rest linked event are present
+    dap_chain_cs_dag_event_item_t * l_event_search = NULL;
+    dap_chain_cs_dag_event_item_t * l_events =( ret==0 ? PVT(l_dag)->events : PVT(l_dag)->events_treshold );
+    pthread_rwlock_t * l_events_rwlock = &PVT(l_dag)->events_rwlock ;
+    pthread_rwlock_wrlock( l_events_rwlock );
+    HASH_FIND(hh, l_events,&l_event_item->hash,sizeof (l_event_search->hash),  l_event_search);
+    if ( l_event_search ) {
+        pthread_rwlock_unlock( l_events_rwlock );
+        char * l_hash_str = dap_chain_hash_fast_to_str_new(&l_event_item->hash);
+        log_it(L_ERROR, "Dag event %s is already present in dag",l_hash_str);
+        DAP_DELETE(l_event_item);
+        DAP_DELETE(l_hash_str);
+        return -3;
+    }
+    HASH_ADD(hh, l_events,hash,sizeof (l_event_item->hash),  l_event_item);
+    // save l_events to dag_pvt
+    if(ret==0)
+        PVT(l_dag)->events = l_events;
+    else
+        PVT(l_dag)->events_treshold = l_events;
+    //HASH_ADD(hh, PVT(l_dag)->events_treshold, hash, sizeof(l_event_item->hash), l_event_item);
+
+    if ( l_events == PVT(l_dag)->events){
+        dap_chain_cs_dag_event_item_t * l_event_last = NULL;
+        // Check the events and update the lasts
+        for ( dap_chain_hash_fast_t * l_link_hash = (dap_chain_hash_fast_t *) l_event->hashes_n_datum_n_signs ;
+                  l_link_hash < ( dap_chain_hash_fast_t *) (
+                  l_event->hashes_n_datum_n_signs + l_event->header.hash_count*sizeof (*l_link_hash) );
+                  l_link_hash += sizeof (dap_chain_hash_fast_t ) ) {
+            l_event_last = NULL;
+            HASH_FIND(hh,PVT(l_dag)->events_lasts_unlinked,&l_link_hash,sizeof(*l_link_hash), l_event_last);
+            if ( l_event_last ){ // If present in unlinked - remove
+                HASH_DEL(PVT(l_dag)->events_lasts_unlinked,l_event_last);
+                DAP_DELETE(l_event_last);
+            }
+
+        }
+        // and then adds itself
+        l_event_last= DAP_NEW_Z(dap_chain_cs_dag_event_item_t);
+        l_event_last->ts_added = l_event_item->ts_added;
+        l_event_last->event = l_event;
+        dap_hash_fast(l_event, dap_chain_cs_dag_event_calc_size(l_event),&l_event_last->hash );
+
+        HASH_ADD(hh,PVT(l_dag)->events_lasts_unlinked,hash,sizeof (l_event_last->hash),l_event_last);
+    }
+
+    // add datum from event to ledger
+    dap_chain_datum_t *l_datum = (dap_chain_datum_t*) dap_chain_cs_dag_event_get_datum(l_event);
+    switch (l_datum->header.type_id) {
+    case DAP_CHAIN_DATUM_TOKEN_DECL: {
+        dap_chain_datum_token_t *l_token = (dap_chain_datum_token_t*) l_datum->data;
+        dap_chain_ledger_token_add(a_chain->ledger, l_token, l_datum->header.data_size);
+    }
+        break;
+    case DAP_CHAIN_DATUM_TOKEN_EMISSION: {
+        dap_chain_datum_token_emission_t *l_token_emission = (dap_chain_datum_token_emission_t*) l_datum->data;
+        dap_chain_ledger_token_emission_add(a_chain->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;
+        dap_chain_cs_dag_event_item_t * l_tx_event= DAP_NEW_Z(dap_chain_cs_dag_event_item_t);
+        l_tx_event->ts_added = l_event_item->ts_added;
+        l_tx_event->event = l_event;
+        memcpy(&l_tx_event->hash, &l_event_item->hash, sizeof (l_tx_event->hash) );
+        HASH_ADD(hh,PVT(l_dag)->tx_events,hash,sizeof (l_tx_event->hash),l_tx_event);
+
+        //if ( !l_gdb_priv->is_load_mode ) // If its not load module but mempool proc
+        //    l_tx->header.ts_created = time(NULL);
+        //if(dap_chain_datum_tx_get_size(l_tx) == l_datum->header.data_size){
+
+        // don't save bad transactions to base
+        if(dap_chain_ledger_tx_add(a_chain->ledger, l_tx) != 1) {
+            pthread_rwlock_unlock(l_events_rwlock);
+            return -1;
+        }
+        //}else
+        //    return -2;
+    }
+        break;
+    default:
+        pthread_rwlock_unlock(l_events_rwlock);
+        return -1;
+    }
+
+    pthread_rwlock_unlock( l_events_rwlock );
+    // Now check the treshold if some events now are ready to move to the main table
+    dap_chain_cs_dag_proc_treshold(l_dag);
+    return 0;
+}
+
+/**
+ * @brief s_chain_callback_datums_add
+ * @param a_chain
+ * @param a_datums
+ * @param a_datums_size
+ */
+static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain_datum_t ** a_datums, size_t a_datums_count)
+{
+    dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG(a_chain);
+    size_t l_datum_processed =0;
+    size_t l_events_round_new_size = 0;
+    // Load current events new round pool
+    dap_global_db_obj_t * l_events_round_new = dap_chain_global_db_gr_load(l_dag->gdb_group_events_round_new, &l_events_round_new_size );
+    // Prepare hashes
+    size_t l_hashes_int_size = min(l_events_round_new_size + a_datums_count, l_dag->datum_add_hashes_count);
+//            ( l_events_round_new_size + a_datums_count ) > l_dag->datum_add_hashes_count ?
+//                                   l_dag->datum_add_hashes_count :
+//                                   l_events_round_new_size+a_datums_count;
+
+    if (l_dag->is_single_line ) // If single line - only one link inside
+        l_hashes_int_size = min(l_hashes_int_size, 1);
+
+    size_t l_hashes_ext_size = 0; // Change in cfg
+    size_t l_hashes_size = l_hashes_int_size+l_hashes_ext_size;
+    dap_chain_hash_fast_t * l_hashes = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t,
+                                             sizeof(dap_chain_hash_fast_t) * l_hashes_size);
+    size_t l_hashes_linked = 0;
+
+    for (size_t d = 0; d <a_datums_count ; d++){
+        dap_chain_datum_t * l_datum = a_datums[d];
+
+        if ( l_hashes_int_size && l_events_round_new_size){
+            // Linking randomly with current new round set
+            size_t l_rnd_steps;
+            // Linking events inside round
+            l_rnd_steps = 0;
+            do{
+                int l_index = rand() % (int) l_events_round_new_size;
+                dap_chain_hash_fast_t l_hash;
+                dap_chain_cs_dag_event_t * l_event = (dap_chain_cs_dag_event_t *) l_events_round_new[l_index].value;
+                size_t l_event_size = dap_chain_cs_dag_event_calc_size(l_event);
+                dap_hash_fast(l_event, l_event_size,&l_hash);
+
+                bool l_is_already_in_event = false;
+                for (uint16_t i=0; i<l_hashes_linked;i++ ){ // check if we already added it
+                    if (memcmp(&l_hashes[i],&l_hash,sizeof (l_hash) )==0 ){
+                        l_is_already_in_event = true;
+                        break;
+                    }
+                }
+
+                if ( ! l_is_already_in_event ){
+                    if(l_hashes_linked < l_hashes_size) {
+                        memcpy(&l_hashes[l_hashes_linked], &l_hash, sizeof(l_hash));
+                        l_hashes_linked++;
+                    }
+                }
+                l_rnd_steps++;
+                if (l_rnd_steps > 100) // Too many attempts
+                    break;
+            } while (l_hashes_linked <(l_events_round_new_size) );
+
+            // Check if we have enought hash links
+            if (l_hashes_linked<l_events_round_new_size ){
+                log_it(L_ERROR,"Can't link new events randomly for 100 attempts");
+                break;
+            }
+        }
+        // Now link with ext events
+        dap_chain_cs_dag_event_item_t *l_event_ext_item = NULL;
+        // is_single_line - only one link inside
+        if(!l_dag->is_single_line || !l_hashes_linked)
+        if( PVT(l_dag)->events_lasts_unlinked && l_hashes_linked < l_hashes_size) { // Take then the first one if any events_lasts are present
+                l_event_ext_item = PVT(l_dag)->events_lasts_unlinked;
+                memcpy(&l_hashes[l_hashes_linked], &l_event_ext_item->hash, sizeof(l_event_ext_item->hash));
+                l_hashes_linked++;
+            }
+
+        if (l_hashes_linked || s_seed_mode ) {
+            dap_chain_cs_dag_event_t * l_event = NULL;
+            if(l_dag->callback_cs_event_create)
+                l_event = l_dag->callback_cs_event_create(l_dag,l_datum,l_hashes,l_hashes_linked);
+            if ( l_event){ // Event is created
+
+                // add directly to file
+                if(l_dag->is_add_directy) {
+                    if(!s_chain_callback_atom_add(a_chain, l_event)) {
+                        l_datum_processed++;
+                    }
+                    else {
+                        log_it(L_ERROR, "Can't add new event");
+                        continue;
+                    }
+                }
+                // add to new round into global_db
+                else {
+                    dap_chain_hash_fast_t l_event_hash;
+                    dap_chain_cs_dag_event_calc_hash(l_event, &l_event_hash);
+                    char * l_event_hash_str = dap_chain_hash_fast_to_str_new(&l_event_hash);
+                    if(dap_chain_global_db_gr_set(dap_strdup(l_event_hash_str), (uint8_t *) l_event,
+                            dap_chain_cs_dag_event_calc_size(l_event),
+                            l_dag->gdb_group_events_round_new)) {
+                        log_it(L_INFO, "Event %s placed in the new forming round", l_event_hash_str);
+                        DAP_DELETE(l_event_hash_str);
+                        l_event_hash_str = NULL;
+                        // Clear old ext link and place itself as event_lasts
+
+                        dap_chain_cs_dag_event_item_t * l_event_unlinked_item = DAP_NEW_Z(
+                                dap_chain_cs_dag_event_item_t);
+                        if(l_event_ext_item)
+                            memcpy(&l_event_unlinked_item->hash, &l_event_ext_item->hash,
+                                    sizeof(l_event_ext_item->hash));
+                        l_event_unlinked_item->event = l_event;
+                        l_event_unlinked_item->ts_added = (time_t) l_event->header.ts_created;
+                        pthread_rwlock_wrlock(&PVT(l_dag)->events_rwlock);
+                        HASH_ADD(hh, PVT(l_dag)->events_lasts_unlinked, hash, sizeof(l_event_unlinked_item->hash),
+                                l_event_unlinked_item);
+                        if(l_event_ext_item) {
+                            HASH_DEL(PVT(l_dag)->events_lasts_unlinked, l_event_ext_item);
+                            DAP_DELETE(l_event_ext_item);
+                        }
+                        pthread_rwlock_unlock(&PVT(l_dag)->events_rwlock);
+
+                        l_datum_processed++;
+                    }else {
+                        log_it(L_ERROR,"Can't add new event to the new events round");
+                        break;
+                    }
+                }
+            }else {
+                log_it(L_ERROR,"Can't create new event!");
+                break;
+            }
+        }
+    }
+    // add events to file
+    if(l_dag->is_add_directy && l_datum_processed>0) {
+        dap_chain_cell_t *l_cell = dap_chain_cell_create();
+        int l_res = -1;
+        if(l_cell) {
+            dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id);
+            l_cell->chain = a_chain;
+            l_cell->id.uint64 = l_net ? l_net->pub.cell_id.uint64 : 0;
+            l_cell->file_storage_path = dap_strdup_printf("%0llx.dchaincell", l_cell->id.uint64);
+            l_res = dap_chain_cell_file_update(l_cell);
+        }
+        if(!l_cell || l_res < 0) {
+            log_it(L_ERROR, "Can't add new %d events to the file '%s'", l_datum_processed,
+                    l_cell ? l_cell->file_storage_path : "");
+            l_datum_processed = 0;
+        }
+        dap_chain_cell_delete(l_cell);
+    }
+    dap_chain_global_db_objs_delete(l_events_round_new, l_events_round_new_size);
+    return  l_datum_processed;
+}
+
+
+/**
+ * @brief dap_chain_cs_dag_find_event_by_hash
+ * @param a_dag
+ * @param a_hash
+ * @return
+ */
+dap_chain_cs_dag_event_t* dap_chain_cs_dag_find_event_by_hash(dap_chain_cs_dag_t * a_dag, dap_chain_hash_fast_t * a_hash)
+{
+    dap_chain_cs_dag_event_item_t* l_event_item = NULL;
+    pthread_rwlock_rdlock( &PVT(a_dag)->events_rwlock );
+    HASH_FIND(hh, PVT(a_dag)->events ,a_hash,sizeof(*a_hash), l_event_item);
+    dap_chain_cs_dag_event_t * l_event = l_event_item->event;
+    pthread_rwlock_unlock( &PVT(a_dag)->events_rwlock );
+    return  l_event;
+}
+
+
+
+/**
+ * @brief s_chain_callback_atom_verify Verify atomic element
+ * @param a_chain
+ * @param a_atom
+ * @return
+ */
+static int s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t  a_atom)
+{
+    dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG(a_chain);
+    dap_chain_cs_dag_event_t * l_event = (dap_chain_cs_dag_event_t *) a_atom;
+
+    if (l_event->header.hash_count == 0 && l_dag->is_static_genesis_event ){
+        dap_chain_hash_fast_t l_event_hash;
+        dap_chain_cs_dag_event_calc_hash(l_event,&l_event_hash);
+        if ( memcmp( &l_event_hash, &l_dag->static_genesis_event_hash, sizeof(l_event_hash) ) != 0 ){
+            char * l_event_hash_str = dap_chain_hash_fast_to_str_new(&l_event_hash);
+            char * l_genesis_event_hash_str = dap_chain_hash_fast_to_str_new(&l_dag->static_genesis_event_hash);
+
+            log_it(L_WARNING, "Wrong genesis block %s (staticly predefined %s)",l_event_hash_str, l_genesis_event_hash_str);
+            return -22;
+        }
+    }
+
+    int ret = l_dag->callback_cs_verify ( l_dag, l_event );
+    if (ret == 0 ){
+        if ( PVT(l_dag)->events )
+            for (size_t i = 0; i< l_event->header.hash_count; i++) {
+                dap_chain_hash_fast_t * l_hash =  ((dap_chain_hash_fast_t *) l_event->hashes_n_datum_n_signs) + i;
+                dap_chain_cs_dag_event_item_t * l_event_search = NULL;
+                HASH_FIND(hh, PVT(l_dag)->events ,l_hash ,sizeof (*l_hash),  l_event_search);
+                if ( l_event_search == NULL ){
+                    log_it(L_DEBUG, "Hash %s wasn't in hashtable of previously parsed", l_hash);
+                    return 1;
+                }
+
+            }
+
+        return 0;
+    }else {
+        return  ret;
+    }
+}
+
+/**
+ * @brief dap_chain_cs_dag_proc_event_round_new
+ * @param a_dag
+ */
+void dap_chain_cs_dag_proc_event_round_new(dap_chain_cs_dag_t *a_dag)
+{
+    (void) a_dag;
+    log_it(L_WARNING,"No proc event algorythm, use manual commands for round aproving");
+}
+
+
+/**
+ * @brief s_dag_events_lasts_delete_linked_with_event
+ * @param a_dag
+ * @param a_event
+ */
+void s_dag_events_lasts_delete_linked_with_event(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_event_t * a_event)
+{
+    for (size_t i = 0; i< a_event->header.hash_count; i++) {
+        dap_chain_hash_fast_t * l_hash =  ((dap_chain_hash_fast_t *) a_event->hashes_n_datum_n_signs) + i;
+        dap_chain_cs_dag_event_item_t * l_event_item = NULL;
+        HASH_FIND(hh, PVT(a_dag)->events_lasts_unlinked ,l_hash ,sizeof (*l_hash),  l_event_item);
+        if ( l_event_item ){
+            HASH_DEL(PVT(a_dag)->events_lasts_unlinked,l_event_item);
+            DAP_DELETE(l_event_item);
+        }
+    }
+}
+
+
+
+int dap_chain_cs_dag_event_verify_hashes_with_treshold(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_event_t * a_event)
+{
+    bool l_is_events_all_hashes = true;
+    bool l_is_events_main_hashes = true;
+    for (size_t i = 0; i< a_event->header.hash_count; i++) {
+        dap_chain_hash_fast_t * l_hash =  ((dap_chain_hash_fast_t *) a_event->hashes_n_datum_n_signs) + i;
+        dap_chain_cs_dag_event_item_t * l_event_search = NULL;
+        HASH_FIND(hh, PVT(a_dag)->events ,l_hash ,sizeof (*l_hash),  l_event_search);
+        if ( l_event_search == NULL ){ // If not found in events - search in treshhold
+            l_is_events_main_hashes = false;
+            HASH_FIND(hh, PVT(a_dag)->events_treshold ,l_hash ,sizeof (*l_hash),  l_event_search);
+            if( l_event_search == NULL ){ // Hash is not in events or treshold table, keep the current item where it is
+                l_is_events_all_hashes = false;
+                break;
+            }
+        }
+    }
+    if( l_is_events_all_hashes && l_is_events_main_hashes ){
+        return  0;
+    }else if ( ! l_is_events_all_hashes) {
+        return  -1;
+    }else {
+        return  1;
+    }
+}
+
+/**
+ * @brief dap_chain_cs_dag_proc_treshold
+ * @param a_dag
+ */
+void dap_chain_cs_dag_proc_treshold(dap_chain_cs_dag_t * a_dag)
+{
+    // TODO Process finish treshold. For now - easiest from possible
+    pthread_rwlock_rdlock(&PVT(a_dag)->events_rwlock);
+    dap_chain_cs_dag_event_item_t * l_event_item = NULL, * l_event_item_tmp = NULL;
+    HASH_ITER(hh,PVT(a_dag)->events_treshold,l_event_item, l_event_item_tmp){
+        dap_chain_cs_dag_event_t * l_event = l_event_item->event;
+        int ret = dap_chain_cs_dag_event_verify_hashes_with_treshold (a_dag,l_event);
+        if ( ret == 0){ // All its hashes are in main table, move thats one too into it
+            pthread_rwlock_unlock(&PVT(a_dag)->events_rwlock);
+            pthread_rwlock_wrlock(&PVT(a_dag)->events_rwlock);
+            HASH_DEL(PVT(a_dag)->events_treshold,l_event_item);
+            HASH_ADD(hh, PVT(a_dag)->events, hash,sizeof (l_event_item->hash),  l_event_item);
+            s_dag_events_lasts_delete_linked_with_event(a_dag, l_event);
+        }
+    }
+    pthread_rwlock_unlock(&PVT(a_dag)->events_rwlock);
+}
+
+
+/**
+ * @brief s_chain_callback_atom_get_size Get size of atomic element
+ * @param a_atom
+ * @return
+ */
+static size_t s_chain_callback_atom_hdr_get_size(dap_chain_atom_ptr_t  a_atom)
+{
+    return dap_chain_cs_dag_event_calc_size( (dap_chain_cs_dag_event_t * ) a_atom);
+}
+
+/**
+ * @brief s_chain_callback_atom_get_static_hdr_size
+ * @param a_chain
+ * @return
+ */
+static size_t s_chain_callback_atom_get_static_hdr_size()
+{
+   return sizeof (dap_chain_class_dag_event_hdr_t);
+}
+
+/**
+ * @brief s_chain_callback_atom_iter_create_from
+ * @param a_chain
+ * @param a_atom
+ * @return
+ */
+static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create_from(dap_chain_t * a_chain ,
+                                                                     dap_chain_atom_ptr_t a_atom)
+{
+    dap_chain_atom_iter_t * l_atom_iter = DAP_NEW_Z(dap_chain_atom_iter_t);
+    l_atom_iter->chain = a_chain;
+    l_atom_iter->cur = a_atom;
+
+    if ( a_atom ){
+        dap_chain_hash_fast_t l_atom_hash;
+        dap_hash_fast(a_atom, a_chain->callback_atom_get_size(a_atom), &l_atom_hash );
+
+        dap_chain_cs_dag_event_item_t  * l_atom_item;
+        HASH_FIND(hh, PVT(DAP_CHAIN_CS_DAG(a_chain))->events, &l_atom_hash, sizeof(l_atom_hash),l_atom_item );
+        l_atom_iter->cur_item = l_atom_item;
+    }
+    return l_atom_iter;
+
+}
+
+/**
+ * @brief s_chain_callback_atom_iter_create Create atomic element iterator
+ * @param a_chain
+ * @return
+ */
+static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create(dap_chain_t * a_chain )
+{
+    dap_chain_atom_iter_t * l_atom_iter = DAP_NEW_Z(dap_chain_atom_iter_t);
+    l_atom_iter->chain = a_chain;
+    return l_atom_iter;
+}
+
+/**
+ * @brief s_chain_callback_atom_get_datum Get the datum from event
+ * @param a_atom_iter
+ * @return
+ */
+static dap_chain_datum_t* s_chain_callback_atom_get_datum(dap_chain_atom_ptr_t a_event)
+{
+    if(a_event)
+        return dap_chain_cs_dag_event_get_datum((dap_chain_cs_dag_event_t*) a_event);
+    return NULL;
+}
+
+/**
+ * @brief s_chain_callback_atom_iter_get_first Get the first dag event
+ * @param a_atom_iter
+ * @return
+ */
+static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_first(dap_chain_atom_iter_t * a_atom_iter )
+{
+    dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG(a_atom_iter->chain);
+    dap_chain_cs_dag_pvt_t *l_dag_pvt = l_dag ? PVT(l_dag) : NULL;
+    a_atom_iter->cur_item = l_dag_pvt->events;
+    a_atom_iter->cur = (dap_chain_cs_dag_event_t*) (l_dag_pvt->events ? l_dag_pvt->events->event : NULL);
+
+//    a_atom_iter->cur =  a_atom_iter->cur ?
+//                (dap_chain_cs_dag_event_t*) PVT (DAP_CHAIN_CS_DAG( a_atom_iter->chain) )->events->event : NULL;
+//    a_atom_iter->cur_item = PVT (DAP_CHAIN_CS_DAG( a_atom_iter->chain) )->events;
+    return a_atom_iter->cur;
+}
+
+/**
+ * @brief s_chain_callback_atom_iter_get_lasts
+ * @param a_atom_iter
+ * @param a_lasts_size_ptr
+ * @return
+ */
+static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_lasts( dap_chain_atom_iter_t * a_atom_iter ,
+                                                                  size_t * a_lasts_size_ptr )
+{
+    dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG( a_atom_iter->chain );
+
+    *a_lasts_size_ptr = HASH_COUNT( PVT(l_dag)->events_lasts_unlinked );
+    if ( *a_lasts_size_ptr > 0 ) {
+        dap_chain_atom_ptr_t * l_ret = DAP_NEW_Z_SIZE( dap_chain_atom_ptr_t,
+                                           sizeof (dap_chain_atom_ptr_t*) * (*a_lasts_size_ptr) );
+
+        dap_chain_cs_dag_event_item_t * l_event_item = NULL, *l_event_item_tmp = NULL;
+        size_t i = 0;
+        HASH_ITER(hh,PVT(l_dag)->events_lasts_unlinked, l_event_item,l_event_item_tmp){
+            l_ret[i] = l_event_item->event;
+            i++;
+        }
+        return l_ret;
+    }
+    return NULL;
+}
+
+/**
+ * @brief s_chain_callback_atom_iter_get_links
+ * @param a_atom_iter
+ * @param a_links_size_ptr
+ * @return
+ */
+static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_links( dap_chain_atom_iter_t * a_atom_iter ,
+                                                                  size_t * a_links_size_ptr )
+{
+    if ( a_atom_iter->cur && a_atom_iter->chain){
+        dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG( a_atom_iter->chain );
+        if(!l_dag){
+            log_it(L_ERROR,"Chain %s have DAP_CHAIN_CS_DAG() = NULL", a_atom_iter->chain->name);
+            return NULL;
+        }
+        dap_chain_cs_dag_event_t * l_event =(dap_chain_cs_dag_event_t *) a_atom_iter->cur;
+        dap_chain_cs_dag_event_item_t * l_event_item = (dap_chain_cs_dag_event_item_t *) a_atom_iter->cur_item;
+        if ( l_event->header.hash_count > 0){
+            dap_chain_atom_ptr_t * l_ret = DAP_NEW_Z_SIZE(dap_chain_atom_ptr_t,
+                                               sizeof (dap_chain_atom_ptr_t*) * l_event->header.hash_count );
+            *a_links_size_ptr = l_event->header.hash_count;
+            for (uint16_t i = 0; i < l_event->header.hash_count; i++){
+                dap_chain_cs_dag_event_item_t * l_link_item = NULL;
+                dap_chain_hash_fast_t * l_link_hash = (dap_chain_hash_fast_t *)
+                        (l_event->hashes_n_datum_n_signs +
+                        i*sizeof(*l_link_hash));
+                HASH_FIND(hh, PVT(l_dag)->events,l_link_hash,sizeof(*l_link_hash),l_link_item);
+                if ( l_link_item ){
+                    l_ret[i] = l_link_item->event;
+                }else {
+                    char * l_link_hash_str = dap_chain_hash_fast_to_str_new(l_link_hash);
+                    char * l_event_hash_str = l_event_item ? dap_chain_hash_fast_to_str_new(&l_event_item->hash) : NULL;
+                    log_it(L_ERROR,"Can't find %s->%s links", l_event_hash_str ? l_event_hash_str : "[null]", l_link_hash_str);
+                    DAP_DELETE(l_event_hash_str);
+                    DAP_DELETE(l_link_hash_str);
+                    (*a_links_size_ptr)--;
+                }
+            }
+            if(!(*a_links_size_ptr)){
+                DAP_DELETE(l_ret);
+                l_ret = NULL;
+            }
+            return l_ret;
+        }
+    }
+    return  NULL;
+}
+
+/**
+ * @brief s_chain_callback_atom_iter_find_by_hash
+ * @param a_atom_iter
+ * @param a_atom_hash
+ * @return
+ */
+static dap_chain_atom_ptr_t s_chain_callback_atom_iter_find_by_hash(dap_chain_atom_iter_t * a_atom_iter ,
+                                                                       dap_chain_hash_fast_t * a_atom_hash)
+{
+    dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG( a_atom_iter->chain );
+    dap_chain_cs_dag_event_item_t * l_event_item = NULL;
+    HASH_FIND(hh, PVT(l_dag)->events,a_atom_hash,sizeof(*a_atom_hash),l_event_item);
+    if ( l_event_item ){
+        a_atom_iter->cur_item = l_event_item;
+        a_atom_iter->cur = l_event_item->event;
+        return  l_event_item->event;
+    }else
+        return NULL;
+}
+
+
+static dap_chain_datum_tx_t* s_chain_callback_atom_iter_find_by_tx_hash(dap_chain_t * a_chain ,
+                                                                       dap_chain_hash_fast_t * a_atom_hash)
+{
+    dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG( a_chain );
+    dap_chain_cs_dag_event_item_t * l_event_item = NULL;
+    HASH_FIND(hh, PVT(l_dag)->tx_events,a_atom_hash,sizeof(*a_atom_hash),l_event_item);
+    if ( l_event_item ){
+        dap_chain_datum_t * l_datum = dap_chain_cs_dag_event_get_datum(l_event_item->event) ;
+        return l_datum ? l_datum->header.data_size ? (dap_chain_datum_tx_t*) l_datum->data : NULL :NULL;
+    }else
+        return NULL;
+}
+
+/**
+ * @brief s_chain_callback_atom_iter_get_next Get the next dag event
+ * @param a_atom_iter
+ * @return
+ */
+static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_next( dap_chain_atom_iter_t * a_atom_iter )
+{
+    if (a_atom_iter->cur ){
+        dap_chain_cs_dag_event_item_t * l_event_item = (dap_chain_cs_dag_event_item_t*) a_atom_iter->cur_item;
+        a_atom_iter->cur_item = l_event_item->hh.next;
+        l_event_item = (dap_chain_cs_dag_event_item_t*) a_atom_iter->cur_item;
+        // if l_event_item=NULL then items are over
+        a_atom_iter->cur = l_event_item ? l_event_item->event : NULL;
+    }
+    return a_atom_iter->cur;
+}
+
+/**
+ * @brief s_chain_callback_atom_iter_delete Delete dag event iterator
+ * @param a_atom_iter
+ */
+static void s_chain_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_iter )
+{
+    DAP_DELETE(a_atom_iter);
+}
+
+/**
+ * @brief s_cli_dag
+ * @param argc
+ * @param argv
+ * @param arg_func
+ * @param str_reply
+ * @return
+ */
+static int s_cli_dag(int argc, char ** argv, void *arg_func, char **a_str_reply)
+{
+    enum {
+        SUBCMD_EVENT_CREATE,
+        SUBCMD_EVENT_CANCEL,
+        SUBCMD_EVENT_LIST,
+        SUBCMD_EVENT_DUMP,
+        SUBCMD_UNDEFINED
+    } l_event_subcmd={0};
+
+    const char* l_event_subcmd_str[]={
+        [SUBCMD_EVENT_CREATE]="create",
+        [SUBCMD_EVENT_CANCEL]="cancel",
+        [SUBCMD_EVENT_LIST]="list",
+        [SUBCMD_EVENT_DUMP]="dump",
+        [SUBCMD_UNDEFINED]="UNDEFINED"
+    };
+
+
+    int arg_index = 1;
+
+    const char * l_net_name = NULL;
+
+    const char * l_chain_name = NULL;
+
+    const char * l_event_cmd_str = NULL;
+    const char * l_round_cmd_str = NULL;
+
+    const char* l_event_hash_str = NULL;
+    dap_chain_hash_fast_t l_event_hash = {0};
+
+    const char * l_datum_hash_str = NULL;
+
+    const char * l_from_events_str = NULL;
+
+    dap_chain_t * l_chain = NULL;
+    dap_chain_cs_dag_t * l_dag = NULL;
+    dap_chain_net_t * l_net = NULL;
+
+    dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-net", &l_net_name);
+    dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-chain", &l_chain_name);
+    dap_chain_node_cli_find_option_val(argv, arg_index, argc, "event", &l_event_cmd_str);
+    dap_chain_node_cli_find_option_val(argv, arg_index, argc, "round", &l_round_cmd_str);
+
+    if ( l_net_name == NULL){
+        dap_chain_node_cli_set_reply_text(a_str_reply, "Need -net <net name> param!");
+        return -1;
+    }
+    l_net = dap_chain_net_by_name( l_net_name );
+    if ( l_net == NULL ){
+        dap_chain_node_cli_set_reply_text(a_str_reply, "Can't find network \"%s\"",l_net_name);
+        return -2;
+
+    }
+
+    if ( l_chain_name == NULL){
+        dap_chain_node_cli_set_reply_text(a_str_reply, "Need -chain <chain name> param!");
+        return -3;
+    }
+    l_chain = dap_chain_net_get_chain_by_name(l_net,l_chain_name);
+    if ( l_chain == NULL ){
+        dap_chain_node_cli_set_reply_text(a_str_reply, "Can't find chain \"%s\" in network \"%s\"",
+                                          l_chain_name, l_net_name);
+        return -4;
+    }
+    l_dag = DAP_CHAIN_CS_DAG(l_chain);
+
+    int ret = 0;
+    if ( l_round_cmd_str ) {
+        if ( strcmp(l_round_cmd_str,"complete") == 0 ){
+            const char * l_cmd_mode_str = NULL;
+            dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-mode", &l_cmd_mode_str);
+            bool l_verify_only = false;
+            if ( dap_strcmp(l_cmd_mode_str,"verify only") == 0 ){
+                l_verify_only = true;
+            }
+            log_it(L_NOTICE,"Round complete command accepted, forming new events");
+
+            size_t l_objs_size=0;
+            dap_global_db_obj_t * l_objs = dap_chain_global_db_gr_load(l_dag->gdb_group_events_round_new,&l_objs_size);
+
+            dap_string_t *l_str_ret_tmp= l_objs_size>0 ? dap_string_new("Completing round:\n") : dap_string_new("Completing round: no data");
+
+            // list for verifed and added events
+            dap_list_t *l_list_to_del = NULL;
+
+            // Check if its ready or not
+            for (size_t i = 0; i< l_objs_size; i++ ){
+                dap_chain_cs_dag_event_t * l_event = (dap_chain_cs_dag_event_t*) l_objs[i].value;
+                size_t l_event_size = l_objs[i].value_len;
+                int l_ret_event_verify;
+                if ( ( l_ret_event_verify = l_dag->callback_cs_verify (l_dag,l_event) ) !=0 ){// if consensus accept the event
+                    dap_string_append_printf( l_str_ret_tmp,
+                            "Error! Event %s is not passing consensus verification, ret code %d\n",
+                                              l_objs[i].key, l_ret_event_verify );
+                    ret = -30;
+                    break;
+                }else {
+                    dap_string_append_printf( l_str_ret_tmp, "Event %s verification passed\n", l_objs[i].key);
+                    // If not verify only mode we add
+                    if ( ! l_verify_only ){
+                        dap_chain_atom_ptr_t l_new_atom = (dap_chain_atom_ptr_t)dap_chain_cs_dag_event_copy(l_event); // produce deep copy of event;
+                        memcpy(l_new_atom, l_event, l_event_size);
+                        if(s_chain_callback_atom_add(l_chain, l_new_atom) < 0) { // Add new atom in chain
+                            DAP_DELETE(l_new_atom);
+                            dap_string_append_printf(l_str_ret_tmp, "Event %s not added in chain\n", l_objs[i].key);
+                        }
+                        else {
+                            // add event to delete
+                            l_list_to_del = dap_list_prepend(l_list_to_del, l_objs[i].key);
+                            dap_string_append_printf(l_str_ret_tmp, "Event %s added in chain successfully\n",
+                                    l_objs[i].key);
+                        }
+                    }
+                }
+            }
+            // write events to file and delete events from db
+            if(l_list_to_del) {
+                dap_chain_cell_t *l_cell = dap_chain_cell_create();
+                if(l_cell) {
+                    l_cell->chain = l_chain;
+                    l_cell->id.uint64 = l_net ? l_net->pub.cell_id.uint64 : 0;
+                    l_cell->file_storage_path = dap_strdup_printf("%0llx.dchaincell", l_cell->id.uint64);
+                    if(!dap_chain_cell_file_update(l_cell)) {
+                        // delete events from db
+                        dap_list_t *l_list_tmp = l_list_to_del;
+                        while(l_list_tmp) {
+                            char *l_key = strdup((char*) l_list_tmp->data);
+                            dap_chain_global_db_gr_del(l_key, l_dag->gdb_group_events_round_new);
+                            l_list_tmp = dap_list_next(l_list_tmp);
+                        }
+                    }
+                }
+                dap_chain_cell_delete(l_cell);
+                dap_list_free(l_list_to_del);
+            }
+
+            // Cleaning up
+            dap_chain_global_db_objs_delete(l_objs, l_objs_size);
+            dap_chain_node_cli_set_reply_text(a_str_reply,l_str_ret_tmp->str);
+            dap_string_free(l_str_ret_tmp,false);
+
+            // Spread new  mempool changes and  dag events in network - going to SYNC_ALL
+            dap_chain_net_sync_all(l_net);
+        }
+    }else if ( l_event_cmd_str  ) {
+        if  ( strcmp( l_event_cmd_str, "create" ) == 0  ) {
+            dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-datum", &l_datum_hash_str);
+            l_event_subcmd = SUBCMD_EVENT_CREATE;
+        } else if (  strcmp( l_event_cmd_str, "cancel" ) == 0  ) {
+            dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-event", &l_event_hash_str);
+            l_event_subcmd = SUBCMD_EVENT_CANCEL;
+        } else if ( strcmp( l_event_cmd_str, "list" ) == 0 ) {
+            l_event_subcmd = SUBCMD_EVENT_LIST;
+            dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-from", &l_from_events_str);
+        } else if ( strcmp( l_event_cmd_str,"dump") == 0 ) {
+            l_event_subcmd = SUBCMD_EVENT_DUMP;
+            dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-from", &l_from_events_str);
+            dap_chain_node_cli_find_option_val(argv, arg_index, argc, "-event", &l_event_hash_str);
+        } else {
+            l_event_subcmd = SUBCMD_UNDEFINED;
+        }
+
+        if (l_event_hash_str)
+            dap_chain_str_to_hash_fast(l_event_hash_str,&l_event_hash);
+
+        switch ( l_event_subcmd ){
+            case SUBCMD_EVENT_CREATE:{
+                size_t l_datums_count=1;
+                char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool(l_chain);
+                dap_chain_datum_t ** l_datums = DAP_NEW_Z_SIZE(dap_chain_datum_t*,
+                                                               sizeof(dap_chain_datum_t*)*l_datums_count);
+                size_t l_datum_size = 0;
+                dap_chain_datum_t * l_datum = (dap_chain_datum_t*) dap_chain_global_db_gr_get( l_datum_hash_str ,
+                                                                                                  &l_datum_size,
+                                                                   l_gdb_group_mempool);
+                l_datums[0] = l_datum;
+                if ( s_chain_callback_datums_pool_proc(l_chain,l_datums,l_datums_count ) == l_datums_count ){
+                    for ( size_t i = 0; i <l_datums_count; i++){
+                       dap_chain_hash_fast_t l_datum_hash;
+                       dap_hash_fast(l_datums[i],dap_chain_datum_size(l_datums[i]),&l_datum_hash);
+                       char * l_datums_datum_hash_str = dap_chain_hash_fast_to_str_new(&l_datum_hash);
+                       if ( dap_chain_global_db_gr_del( dap_strdup(l_datums_datum_hash_str),l_gdb_group_mempool ) ){
+                           dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                             "Converted datum %s from mempool to event in the new forming round ",
+                                                             l_datums_datum_hash_str);
+                           DAP_DELETE(l_datums_datum_hash_str);
+                           ret = 0;
+                       }else {
+                           dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                             "Warning! Can't delete datum %s from mempool after conversion to event in the new forming round ",
+                                                             l_datums_datum_hash_str);
+                           ret = 1;
+                       }
+                    }
+                }else {
+                    dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                      "Warning! Can't convert datum %s from mempool to event in the new forming round ",
+                                                      l_datum_hash_str);
+                    ret = -12;
+
+                }
+                DAP_DELETE(l_gdb_group_mempool);
+                dap_chain_net_sync_all(l_net);
+            }break;
+            case SUBCMD_EVENT_CANCEL:{
+                char * l_gdb_group_events = DAP_CHAIN_CS_DAG(l_chain)->gdb_group_events_round_new;
+                if ( dap_chain_global_db_gr_del( dap_strdup(l_event_hash_str) ,l_gdb_group_events ) ){
+                    dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                      "Successfuly removed event 0x%s from the new forming round ",
+                                                      l_event_hash_str);
+                    ret = 0;
+                }else {
+                    dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                      "Can't remove event 0x%s from the new forming round ",
+                                                      l_event_hash_str);
+                    ret = -1;
+                }
+                DAP_DELETE( l_gdb_group_events );
+                dap_chain_net_sync_gdb(l_net);
+            }break;
+            case SUBCMD_EVENT_DUMP:{
+                dap_chain_cs_dag_event_t * l_event = NULL;
+                size_t l_event_size = 0;
+                if ( l_from_events_str ){
+                    if ( strcmp(l_from_events_str,"round.new") == 0 ){
+                        const char * l_gdb_group_events = l_dag->gdb_group_events_round_new;
+                        l_event = (dap_chain_cs_dag_event_t *)  dap_chain_global_db_gr_get
+                                              ( l_event_hash_str ,&l_event_size,l_gdb_group_events );
+                    }else if ( strncmp(l_from_events_str,"round.",6) == 0){
+
+                    }else if ( strcmp(l_from_events_str,"events_lasts") == 0){
+                        dap_chain_cs_dag_event_item_t * l_event_item = NULL;
+                        HASH_FIND(hh,PVT(l_dag)->events_lasts_unlinked,&l_event_hash,sizeof(l_event_hash),l_event_item);
+                        if ( l_event_item )
+                            l_event = l_event_item->event;
+                        else {
+                            ret = -23;
+                            dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                              "Can't find events %s in events_last table\n");
+                            break;
+                        }
+                    }else if ( strcmp(l_from_events_str,"events") == 0){
+                        dap_chain_cs_dag_event_item_t * l_event_item = NULL;
+                        HASH_FIND(hh,PVT(l_dag)->events,&l_event_hash,sizeof(l_event_hash),l_event_item);
+                        if ( l_event_item )
+                            l_event = l_event_item->event;
+                        else {
+                            ret = -24;
+                            dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                              "Can't find events %s in events table\n");
+                            break;
+                        }
+
+                    }else {
+                        ret = -22;
+                        dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                          "Wrong events_from option \"%s\", need one of variant: events, round.new, events_lasts, round.0x0123456789ABCDEF");
+                        break;
+
+                    }
+                } else {
+                    ret = -21;
+                    dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                      "No events_from option");
+                    break;
+                }
+                if ( l_event ){
+                    dap_string_t * l_str_tmp = dap_string_new(NULL);
+                    char buf[50];
+                    time_t l_ts_reated = (time_t) l_event->header.ts_created;
+                     // Header
+                    dap_string_append_printf(l_str_tmp,"Event %s:\n", l_event_hash_str);
+                    dap_string_append_printf(l_str_tmp,"\t\t\t\tversion: 0x%04sX\n",l_event->header.version);
+                    dap_string_append_printf(l_str_tmp,"\t\t\t\tcell_id: 0x%016llX\n",l_event->header.cell_id.uint64);
+                    dap_string_append_printf(l_str_tmp,"\t\t\t\tchain_id: 0x%016llX\n",l_event->header.chain_id.uint64);
+                    dap_string_append_printf(l_str_tmp,"\t\t\t\tts_created: %s\n",ctime_r(&l_ts_reated, buf) );
+
+                    // Hash links
+                    dap_string_append_printf(l_str_tmp,"\t\t\t\thashes:\tcount: %us\n",l_event->header.hash_count);
+                    for (uint16_t i=0; i < l_event->header.hash_count; i++){
+                        dap_chain_hash_fast_t * l_hash = (dap_chain_hash_fast_t *) (l_event->hashes_n_datum_n_signs +
+                                i*sizeof (dap_chain_hash_fast_t));
+                        char * l_hash_str = dap_chain_hash_fast_to_str_new(l_hash);
+                        dap_string_append_printf(l_str_tmp,"\t\t\t\t\t\thash: %s\n",l_hash_str);
+                        DAP_DELETE(l_hash_str);
+                    }
+                    size_t l_offset =  l_event->header.hash_count*sizeof (dap_chain_hash_fast_t);
+                    dap_chain_datum_t * l_datum = (dap_chain_datum_t*) (l_event->hashes_n_datum_n_signs + l_offset);
+                    size_t l_datum_size =  dap_chain_datum_size(l_datum);
+                    time_t l_datum_ts_create = (time_t) l_datum->header.ts_create;
+
+                    // Nested datum
+                    dap_string_append_printf(l_str_tmp,"\t\t\t\tdatum:\tdatum_size: %u\n",l_datum_size);
+                    dap_string_append_printf(l_str_tmp,"\t\t\t\t\t\tversion:=%0x02X\n", l_datum->header.version_id);
+                    dap_string_append_printf(l_str_tmp,"\t\t\t\t\t\ttype_id:=%s\n", c_datum_type_str[l_datum->header.type_id]);
+                    dap_string_append_printf(l_str_tmp,"\t\t\t\t\t\tts_create=%s\n",ctime_r( &l_datum_ts_create,buf ));
+                    dap_string_append_printf(l_str_tmp,"\t\t\t\t\t\tdata_size=%u\n", l_datum->header.data_size);
+
+                    // Signatures
+                    dap_string_append_printf(l_str_tmp,"\t\t\t\tsigns:\tcount: %us\n",l_event->header.signs_count);
+                    l_offset += l_datum_size;
+                    while (l_offset + sizeof (l_event->header) < l_event_size ){
+                        dap_sign_t * l_sign =(dap_sign_t *) (l_event->hashes_n_datum_n_signs +l_offset);
+                        size_t l_sign_size = dap_sign_get_size(l_sign);
+                        if (l_sign_size == 0 ){
+                            dap_string_append_printf(l_str_tmp,"\t\t\t\tERROR: wrong sign size 0, stop parsing headers\n");
+                            break;
+                        }
+                        dap_enc_key_t * l_sign_key = dap_sign_to_enc_key(l_sign);
+                        dap_chain_addr_t l_addr = {0};
+                        dap_chain_addr_fill(&l_addr,l_sign_key,&l_net->pub.id);
+                        char * l_addr_str = dap_chain_addr_to_str(&l_addr);
+                        dap_string_append_printf(l_str_tmp,"\t\t\t\t\t\ttype: %s\taddr: %s"
+                                                           "n", dap_sign_type_to_str( l_sign->header.type ),
+                                                 l_addr_str );
+                        l_offset += l_sign_size;
+                        DAP_DELETE( l_addr_str);
+                        dap_enc_key_delete(l_sign_key);
+                    }
+
+                    dap_chain_node_cli_set_reply_text(a_str_reply, l_str_tmp->str);
+                    dap_string_free(l_str_tmp,false);
+                    ret=0;
+                }else {
+                    dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                      "Can't find event 0x%s in the new forming round ",
+                                                      l_event_hash_str);
+                    ret=-10;
+                }
+            }break;
+            case SUBCMD_EVENT_LIST:{
+                if( (l_from_events_str == NULL) ||
+                        (strcmp(l_from_events_str,"round.new") == 0) ){
+                    char * l_gdb_group_events = DAP_CHAIN_CS_DAG(l_chain)->gdb_group_events_round_new;
+                    dap_string_t * l_str_tmp = dap_string_new("");
+                    if ( l_gdb_group_events ){
+                        dap_global_db_obj_t * l_objs;
+                        size_t l_objs_count = 0;
+                        l_objs = dap_chain_global_db_gr_load(l_gdb_group_events,&l_objs_count);
+                        dap_string_append_printf(l_str_tmp,"%s.%s: Found %u records :\n",l_net->pub.name,l_chain->name,l_objs_count);
+
+                        for (size_t i = 0; i< l_objs_count; i++){
+                            dap_chain_cs_dag_event_t * l_event = (dap_chain_cs_dag_event_t *) l_objs[i].value;
+                            char buf[50];
+                            time_t l_ts_create = (time_t) l_event->header.ts_created;
+                            dap_string_append_printf(l_str_tmp,"\t%s: ts_create=%s",
+                                                     l_objs[i].key, ctime_r( &l_ts_create,buf ) );
+
+                        }
+                        DAP_DELETE( l_gdb_group_events);
+                        if (l_objs && l_objs_count )
+                            dap_chain_global_db_objs_delete(l_objs, l_objs_count);
+                        ret = 0;
+                    } else {
+                        dap_string_append_printf(l_str_tmp,"%s.%s: Error! No GlobalDB group!\n",l_net->pub.name,l_chain->name);
+                        ret = -2;
+
+                    }
+                    dap_chain_node_cli_set_reply_text(a_str_reply, l_str_tmp->str);
+                    dap_string_free(l_str_tmp,false);
+                }else if (l_from_events_str && (strcmp(l_from_events_str,"events") == 0) ){
+                    dap_string_t * l_str_tmp = dap_string_new(NULL);
+                    size_t l_events_count = HASH_COUNT(PVT(l_dag)->events);
+                    dap_string_append_printf(l_str_tmp,"%s.%s: Have %u events :\n",
+                                             l_net->pub.name,l_chain->name,l_events_count);
+                    dap_chain_cs_dag_event_item_t * l_event_item = NULL,*l_event_item_tmp = NULL;
+                    HASH_ITER(hh,PVT(l_dag)->events,l_event_item, l_event_item_tmp ) {
+                        char buf[50];
+                        char * l_event_item_hash_str = dap_chain_hash_fast_to_str_new( &l_event_item->hash);
+                        time_t l_ts_create = (time_t) l_event_item->event->header.ts_created;
+                        dap_string_append_printf(l_str_tmp,"\t%s: ts_create=%s",
+                                                 l_event_item_hash_str, ctime_r( &l_ts_create,buf ) );
+                        DAP_DELETE(l_event_item_hash_str);
+                    }
+
+                    dap_chain_node_cli_set_reply_text(a_str_reply, l_str_tmp->str);
+                    dap_string_free(l_str_tmp,false);
+
+                }else {
+                    dap_chain_node_cli_set_reply_text(a_str_reply, "Undefined events source for listing ");
+                    ret=-14;
+
+                }
+            }break;
+
+            case SUBCMD_UNDEFINED: {
+                dap_chain_node_cli_set_reply_text(a_str_reply,
+                                                  "Undefined event subcommand \"%s\" ",
+                                                  l_event_cmd_str);
+                ret=-11;
+            }
+        }
+    }else {
+        dap_chain_node_cli_set_reply_text(a_str_reply,
+                                          "Undefined subcommand");
+        ret = -13;
+    }
+    return ret;
+}
diff --git a/libdap-chain-cs-dag/dap_chain_cs_dag.h b/libdap-chain-cs-dag/dap_chain_cs_dag.h
new file mode 100755
index 0000000000000000000000000000000000000000..0621df69b9f6dadf0a89fd07c08682b83729a39a
--- /dev/null
+++ b/libdap-chain-cs-dag/dap_chain_cs_dag.h
@@ -0,0 +1,72 @@
+/*
+ * Authors:
+ * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net      https://gitlab/demlabs
+ * Kelvin Project https://github.com/kelvinblockchain
+ * Copyright  (c) 2017-2018
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+    DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    DAP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#pragma once
+#include "dap_chain.h"
+#include "dap_chain_cs_dag_event.h"
+
+typedef struct dap_chain_cs_dag dap_chain_cs_dag_t;
+
+typedef void (*dap_chain_cs_dag_callback_t)(dap_chain_cs_dag_t *);
+typedef int (*dap_chain_cs_dag_callback_event_t)(dap_chain_cs_dag_t *, dap_chain_cs_dag_event_t *);
+
+
+
+typedef dap_chain_cs_dag_event_t * (*dap_chain_cs_dag_callback_event_create_t)(dap_chain_cs_dag_t *,
+                                                                               dap_chain_datum_t *,
+                                                                               dap_chain_hash_fast_t *,
+                                                                               size_t);
+
+typedef struct dap_chain_cs_dag
+{
+    dap_chain_t * chain;
+    bool is_single_line;
+    bool is_celled;
+    bool is_add_directy;
+    bool is_static_genesis_event;
+    dap_chain_hash_fast_t static_genesis_event_hash;
+
+    uint16_t datum_add_hashes_count;
+    char * gdb_group_events_round_new;
+
+    dap_chain_cs_dag_callback_t callback_delete;
+    dap_chain_cs_dag_callback_event_create_t callback_cs_event_create;
+    dap_chain_cs_dag_callback_event_t callback_cs_verify;
+
+    void * _pvt;
+    void * _inheritor;
+} dap_chain_cs_dag_t;
+
+#define DAP_CHAIN_CS_DAG(a) ( (dap_chain_cs_dag_t *) (a)->_inheritor)
+
+int dap_chain_cs_dag_init(void);
+void dap_chain_cs_dag_deinit(void);
+
+int dap_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg);
+void dap_chain_cs_dag_delete(dap_chain_t * a_chain);
+
+void dap_chain_cs_dag_proc_treshold(dap_chain_cs_dag_t * a_dag);
+void dap_chain_cs_dag_proc_event_round_new(dap_chain_cs_dag_t *a_dag);
+
+dap_chain_cs_dag_event_t* dap_chain_cs_dag_find_event_by_hash(dap_chain_cs_dag_t * a_dag,
+                                                              dap_chain_hash_fast_t * a_hash);
diff --git a/libdap-chain-cs-dag/dap_chain_cs_dag_event.c b/libdap-chain-cs-dag/dap_chain_cs_dag_event.c
new file mode 100755
index 0000000000000000000000000000000000000000..edf2b6621705cece4659efc2ddae1e91063a979d
--- /dev/null
+++ b/libdap-chain-cs-dag/dap_chain_cs_dag_event.c
@@ -0,0 +1,146 @@
+/*
+ * Authors:
+ * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net      https://gitlab/demlabs
+ * Kelvin Project https://github.com/kelvinblockchain
+ * Copyright  (c) 2017-2018
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+    DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    DAP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dap_common.h"
+#include "dap_enc_key.h"
+
+#include "dap_hash.h"
+#include "dap_sign.h"
+#include "dap_chain_datum.h"
+#include "dap_chain_cs_dag.h"
+#include "dap_chain_cs_dag_event.h"
+
+#define LOG_TAG "dap_chain_cs_dag_event"
+
+/**
+ * @brief dap_chain_cs_dag_event_new
+ * @param a_chain_id
+ * @param a_cell_id
+ * @param a_datum
+ * @param a_key
+ * @param a_hashes
+ * @param a_hashes_count
+ * @return
+ */
+dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_new(dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id, dap_chain_datum_t * a_datum
+                                                ,dap_enc_key_t * a_key ,
+                                                dap_chain_hash_fast_t * a_hashes, size_t a_hashes_count)
+{
+    size_t l_hashes_size = sizeof(*a_hashes)*a_hashes_count;
+    size_t l_datum_size =  dap_chain_datum_size(a_datum);
+    dap_chain_cs_dag_event_t * l_event_new = NULL;
+    size_t l_event_size = sizeof(l_event_new->header)
+            + l_hashes_size
+            + l_datum_size;
+    l_event_new = DAP_NEW_Z_SIZE(dap_chain_cs_dag_event_t, l_event_size);
+    l_event_new->header.ts_created = (uint64_t)time(NULL);
+    l_event_new->header.cell_id.uint64 = a_cell_id.uint64;
+    l_event_new->header.chain_id.uint64 = a_chain_id.uint64;
+    l_event_new->header.hash_count = a_hashes_count;
+
+    if ( l_hashes_size )
+        memcpy(l_event_new->hashes_n_datum_n_signs, a_hashes, l_hashes_size );
+
+    memcpy(l_event_new->hashes_n_datum_n_signs+l_hashes_size, a_datum,l_datum_size );
+
+    if ( a_key ){
+        dap_sign_t * l_sign = dap_sign_create(a_key,l_event_new,
+                                                          l_hashes_size+  sizeof(l_event_new->header)
+                                                          + l_datum_size ,0);
+        if ( l_sign ){
+            size_t l_sign_size = dap_sign_get_size(l_sign);
+            l_event_new = (dap_chain_cs_dag_event_t* )DAP_REALLOC(l_event_new,l_event_size+l_sign_size );
+            memcpy(l_event_new->hashes_n_datum_n_signs + l_hashes_size + l_datum_size, l_sign, l_sign_size);
+            l_event_size += l_sign_size;
+            l_event_new->header.signs_count++;
+            DAP_DELETE(l_sign);
+        }else {
+            log_it(L_ERROR,"Can't sign dag event!");
+            DAP_DELETE(l_event_new);
+            return NULL;
+        }
+    }else {
+        log_it(L_NOTICE, "Created unsigned dag event");
+    }
+    return l_event_new;
+}
+
+/**
+ * @brief dap_chain_cs_dag_event_deep_copy
+ * @param a_event_src
+ * @return
+ */
+dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_copy(dap_chain_cs_dag_event_t *a_event_src)
+{
+    if(!a_event_src)
+        return NULL;
+    size_t l_event_size = dap_chain_cs_dag_event_calc_size(a_event_src);
+    dap_chain_cs_dag_event_t *l_event_new = DAP_NEW_Z_SIZE(dap_chain_cs_dag_event_t, l_event_size);
+    memcpy(l_event_new, a_event_src, l_event_size);
+    return l_event_new;
+}
+
+/**
+ * @brief dap_chain_cs_dag_event_sign_add
+ * @param a_event
+ * @param l_key
+ * @return
+ */
+dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_copy_with_sign_add( dap_chain_cs_dag_event_t * a_event,
+                                                                      dap_enc_key_t * l_key)
+{
+    size_t l_event_size = dap_chain_cs_dag_event_calc_size( a_event );
+    size_t l_event_signing_size = dap_chain_cs_dag_event_calc_size_excl_signs( a_event );
+    dap_sign_t * l_sign = dap_sign_create(l_key,a_event,l_event_signing_size,0);
+    size_t l_sign_size = dap_sign_get_size(l_sign);
+    dap_chain_cs_dag_event_t *l_event_new = DAP_NEW_Z_SIZE(dap_chain_cs_dag_event_t, l_event_size+l_sign_size);
+    memcpy(l_event_new, a_event,l_event_size);
+    memcpy(l_event_new+l_event_size,l_sign,l_sign_size);
+    l_event_new->header.signs_count++;
+    return l_event_new;
+}
+
+/**
+ * @brief dap_chain_cs_dag_event_get_sign
+ * @param a_event
+ * @param a_sign_number
+ * @return
+ */
+dap_sign_t * dap_chain_cs_dag_event_get_sign( dap_chain_cs_dag_event_t * a_event, uint16_t a_sign_number)
+{
+    if (a_event->header.signs_count > a_sign_number ){
+        size_t l_offset_to_sign = dap_chain_cs_dag_event_calc_size_excl_signs(a_event);
+        uint8_t * l_signs = ((uint8_t*) a_event)+l_offset_to_sign;
+        uint16_t l_signs_offset = 0;
+        uint16_t l_signs_passed;
+        for ( l_signs_passed=0;  l_signs_passed < a_sign_number; l_signs_passed++){
+            dap_sign_t * l_sign = (dap_sign_t *) (l_signs+l_signs_offset);
+            l_signs_offset+=l_sign->header.sign_pkey_size+l_sign->header.sign_size+sizeof(l_sign->header);
+        }
+        return (dap_sign_t*) l_signs + l_signs_offset;
+    }else
+        return NULL;
+}
+
+
diff --git a/libdap-chain-cs-dag/dap_chain_cs_dag_event.h b/libdap-chain-cs-dag/dap_chain_cs_dag_event.h
new file mode 100755
index 0000000000000000000000000000000000000000..39b898d9b1e9123e8ed62b068287a85a0c31d3e6
--- /dev/null
+++ b/libdap-chain-cs-dag/dap_chain_cs_dag_event.h
@@ -0,0 +1,119 @@
+/*
+ * Authors:
+ * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net      https://gitlab/demlabs
+ * Kelvin Project https://github.com/kelvinblockchain
+ * Copyright  (c) 2017-2018
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+    DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    DAP is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#pragma once
+
+#include "dap_enc_key.h"
+#include "dap_chain_common.h"
+#include "dap_chain_datum.h"
+#include "dap_sign.h"
+#include "dap_hash.h"
+
+typedef struct dap_chain_cs_dag dap_chain_cs_dag_t;
+
+typedef struct dap_chain_class_dag_event_hdr {
+        uint16_t version;
+        uint64_t round_id;
+        uint64_t ts_created;
+        dap_chain_id_t chain_id;
+        dap_chain_cell_id_t cell_id; // Cell id if celled dag
+        uint16_t hash_count; // Number of hashes
+        uint16_t signs_count; // Number of signs nested with event
+} DAP_ALIGN_PACKED dap_chain_class_dag_event_hdr_t;
+
+typedef struct dap_chain_cs_dag_event {
+    dap_chain_class_dag_event_hdr_t header;
+    uint8_t hashes_n_datum_n_signs[]; // Hashes, signes and datum
+} DAP_ALIGN_PACKED dap_chain_cs_dag_event_t;
+
+
+dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_new(dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id, dap_chain_datum_t * a_datum,
+                                                dap_enc_key_t * a_key,
+                                                dap_chain_hash_fast_t * a_hashes, size_t a_hashes_count);
+
+
+/**
+ * @brief dap_chain_cs_dag_event_get_datum
+ * @param a_event
+ * @return
+ */
+static inline dap_chain_datum_t* dap_chain_cs_dag_event_get_datum(dap_chain_cs_dag_event_t * a_event)
+{
+    return (dap_chain_datum_t* ) (a_event->hashes_n_datum_n_signs
+            +a_event->header.hash_count*sizeof(dap_chain_hash_fast_t));
+}
+
+dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_copy(dap_chain_cs_dag_event_t *a_event_src);
+
+// Important: returns new deep copy of event
+dap_chain_cs_dag_event_t * dap_chain_cs_dag_event_copy_with_sign_add( dap_chain_cs_dag_event_t * a_event, dap_enc_key_t * l_key);
+dap_sign_t * dap_chain_cs_dag_event_get_sign( dap_chain_cs_dag_event_t * a_event, uint16_t a_sign_number);
+
+/**
+ * @brief dap_chain_cs_dag_event_calc_size
+ * @param a_event
+ * @return
+ */
+static inline size_t dap_chain_cs_dag_event_calc_size(dap_chain_cs_dag_event_t * a_event)
+{
+    if(!a_event)
+        return 0;
+    size_t l_hashes_size = a_event->header.hash_count*sizeof(dap_chain_hash_fast_t);
+    dap_chain_datum_t * l_datum = (dap_chain_datum_t*) (a_event->hashes_n_datum_n_signs + l_hashes_size);
+
+    size_t l_datum_size = dap_chain_datum_size(l_datum);
+    uint8_t * l_signs = a_event->hashes_n_datum_n_signs
+            +l_hashes_size+l_datum_size;
+    uint16_t l_signs_offset = 0;
+    uint16_t l_signs_passed;
+    for ( l_signs_passed=0;  l_signs_passed < a_event->header.signs_count; l_signs_passed++){
+        dap_sign_t * l_sign = (dap_sign_t *) l_signs+l_signs_offset;
+        l_signs_offset+=l_sign->header.sign_pkey_size+l_sign->header.sign_size+sizeof(l_sign->header);
+    }
+
+    return sizeof( a_event->header ) + l_hashes_size +l_signs_offset +l_datum_size;
+}
+
+/**
+ * @brief dap_chain_cs_dag_event_calc_size_excl_signs
+ * @param a_event
+ * @return
+ */
+static inline size_t dap_chain_cs_dag_event_calc_size_excl_signs(dap_chain_cs_dag_event_t * a_event)
+{
+    size_t l_hashes_size = a_event->header.hash_count*sizeof(dap_chain_hash_fast_t);
+    dap_chain_datum_t * l_datum = (dap_chain_datum_t*) (a_event->hashes_n_datum_n_signs + l_hashes_size);
+    size_t l_datum_size = dap_chain_datum_size(l_datum);
+    return  l_hashes_size + sizeof (a_event->header)+l_datum_size;
+}
+
+/**
+ * @brief dap_chain_cs_dag_event_calc_hash
+ * @details Important moment, it calculates hash of everything except signatures
+ * @param a_event
+ * @param a_event_hash
+ */
+static inline void dap_chain_cs_dag_event_calc_hash(dap_chain_cs_dag_event_t * a_event,dap_chain_hash_fast_t * a_event_hash)
+{
+    dap_hash_fast(a_event, dap_chain_cs_dag_event_calc_size (a_event) , a_event_hash);
+}