Repository: ergoplatform/sigma-rust (language: rust)

Issue:
[100 SigmaUSD] Move Header type from ergotree-ir to ergo-chain-types crate
Along with JSON serialization and `Arbitrary` implementation (behind `arbitrary` feature).


Discussion / hints:
Working on this one.
It seems much easier and cleaner to mergo ergo-chain-types logic to ergotree-ir, and wrap them outside. Otherwise, a lot of serde, even mir parts should be seperated from ergootree-ir, in case cyclic dependency.
@greenhat 
> It seems much easier and cleaner to mergo ergo-chain-types logic to ergotree-ir, and wrap them outside. Otherwise, a lot of serde, even mir parts should be seperated from ergootree-ir, in case cyclic dependency.

Is it because of `AutolykosSolution` (`EcPoint`)? That might be a showstopper. ergo-chain-types are meant to be lower in dependency graph than ergotree-ir, so if it's too much effort we probably should leave it as is. Could you push your code as a draft PR so could take a look?
@hanbu97 are you still working on this issue? If not, I'd like to work on this.
> @hanbu97 are you still working on this issue? If not, I'd like to work on this.

ok. please

Fix patch:
diff --git a/bindings/ergo-lib-c-core/src/block_header.rs b/bindings/ergo-lib-c-core/src/block_header.rs
index 290a1d52f..ddfdf19fc 100644
--- a/bindings/ergo-lib-c-core/src/block_header.rs
+++ b/bindings/ergo-lib-c-core/src/block_header.rs
@@ -4,7 +4,7 @@ use crate::{
     error::*,
     util::{const_ptr_as_ref, mut_ptr_as_mut},
 };
-use ergo_lib::ergotree_ir::chain::header::Header;
+use ergo_lib::ergo_chain_types::Header;
 
 /// Block header
 #[derive(PartialEq, Eq, Debug, Clone)]
diff --git a/bindings/ergo-lib-c-core/src/constant.rs b/bindings/ergo-lib-c-core/src/constant.rs
index 823866c62..356a72fbd 100644
--- a/bindings/ergo-lib-c-core/src/constant.rs
+++ b/bindings/ergo-lib-c-core/src/constant.rs
@@ -8,12 +8,12 @@ use crate::{
     Error,
 };
 use ergo_lib::{
-    ergo_chain_types::Base16DecodedBytes,
+    ergo_chain_types::{Base16DecodedBytes, EcPoint},
     ergotree_ir::{
         base16_str::Base16Str,
         mir::constant::{TryExtractFrom, TryExtractInto},
         serialization::SigmaSerializable,
-        sigma_protocol::{dlog_group::EcPoint, sigma_boolean::ProveDlog},
+        sigma_protocol::sigma_boolean::ProveDlog,
     },
 };
 
diff --git a/bindings/ergo-lib-c-core/src/header.rs b/bindings/ergo-lib-c-core/src/header.rs
index cfa377f01..846b96d24 100644
--- a/bindings/ergo-lib-c-core/src/header.rs
+++ b/bindings/ergo-lib-c-core/src/header.rs
@@ -5,7 +5,7 @@ use crate::{block_header::ConstBlockHeaderPtr, error::Error, util::const_ptr_as_
 /// Block header with the current `spendingTransaction`, that can be predicted
 /// by a miner before its formation
 #[derive(PartialEq, Eq, Debug, Clone)]
-pub struct PreHeader(pub ergo_lib::ergotree_ir::chain::preheader::PreHeader);
+pub struct PreHeader(pub ergo_lib::ergo_chain_types::PreHeader);
 pub type PreHeaderPtr = *mut PreHeader;
 pub type ConstPreHeaderPtr = *const PreHeader;
 
@@ -15,8 +15,8 @@ pub unsafe fn preheader_from_block_header(
     preheader_out: *mut PreHeaderPtr,
 ) -> Result<(), Error> {
     let block_header = const_ptr_as_ref(block_header_ptr, "block_header")?;
-    let bh: ergo_lib::ergotree_ir::chain::header::Header = block_header.0.clone();
-    let ph: ergo_lib::ergotree_ir::chain::preheader::PreHeader = bh.into();
+    let bh: ergo_lib::ergo_chain_types::Header = block_header.0.clone();
+    let ph: ergo_lib::ergo_chain_types::PreHeader = bh.into();
     *preheader_out = Box::into_raw(Box::new(PreHeader(ph)));
     Ok(())
 }
diff --git a/bindings/ergo-lib-wasm/src/address.rs b/bindings/ergo-lib-wasm/src/address.rs
index 325f9a57f..934862906 100644
--- a/bindings/ergo-lib-wasm/src/address.rs
+++ b/bindings/ergo-lib-wasm/src/address.rs
@@ -1,7 +1,7 @@
 //! Address types
 
+use ergo_lib::ergo_chain_types::EcPoint;
 use ergo_lib::ergotree_ir::serialization::SigmaSerializable;
-use ergo_lib::ergotree_ir::sigma_protocol::dlog_group::EcPoint;
 use ergo_lib::ergotree_ir::sigma_protocol::sigma_boolean::ProveDlog;
 use wasm_bindgen::prelude::*;
 
diff --git a/bindings/ergo-lib-wasm/src/ast.rs b/bindings/ergo-lib-wasm/src/ast.rs
index c362145cc..ba6b41658 100644
--- a/bindings/ergo-lib-wasm/src/ast.rs
+++ b/bindings/ergo-lib-wasm/src/ast.rs
@@ -4,10 +4,10 @@ use crate::ergo_box::ErgoBox;
 use crate::error_conversion::to_js;
 use crate::utils::I64;
 use ergo_lib::ergo_chain_types::Base16DecodedBytes;
+use ergo_lib::ergo_chain_types::EcPoint;
 use ergo_lib::ergotree_ir::base16_str::Base16Str;
 use ergo_lib::ergotree_ir::mir::constant::{TryExtractFrom, TryExtractInto};
 use ergo_lib::ergotree_ir::serialization::SigmaSerializable;
-use ergo_lib::ergotree_ir::sigma_protocol::dlog_group::EcPoint;
 use ergo_lib::ergotree_ir::sigma_protocol::sigma_boolean::ProveDlog;
 use js_sys::Uint8Array;
 use std::convert::TryFrom;
diff --git a/bindings/ergo-lib-wasm/src/block_header.rs b/bindings/ergo-lib-wasm/src/block_header.rs
index 8ea93dff9..528417d33 100644
--- a/bindings/ergo-lib-wasm/src/block_header.rs
+++ b/bindings/ergo-lib-wasm/src/block_header.rs
@@ -1,6 +1,6 @@
 //! Block header
 
-use ergo_lib::ergotree_ir::chain::header::Header;
+use ergo_lib::ergo_chain_types::Header;
 use wasm_bindgen::prelude::*;
 
 extern crate derive_more;
@@ -52,7 +52,7 @@ impl BlockHeaders {
                         .ok_or(JsValue::from_str("Expected BlockHeader JSON as string"))?;
                     serde_json::from_str(jb_str.as_str())
                 } else {
-                    jb.into_serde::<ergo_lib::ergotree_ir::chain::header::Header>()
+                    jb.into_serde::<ergo_lib::ergo_chain_types::Header>()
                 }
                 .map_err(|e| {
                     JsValue::from_str(&format!(
diff --git a/bindings/ergo-lib-wasm/src/header.rs b/bindings/ergo-lib-wasm/src/header.rs
index 82d118881..f1df493ee 100644
--- a/bindings/ergo-lib-wasm/src/header.rs
+++ b/bindings/ergo-lib-wasm/src/header.rs
@@ -10,14 +10,14 @@ use crate::block_header::BlockHeader;
 /// by a miner before it's formation
 #[wasm_bindgen]
 #[derive(PartialEq, Eq, Debug, Clone, From, Into)]
-pub struct PreHeader(ergo_lib::ergotree_ir::chain::preheader::PreHeader);
+pub struct PreHeader(ergo_lib::ergo_chain_types::PreHeader);
 
 #[wasm_bindgen]
 impl PreHeader {
     /// Create using data from block header
     pub fn from_block_header(block_header: BlockHeader) -> Self {
-        let bh: ergo_lib::ergotree_ir::chain::header::Header = block_header.into();
-        let ph: ergo_lib::ergotree_ir::chain::preheader::PreHeader = bh.into();
+        let bh: ergo_lib::ergo_chain_types::Header = block_header.into();
+        let ph: ergo_lib::ergo_chain_types::PreHeader = bh.into();
         ph.into()
     }
 }
diff --git a/ergo-chain-generation/Cargo.toml b/ergo-chain-generation/Cargo.toml
index ca81bbf5b..462b974bb 100644
--- a/ergo-chain-generation/Cargo.toml
+++ b/ergo-chain-generation/Cargo.toml
@@ -14,6 +14,7 @@ ergo-lib = {version = "^0.16.0", path = "../ergo-lib"}
 num-bigint = "0.4.0"
 rand = "0.8.4"
 sigma-test-util = { version = "^0.3.0", path = "../sigma-test-util" }
+ergo-chain-types = { version = "^0.3", path = "../ergo-chain-types" }
 ergo-nipopow = { version = "^0.3", path = "../ergo-nipopow" }
 ergo-merkle-tree = { version = "^0.3", path = "../ergo-merkle-tree" }
 
diff --git a/ergo-chain-generation/src/chain_generation.rs b/ergo-chain-generation/src/chain_generation.rs
index 235be6419..f2dfb5d4d 100644
--- a/ergo-chain-generation/src/chain_generation.rs
+++ b/ergo-chain-generation/src/chain_generation.rs
@@ -10,19 +10,6 @@ use ergo_lib::{
     },
     ergo_chain_types::{BlockId, Digest32},
 };
-use ergo_lib::{
-    ergo_chain_types::blake2b256_hash,
-    ergotree_ir::{
-        chain::{
-            ergo_box::{box_value::BoxValue, BoxId},
-            header::{AutolykosSolution, Header},
-            votes::Votes,
-        },
-        ergo_tree::ErgoTree,
-        serialization::{sigma_byte_writer::SigmaByteWriter, SigmaSerializable},
-        sigma_protocol::dlog_group::{order, EcPoint},
-    },
-};
 use ergo_lib::{
     ergo_chain_types::ADDigest,
     ergotree_interpreter::sigma_protocol::{
@@ -30,6 +17,15 @@ use ergo_lib::{
         prover::{ContextExtension, ProofBytes},
     },
 };
+use ergo_lib::{
+    ergo_chain_types::{blake2b256_hash, AutolykosSolution, EcPoint, Header, Votes},
+    ergotree_ir::{
+        chain::ergo_box::{box_value::BoxValue, BoxId},
+        ergo_tree::ErgoTree,
+        serialization::{sigma_byte_writer::SigmaByteWriter, SigmaSerializable},
+        sigma_protocol::dlog_group::order,
+    },
+};
 use ergo_merkle_tree::{MerkleNode, MerkleTree};
 use ergo_nipopow::NipopowAlgos;
 use num_bigint::{BigInt, Sign};
diff --git a/ergo-chain-generation/src/fake_pow_scheme.rs b/ergo-chain-generation/src/fake_pow_scheme.rs
index 03beecc99..b4de5ed21 100644
--- a/ergo-chain-generation/src/fake_pow_scheme.rs
+++ b/ergo-chain-generation/src/fake_pow_scheme.rs
@@ -10,14 +10,10 @@ mod tests {
     use ergo_lib::ergo_chain_types::{blake2b256_hash, ADDigest, BlockId, Digest32};
     use ergo_nipopow::{NipopowAlgos, NipopowProof};
 
+    use ergo_chain_types::{AutolykosSolution, EcPoint, Header, Votes};
     use ergo_lib::ergotree_interpreter::sigma_protocol::private_input::DlogProverInput;
     use ergo_lib::ergotree_ir::{
-        chain::{
-            header::{AutolykosSolution, Header},
-            votes::Votes,
-        },
-        serialization::sigma_byte_writer::SigmaByteWriter,
-        sigma_protocol::dlog_group::{order, EcPoint},
+        serialization::sigma_byte_writer::SigmaByteWriter, sigma_protocol::dlog_group::order,
     };
     use ergo_nipopow::PoPowHeader;
     use num_bigint::BigInt;
diff --git a/ergo-chain-generation/src/lib.rs b/ergo-chain-generation/src/lib.rs
index 8c7287d7f..656beaf16 100644
--- a/ergo-chain-generation/src/lib.rs
+++ b/ergo-chain-generation/src/lib.rs
@@ -17,7 +17,7 @@
 #![deny(clippy::unimplemented)]
 #![deny(clippy::panic)]
 
-use ergo_lib::ergotree_ir::chain::header::Header;
+use ergo_chain_types::Header;
 use ergo_lib::{
     ergo_chain_types::ExtensionCandidate,
     wallet::{ext_secret_key::ExtSecretKey, mnemonic::Mnemonic},
diff --git a/ergo-chain-types/Cargo.toml b/ergo-chain-types/Cargo.toml
index c3aab35e2..62aa11f29 100644
--- a/ergo-chain-types/Cargo.toml
+++ b/ergo-chain-types/Cargo.toml
@@ -24,6 +24,10 @@ proptest-derive = {version = "0.3.0", optional = true }
 serde = { version = "1.0", features = ["derive"], optional = true }
 serde_json = { version = "1.0", optional = true }
 url = "2.2"
+k256 = { version = "0.10.2", features = ["arithmetic", "ecdsa"] }
+elliptic-curve = {version = "0.11.6", features = [ "ff"]}
+num-bigint = "0.4.0"
+byteorder = "1"
 
 [dependencies.serde_with]
 version = "1.9.1"
diff --git a/ergo-chain-types/src/ec_point.rs b/ergo-chain-types/src/ec_point.rs
new file mode 100644
index 000000000..5dd3ea330
--- /dev/null
+++ b/ergo-chain-types/src/ec_point.rs
@@ -0,0 +1,173 @@
+//! Elliptic curve point.
+
+use elliptic_curve::group::prime::PrimeCurveAffine;
+use k256::elliptic_curve::sec1::ToEncodedPoint;
+use k256::{ProjectivePoint, PublicKey, Scalar};
+use sigma_ser::vlq_encode::{ReadSigmaVlqExt, WriteSigmaVlqExt};
+use sigma_ser::{ScorexParsingError, ScorexSerializable, ScorexSerializeResult};
+use std::convert::TryFrom;
+use std::ops::{Add, Mul, Neg};
+
+/// Elliptic curve point
+#[derive(PartialEq, Clone, Default)]
+#[cfg_attr(
+    feature = "json",
+    derive(serde::Serialize, serde::Deserialize),
+    serde(into = "String", try_from = "String")
+)]
+pub struct EcPoint(ProjectivePoint);
+
+#[allow(clippy::unwrap_used)]
+impl std::fmt::Debug for EcPoint {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        f.write_str("EC:")?;
+        f.write_str(&base16::encode_lower(
+            &self.scorex_serialize_bytes().unwrap(),
+        ))
+    }
+}
+
+impl EcPoint {
+    /// Number of bytes to represent any group element as byte array
+    pub const GROUP_SIZE: usize = 33;
+
+    /// Attempts to parse from Base16-encoded string
+    pub fn from_base16_str(str: String) -> Option<Self> {
+        base16::decode(&str)
+            .ok()
+            .and_then(|bytes| Self::scorex_parse_bytes(&bytes).ok())
+    }
+}
+
+impl TryFrom<String> for EcPoint {
+    type Error = String;
+    fn try_from(value: String) -> Result<Self, Self::Error> {
+        EcPoint::from_base16_str(value)
+            .ok_or_else(|| String::from("Ecpoint: error parsing from base16-encoded string"))
+    }
+}
+
+impl From<EcPoint> for String {
+    fn from(value: EcPoint) -> String {
+        #[allow(clippy::unwrap_used)]
+        {
+            let bytes = value.scorex_serialize_bytes().unwrap();
+            base16::encode_lower(&bytes)
+        }
+    }
+}
+
+impl Eq for EcPoint {}
+
+impl Mul<&EcPoint> for EcPoint {
+    type Output = EcPoint;
+
+    fn mul(self, other: &EcPoint) -> EcPoint {
+        EcPoint(ProjectivePoint::add(self.0, &other.0))
+    }
+}
+
+impl Neg for EcPoint {
+    type Output = EcPoint;
+
+    fn neg(self) -> EcPoint {
+        EcPoint(ProjectivePoint::neg(self.0))
+    }
+}
+
+/// The generator g of the group is an element of the group such that, when written multiplicatively, every element
+/// of the group is a power of g.
+pub fn generator() -> EcPoint {
+    EcPoint(ProjectivePoint::GENERATOR)
+}
+
+/// The identity(infinity) element
+pub const fn identity() -> EcPoint {
+    EcPoint(ProjectivePoint::IDENTITY)
+}
+
+/// Check if point is identity(infinity) element
+pub fn is_identity(ge: &EcPoint) -> bool {
+    *ge == identity()
+}
+
+/// Calculates the inverse of the given group element
+pub fn inverse(ec: &EcPoint) -> EcPoint {
+    -ec.clone()
+}
+
+/// Raises the base GroupElement to the exponent. The result is another GroupElement.
+pub fn exponentiate(base: &EcPoint, exponent: &Scalar) -> EcPoint {
+    if !is_identity(base) {
+        // we treat EC as a multiplicative group, therefore, exponentiate point is multiply.
+        EcPoint(base.0 * exponent)
+    } else {
+        base.clone()
+    }
+}
+
+impl ScorexSerializable for EcPoint {
+    fn scorex_serialize<W: WriteSigmaVlqExt>(&self, w: &mut W) -> ScorexSerializeResult {
+        let caff = self.0.to_affine();
+        if caff.is_identity().into() {
+            // infinity point
+            let zeroes = [0u8; EcPoint::GROUP_SIZE];
+            w.write_all(&zeroes)?;
+        } else {
+            w.write_all(caff.to_encoded_point(true).as_bytes())?;
+        }
+        Ok(())
+    }
+
+    fn scorex_parse<R: ReadSigmaVlqExt>(r: &mut R) -> Result<Self, ScorexParsingError> {
+        let mut buf = [0; EcPoint::GROUP_SIZE];
+        r.read_exact(&mut buf[..])?;
+        if buf[0] != 0 {
+            let pubkey = PublicKey::from_sec1_bytes(&buf[..]).map_err(|e| {
+                ScorexParsingError::Misc(format!("failed to parse PK from bytes: {:?}", e))
+            })?;
+            Ok(EcPoint(pubkey.to_projective()))
+        } else {
+            // infinity point
+            Ok(EcPoint(ProjectivePoint::IDENTITY))
+        }
+    }
+}
+
+/// Arbitrary impl for EcPoint
+#[cfg(feature = "arbitrary")]
+mod arbitrary {
+    use super::*;
+    use proptest::prelude::*;
+
+    impl Arbitrary for EcPoint {
+        type Parameters = ();
+        type Strategy = BoxedStrategy<Self>;
+
+        fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
+            prop_oneof![
+                Just(generator()),
+                Just(identity()), /*Just(random_element()),*/
+            ]
+            .boxed()
+        }
+    }
+}
+
+#[allow(clippy::unwrap_used)]
+#[cfg(test)]
+#[allow(clippy::panic)]
+mod tests {
+    use super::*;
+    use proptest::prelude::*;
+    use sigma_ser::scorex_serialize_roundtrip;
+
+    proptest! {
+
+        #[test]
+        fn ser_roundtrip(v in any::<EcPoint>()) {
+            prop_assert_eq![scorex_serialize_roundtrip(&v), v];
+        }
+
+    }
+}
diff --git a/ergotree-ir/src/chain/header.rs b/ergo-chain-types/src/header.rs
similarity index 92%
rename from ergotree-ir/src/chain/header.rs
rename to ergo-chain-types/src/header.rs
index 726280699..f47e4c37a 100644
--- a/ergotree-ir/src/chain/header.rs
+++ b/ergo-chain-types/src/header.rs
@@ -1,7 +1,5 @@
 //! Block header
-use ergo_chain_types::ADDigest;
-use ergo_chain_types::BlockId;
-use ergo_chain_types::Digest32;
+use crate::{ADDigest, BlockId, Digest32, EcPoint};
 use num_bigint::BigInt;
 use sigma_ser::vlq_encode::{ReadSigmaVlqExt, WriteSigmaVlqExt};
 use sigma_ser::{
@@ -10,11 +8,7 @@ use sigma_ser::{
 use sigma_util::hash::blake2b256_hash;
 use std::io::Write;
 
-use crate::serialization::sigma_byte_writer::SigmaByteWriter;
-use crate::sigma_protocol::dlog_group::{self, EcPoint};
-
-use super::preheader::PreHeader;
-use super::votes::Votes;
+use crate::votes::Votes;
 
 /// Represents data of the block header available in Sigma propositions.
 #[cfg_attr(feature = "json", derive(serde::Serialize, serde::Deserialize))]
@@ -64,7 +58,7 @@ impl Header {
     pub fn serialize_without_pow(&self) -> Result<Vec<u8>, ScorexSerializationError> {
         use byteorder::{BigEndian, WriteBytesExt};
         let mut data = Vec::new();
-        let mut w = SigmaByteWriter::new(&mut data, None);
+        let mut w = &mut data;
         w.put_u8(self.version)?;
         self.parent_id.0.scorex_serialize(&mut w)?;
         self.ad_proofs_root.scorex_serialize(&mut w)?;
@@ -189,8 +183,7 @@ impl ScorexSerializable for Header {
 
         let mut id_bytes = header.serialize_without_pow()?;
         let mut data = Vec::new();
-        let mut w = SigmaByteWriter::new(&mut data, None);
-        autolykos_solution.serialize_bytes(version, &mut w)?;
+        autolykos_solution.serialize_bytes(version, &mut data)?;
         id_bytes.extend(data);
         let id = BlockId(blake2b256_hash(&id_bytes).into());
         header.id = id;
@@ -205,17 +198,17 @@ impl ScorexSerializable for Header {
 pub struct AutolykosSolution {
     /// Public key of miner. Part of Autolykos solution.
     #[cfg_attr(feature = "json", serde(rename = "pk"))]
-    pub miner_pk: Box<dlog_group::EcPoint>,
+    pub miner_pk: Box<EcPoint>,
     /// One-time public key. Prevents revealing of miners secret.
     #[cfg_attr(feature = "json", serde(default, rename = "w"))]
-    pub pow_onetime_pk: Option<Box<dlog_group::EcPoint>>,
+    pub pow_onetime_pk: Option<Box<EcPoint>>,
     /// nonce
     #[cfg_attr(
         feature = "json",
         serde(
             rename = "n",
-            serialize_with = "crate::chain::json::autolykos_solution::as_base16_string",
-            deserialize_with = "crate::chain::json::autolykos_solution::from_base16_string"
+            serialize_with = "crate::json::autolykos_solution::as_base16_string",
+            deserialize_with = "crate::json::autolykos_solution::from_base16_string"
         )
     )]
     pub nonce: Vec<u8>,
@@ -232,8 +225,8 @@ pub struct AutolykosSolution {
         serde(
             default,
             rename = "d",
-            serialize_with = "crate::chain::json::autolykos_solution::bigint_as_str",
-            deserialize_with = "crate::chain::json::autolykos_solution::bigint_from_serde_json_number"
+            serialize_with = "crate::json::autolykos_solution::bigint_as_str",
+            deserialize_with = "crate::json::autolykos_solution::bigint_from_serde_json_number"
         )
     )]
     pub pow_distance: Option<BigInt>,
@@ -274,29 +267,11 @@ impl AutolykosSolution {
     }
 }
 
-impl From<Header> for PreHeader {
-    fn from(bh: Header) -> Self {
-        PreHeader {
-            version: bh.version,
-            parent_id: bh.parent_id,
-            timestamp: bh.timestamp,
-            n_bits: bh.n_bits,
-            height: bh.height,
-            miner_pk: bh.autolykos_solution.miner_pk,
-            votes: bh.votes,
-        }
-    }
-}
-
 #[cfg(feature = "arbitrary")]
 #[allow(clippy::unwrap_used)]
 mod arbitrary {
 
-    use crate::serialization::sigma_byte_writer::SigmaByteWriter;
-    use crate::sigma_protocol::dlog_group::EcPoint;
-    use ergo_chain_types::Digest;
-    use ergo_chain_types::Digest32;
-    use ergo_chain_types::{blake2b256_hash, ADDigest};
+    use crate::*;
     use num_bigint::BigInt;
     use proptest::array::{uniform3, uniform32};
     use proptest::prelude::*;
@@ -357,7 +332,7 @@ mod arbitrary {
                         };
                         let mut id_bytes = header.serialize_without_pow().unwrap();
                         let mut data = Vec::new();
-                        let mut w = SigmaByteWriter::new(&mut data, None);
+                        let mut w = &mut data;
                         autolykos_solution.serialize_bytes(version, &mut w).unwrap();
                         id_bytes.extend(data);
                         let id = BlockId(blake2b256_hash(&id_bytes));
@@ -412,7 +387,7 @@ mod tests {
 
     use num_bigint::BigInt;
 
-    use crate::chain::header::Header;
+    use crate::header::Header;
     use proptest::prelude::*;
     use sigma_ser::scorex_serialize_roundtrip;
 
diff --git a/ergo-chain-types/src/json.rs b/ergo-chain-types/src/json.rs
new file mode 100644
index 000000000..674c0108c
--- /dev/null
+++ b/ergo-chain-types/src/json.rs
@@ -0,0 +1,4 @@
+//! JSON serialization
+
+pub(crate) mod autolykos_solution;
+pub(crate) mod votes;
diff --git a/ergotree-ir/src/chain/json/autolykos_solution.rs b/ergo-chain-types/src/json/autolykos_solution.rs
similarity index 100%
rename from ergotree-ir/src/chain/json/autolykos_solution.rs
rename to ergo-chain-types/src/json/autolykos_solution.rs
diff --git a/ergotree-ir/src/chain/json/votes.rs b/ergo-chain-types/src/json/votes.rs
similarity index 94%
rename from ergotree-ir/src/chain/json/votes.rs
rename to ergo-chain-types/src/json/votes.rs
index 6caef3ec3..996cc4018 100644
--- a/ergotree-ir/src/chain/json/votes.rs
+++ b/ergo-chain-types/src/json/votes.rs
@@ -2,8 +2,8 @@
 
 use std::convert::{TryFrom, TryInto};
 
-use crate::chain::votes::{Votes, VotesError};
-use ergo_chain_types::Base16DecodedBytes;
+use crate::votes::{Votes, VotesError};
+use crate::Base16DecodedBytes;
 
 #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
 #[serde(untagged)]
diff --git a/ergo-chain-types/src/lib.rs b/ergo-chain-types/src/lib.rs
index 68db918ff..1e1709787 100644
--- a/ergo-chain-types/src/lib.rs
+++ b/ergo-chain-types/src/lib.rs
@@ -20,9 +20,14 @@
 mod base16_bytes;
 mod block_id;
 mod digest32;
+pub mod ec_point;
 mod extensioncandidate;
+mod header;
+mod json;
 mod peer_addr;
 mod peer_connection_dir;
+mod preheader;
+mod votes;
 
 pub use base16_bytes::Base16DecodedBytes;
 pub use base16_bytes::Base16EncodedBytes;
@@ -32,6 +37,10 @@ pub use digest32::ADDigest;
 pub use digest32::Digest;
 pub use digest32::Digest32;
 pub use digest32::DigestNError;
+pub use ec_point::EcPoint;
 pub use extensioncandidate::ExtensionCandidate;
+pub use header::{AutolykosSolution, Header};
 pub use peer_addr::PeerAddr;
 pub use peer_connection_dir::ConnectionDirection;
+pub use preheader::PreHeader;
+pub use votes::Votes;
diff --git a/ergotree-ir/src/chain/preheader.rs b/ergo-chain-types/src/preheader.rs
similarity index 79%
rename from ergotree-ir/src/chain/preheader.rs
rename to ergo-chain-types/src/preheader.rs
index aab5b4361..2923c3599 100644
--- a/ergotree-ir/src/chain/preheader.rs
+++ b/ergo-chain-types/src/preheader.rs
@@ -1,10 +1,5 @@
 //! Block header with fields that can be predicted by miner
-
-use ergo_chain_types::BlockId;
-
-use crate::sigma_protocol::dlog_group;
-
-use super::votes::Votes;
+use crate::{BlockId, EcPoint, Header, Votes};
 
 /// Block header with the current `spendingTransaction`, that can be predicted
 /// by a miner before it's formation
@@ -21,17 +16,31 @@ pub struct PreHeader {
     /// Block height
     pub height: u32,
     /// Public key of miner
-    pub miner_pk: Box<dlog_group::EcPoint>,
+    pub miner_pk: Box<EcPoint>,
     /// Votes
     pub votes: Votes,
 }
 
+impl From<Header> for PreHeader {
+    fn from(bh: Header) -> Self {
+        PreHeader {
+            version: bh.version,
+            parent_id: bh.parent_id,
+            timestamp: bh.timestamp,
+            n_bits: bh.n_bits,
+            height: bh.height,
+            miner_pk: bh.autolykos_solution.miner_pk,
+            votes: bh.votes,
+        }
+    }
+}
+
 #[cfg(feature = "arbitrary")]
 mod arbitrary {
     use proptest::array::{uniform3, uniform32};
     use proptest::prelude::*;
 
-    use crate::sigma_protocol::dlog_group::EcPoint;
+    use crate::EcPoint;
 
     use super::*;
 
diff --git a/ergotree-ir/src/chain/votes.rs b/ergo-chain-types/src/votes.rs
similarity index 89%
rename from ergotree-ir/src/chain/votes.rs
rename to ergo-chain-types/src/votes.rs
index 6b9091a18..4a51c8dba 100644
--- a/ergotree-ir/src/chain/votes.rs
+++ b/ergo-chain-types/src/votes.rs
@@ -1,5 +1,5 @@
 //! Main "remote" type for [Vote]()
-use ergo_chain_types::{Base16DecodedBytes, Base16EncodedBytes};
+use crate::{Base16DecodedBytes, Base16EncodedBytes};
 use thiserror::Error;
 
 use std::convert::{TryFrom, TryInto};
@@ -11,7 +11,7 @@ use std::convert::{TryFrom, TryInto};
     feature = "json",
     serde(
         into = "Base16EncodedBytes",
-        try_from = "crate::chain::json::votes::VotesEncodingVariants"
+        try_from = "crate::json::votes::VotesEncodingVariants"
     )
 )]
 pub struct Votes(pub [u8; 3]);
diff --git a/ergo-lib/src/chain/ergo_state_context.rs b/ergo-lib/src/chain/ergo_state_context.rs
index 07b629387..53623af3e 100644
--- a/ergo-lib/src/chain/ergo_state_context.rs
+++ b/ergo-lib/src/chain/ergo_state_context.rs
@@ -1,6 +1,5 @@
 //! Blockchain state
-use ergotree_ir::chain::header::Header;
-use ergotree_ir::chain::preheader::PreHeader;
+use ergo_chain_types::{Header, PreHeader};
 
 /// Fixed number of last block headers in descending order (first header is the newest one)
 pub type Headers = [Header; 10];
diff --git a/ergo-lib/src/wallet/ext_pub_key.rs b/ergo-lib/src/wallet/ext_pub_key.rs
index 5c379033a..91b645216 100644
--- a/ergo-lib/src/wallet/ext_pub_key.rs
+++ b/ergo-lib/src/wallet/ext_pub_key.rs
@@ -1,12 +1,11 @@
 //! Extended public key operations according to BIP-32
 use std::convert::TryInto;
 
+use ergo_chain_types::EcPoint;
 use ergotree_interpreter::sigma_protocol::private_input::DlogProverInput;
 use ergotree_ir::chain::address::Address;
 use ergotree_ir::serialization::SigmaParsingError;
 use ergotree_ir::serialization::SigmaSerializable;
-use ergotree_ir::sigma_protocol::dlog_group;
-use ergotree_ir::sigma_protocol::dlog_group::EcPoint;
 use hmac::{Hmac, Mac, NewMac};
 use sha2::Sha512;
 use thiserror::Error;
@@ -87,7 +86,7 @@ impl ExtPubKey {
         secret_key_bytes.copy_from_slice(&mac_bytes[..32]);
         if let Some(child_secret_key) = DlogProverInput::from_bytes(&secret_key_bytes) {
             let child_pub_key = *child_secret_key.public_image().h * &self.public_key;
-            if dlog_group::is_identity(&child_pub_key) {
+            if ergo_chain_types::ec_point::is_identity(&child_pub_key) {
                 // point is infinity element, thus repeat with next index value (see BIP-32)
                 self.child(index.next())
             } else {
diff --git a/ergo-lib/src/wallet/multi_sig.rs b/ergo-lib/src/wallet/multi_sig.rs
index 3c77b81de..118103cc1 100644
--- a/ergo-lib/src/wallet/multi_sig.rs
+++ b/ergo-lib/src/wallet/multi_sig.rs
@@ -459,7 +459,6 @@ mod tests {
     use crate::ergotree_ir::mir::expr::Expr;
     use crate::ergotree_ir::mir::sigma_and::SigmaAnd;
     use crate::ergotree_ir::serialization::SigmaSerializable;
-    use crate::ergotree_ir::sigma_protocol::dlog_group;
     use crate::ergotree_ir::sigma_protocol::sigma_boolean::cand::Cand;
     use ergo_chain_types::Base16DecodedBytes;
     use ergotree_interpreter::sigma_protocol::private_input::DhTupleProverInput;
@@ -653,7 +652,8 @@ mod tests {
             assert_eq!(comm.position, NodePosition::crypto_tree_prefix());
             r = Some(comm.secret_randomness);
         }
-        let g_to_r = dlog_group::exponentiate(&dlog_group::generator(), &r.unwrap());
+        use ergo_chain_types::ec_point::{exponentiate, generator};
+        let g_to_r = exponentiate(&generator(), &r.unwrap());
         assert_eq!(
             FirstProverMessage::FirstDlogProverMessage(g_to_r.into()),
             a.unwrap()
diff --git a/ergo-nipopow/src/autolykos_pow_scheme.rs b/ergo-nipopow/src/autolykos_pow_scheme.rs
index 9cb9ca252..69f10878f 100644
--- a/ergo-nipopow/src/autolykos_pow_scheme.rs
+++ b/ergo-nipopow/src/autolykos_pow_scheme.rs
@@ -1,6 +1,6 @@
 use bounded_integer::{BoundedI32, BoundedU64};
 use derive_more::From;
-use ergotree_ir::chain::header::Header;
+use ergo_chain_types::Header;
 use num_bigint::{BigInt, Sign};
 use sigma_ser::ScorexSerializationError;
 use sigma_util::hash::blake2b256_hash;
diff --git a/ergo-nipopow/src/nipopow_algos.rs b/ergo-nipopow/src/nipopow_algos.rs
index 7a5acda47..655d261d0 100644
--- a/ergo-nipopow/src/nipopow_algos.rs
+++ b/ergo-nipopow/src/nipopow_algos.rs
@@ -1,4 +1,5 @@
-use ergotree_ir::{chain::header::Header, sigma_protocol::dlog_group::order};
+use ergo_chain_types::Header;
+use ergotree_ir::sigma_protocol::dlog_group::order;
 use num_bigint::BigInt;
 use num_traits::ToPrimitive;
 use std::convert::TryInto;
diff --git a/ergo-nipopow/src/nipopow_proof.rs b/ergo-nipopow/src/nipopow_proof.rs
index 3e292e5f8..f5d4048df 100644
--- a/ergo-nipopow/src/nipopow_proof.rs
+++ b/ergo-nipopow/src/nipopow_proof.rs
@@ -1,7 +1,6 @@
 use derive_more::From;
-use ergo_chain_types::BlockId;
+use ergo_chain_types::{BlockId, Header};
 use ergo_merkle_tree::BatchMerkleProof;
-use ergotree_ir::chain::header::Header;
 use serde::{Deserialize, Serialize};
 use sigma_ser::{
     vlq_encode::{ReadSigmaVlqExt, WriteSigmaVlqExt},
diff --git a/ergo-nipopow/src/nipopow_verifier.rs b/ergo-nipopow/src/nipopow_verifier.rs
index f535d8a8e..75c936e6f 100644
--- a/ergo-nipopow/src/nipopow_verifier.rs
+++ b/ergo-nipopow/src/nipopow_verifier.rs
@@ -1,5 +1,5 @@
 use ergo_chain_types::BlockId;
-use ergotree_ir::chain::header::Header;
+use ergo_chain_types::Header;
 
 use crate::nipopow_proof::{NipopowProof, NipopowProofError};
 
diff --git a/ergotree-interpreter/src/eval/context.rs b/ergotree-interpreter/src/eval/context.rs
index 4b6f35d56..f4cecccc6 100644
--- a/ergotree-interpreter/src/eval/context.rs
+++ b/ergotree-interpreter/src/eval/context.rs
@@ -2,9 +2,8 @@ use std::rc::Rc;
 
 use crate::sigma_protocol::prover::ContextExtension;
 use bounded_vec::BoundedVec;
+use ergo_chain_types::{Header, PreHeader};
 use ergotree_ir::chain::ergo_box::ErgoBox;
-use ergotree_ir::chain::header::Header;
-use ergotree_ir::chain::preheader::PreHeader;
 
 /// BoundedVec type for Tx inputs, output_candidates and outputs
 pub type TxIoVec<T> = BoundedVec<T, 1, { u16::MAX as usize }>;
diff --git a/ergotree-interpreter/src/eval/create_prove_dh_tuple.rs b/ergotree-interpreter/src/eval/create_prove_dh_tuple.rs
index f529f4143..d06f9c604 100644
--- a/ergotree-interpreter/src/eval/create_prove_dh_tuple.rs
+++ b/ergotree-interpreter/src/eval/create_prove_dh_tuple.rs
@@ -1,7 +1,7 @@
+use ergo_chain_types::EcPoint;
 use ergotree_ir::mir::constant::TryExtractInto;
 use ergotree_ir::mir::create_prove_dh_tuple::CreateProveDhTuple;
 use ergotree_ir::mir::value::Value;
-use ergotree_ir::sigma_protocol::dlog_group::EcPoint;
 use ergotree_ir::sigma_protocol::sigma_boolean::ProveDhTuple;
 
 use crate::eval::env::Env;
diff --git a/ergotree-interpreter/src/eval/decode_point.rs b/ergotree-interpreter/src/eval/decode_point.rs
index ecd501850..8ef37704b 100644
--- a/ergotree-interpreter/src/eval/decode_point.rs
+++ b/ergotree-interpreter/src/eval/decode_point.rs
@@ -6,9 +6,9 @@ use crate::eval::EvalContext;
 use crate::eval::EvalError;
 use crate::eval::EvalError::Misc;
 use crate::eval::Evaluable;
+use ergo_chain_types::EcPoint;
 use ergotree_ir::mir::constant::TryExtractInto;
 use ergotree_ir::serialization::SigmaSerializable;
-use ergotree_ir::sigma_protocol::dlog_group::EcPoint;
 
 impl Evaluable for DecodePoint {
     fn eval(&self, env: &Env, ctx: &mut EvalContext) -> Result<Value, EvalError> {
diff --git a/ergotree-interpreter/src/eval/exponentiate.rs b/ergotree-interpreter/src/eval/exponentiate.rs
index baa430a82..7439d11ee 100644
--- a/ergotree-interpreter/src/eval/exponentiate.rs
+++ b/ergotree-interpreter/src/eval/exponentiate.rs
@@ -20,7 +20,7 @@ impl Evaluable for Exponentiate {
 
         match (left_v.clone(), exp_scalar) {
             (Value::GroupElement(group), Some(exp)) => {
-                Ok(dlog_group::exponentiate(&group, &exp).into())
+                Ok(ergo_chain_types::ec_point::exponentiate(&group, &exp).into())
             }
             _ => Err(EvalError::UnexpectedValue(format!(
                 "Exponentiate input should be GroupElement, BigInt (positive, <= 256 bit). Received: {0:?}",
@@ -39,9 +39,10 @@ mod tests {
     use crate::eval::tests::{eval_out, try_eval_out};
     use crate::sigma_protocol::private_input::DlogProverInput;
 
+    use ergo_chain_types::EcPoint;
     use ergotree_ir::bigint256::BigInt256;
     use ergotree_ir::mir::expr::Expr;
-    use ergotree_ir::sigma_protocol::dlog_group::{scalar_to_bigint256, EcPoint};
+    use ergotree_ir::sigma_protocol::dlog_group::scalar_to_bigint256;
     use num_traits::Num;
     use proptest::prelude::*;
     use sigma_test_util::force_any_val;
@@ -55,7 +56,7 @@ mod tests {
             // can be converted to a BigInt256 and back
             let right: BigInt256 = scalar_to_bigint256(pi.w >> 1).unwrap();
 
-            let expected_exp = dlog_group::exponentiate(
+            let expected_exp = ergo_chain_types::ec_point::exponentiate(
                 &left,
                 &dlog_group::bigint256_to_scalar(right.clone()).unwrap()
             );
diff --git a/ergotree-interpreter/src/eval/global_vars.rs b/ergotree-interpreter/src/eval/global_vars.rs
index 125e33d6f..d5e6f04bf 100644
--- a/ergotree-interpreter/src/eval/global_vars.rs
+++ b/ergotree-interpreter/src/eval/global_vars.rs
@@ -2,7 +2,6 @@ use crate::eval::Env;
 use ergotree_ir::mir::global_vars::GlobalVars;
 use ergotree_ir::mir::value::Value;
 use ergotree_ir::serialization::SigmaSerializable;
-use ergotree_ir::sigma_protocol::dlog_group;
 
 use super::EvalContext;
 use super::EvalError;
@@ -18,7 +17,7 @@ impl Evaluable for GlobalVars {
             GlobalVars::MinerPubKey => {
                 Ok(ectx.ctx.pre_header.miner_pk.sigma_serialize_bytes()?.into())
             }
-            GlobalVars::GroupGenerator => Ok(dlog_group::generator().into()),
+            GlobalVars::GroupGenerator => Ok(ergo_chain_types::ec_point::generator().into()),
         }
     }
 }
@@ -30,10 +29,10 @@ mod tests {
 
     use crate::eval::context::Context;
     use crate::eval::tests::eval_out;
+    use ergo_chain_types::EcPoint;
     use ergoscript_compiler::compiler::compile_expr;
     use ergoscript_compiler::script_env::ScriptEnv;
     use ergotree_ir::chain::ergo_box::ErgoBox;
-    use ergotree_ir::sigma_protocol::dlog_group::EcPoint;
     use sigma_test_util::force_any_val;
 
     use super::*;
@@ -77,7 +76,7 @@ mod tests {
         let ctx = Rc::new(force_any_val::<Context>());
         assert_eq!(
             eval_out::<EcPoint>(&GlobalVars::GroupGenerator.into(), ctx),
-            dlog_group::generator()
+            ergo_chain_types::ec_point::generator()
         );
     }
 }
diff --git a/ergotree-interpreter/src/eval/multiply_group.rs b/ergotree-interpreter/src/eval/multiply_group.rs
index 15ab44f8b..de6d8a732 100644
--- a/ergotree-interpreter/src/eval/multiply_group.rs
+++ b/ergotree-interpreter/src/eval/multiply_group.rs
@@ -29,8 +29,8 @@ mod tests {
     use crate::eval::context::Context;
     use crate::eval::tests::eval_out;
 
+    use ergo_chain_types::EcPoint;
     use ergotree_ir::mir::expr::Expr;
-    use ergotree_ir::sigma_protocol::dlog_group::EcPoint;
     use proptest::prelude::*;
     use sigma_test_util::force_any_val;
     use std::rc::Rc;
diff --git a/ergotree-interpreter/src/eval/scontext.rs b/ergotree-interpreter/src/eval/scontext.rs
index 1b12abdf8..63ac60038 100644
--- a/ergotree-interpreter/src/eval/scontext.rs
+++ b/ergotree-interpreter/src/eval/scontext.rs
@@ -93,9 +93,8 @@ pub(crate) static LAST_BLOCK_UTXO_ROOT_HASH_EVAL_FN: EvalFn = |_env, ctx, obj, _
 mod tests {
     use crate::eval::context::{Context, TxIoVec};
     use crate::eval::tests::eval_out;
+    use ergo_chain_types::{Header, PreHeader};
     use ergotree_ir::chain::ergo_box::ErgoBox;
-    use ergotree_ir::chain::header::Header;
-    use ergotree_ir::chain::preheader::PreHeader;
     use ergotree_ir::mir::avl_tree_data::{AvlTreeData, AvlTreeFlags};
     use ergotree_ir::mir::expr::Expr;
     use ergotree_ir::mir::property_call::PropertyCall;
diff --git a/ergotree-interpreter/src/eval/sglobal.rs b/ergotree-interpreter/src/eval/sglobal.rs
index f5c9ec09d..6b694ec21 100644
--- a/ergotree-interpreter/src/eval/sglobal.rs
+++ b/ergotree-interpreter/src/eval/sglobal.rs
@@ -2,7 +2,7 @@ use crate::eval::EvalError;
 
 use ergotree_ir::mir::value::{CollKind, NativeColl, Value};
 
-use ergotree_ir::sigma_protocol::dlog_group::generator;
+use ergo_chain_types::ec_point::generator;
 
 use super::EvalFn;
 
@@ -56,11 +56,10 @@ pub(crate) static XOR_EVAL_FN: EvalFn = |_env, _ctx, obj, args| {
 #[cfg(test)]
 #[cfg(feature = "arbitrary")]
 mod tests {
+    use ergo_chain_types::EcPoint;
     use ergotree_ir::mir::expr::Expr;
     use ergotree_ir::mir::method_call::MethodCall;
     use ergotree_ir::mir::property_call::PropertyCall;
-    use ergotree_ir::sigma_protocol::dlog_group;
-    use ergotree_ir::sigma_protocol::dlog_group::EcPoint;
     use std::rc::Rc;
 
     use crate::eval::context::Context;
@@ -74,7 +73,10 @@ mod tests {
             .unwrap()
             .into();
         let ctx = Rc::new(force_any_val::<Context>());
-        assert_eq!(eval_out::<EcPoint>(&expr, ctx), dlog_group::generator());
+        assert_eq!(
+            eval_out::<EcPoint>(&expr, ctx),
+            ergo_chain_types::ec_point::generator()
+        );
     }
 
     #[test]
diff --git a/ergotree-interpreter/src/eval/sgroup_elem.rs b/ergotree-interpreter/src/eval/sgroup_elem.rs
index cd9faaa62..1a57139c9 100644
--- a/ergotree-interpreter/src/eval/sgroup_elem.rs
+++ b/ergotree-interpreter/src/eval/sgroup_elem.rs
@@ -1,8 +1,8 @@
 use crate::eval::EvalError;
 
+use ergo_chain_types::EcPoint;
 use ergotree_ir::mir::value::Value;
 use ergotree_ir::serialization::SigmaSerializable;
-use ergotree_ir::sigma_protocol::dlog_group::EcPoint;
 
 use super::EvalFn;
 
@@ -38,8 +38,8 @@ mod tests {
     use ergotree_ir::types::sgroup_elem;
 
     use crate::eval::tests::eval_out_wo_ctx;
+    use ergo_chain_types::EcPoint;
     use ergotree_ir::serialization::SigmaSerializable;
-    use ergotree_ir::sigma_protocol::dlog_group::EcPoint;
     use sigma_test_util::force_any_val;
 
     #[test]
diff --git a/ergotree-interpreter/src/eval/sheader.rs b/ergotree-interpreter/src/eval/sheader.rs
index d37631225..4917e3a5a 100644
--- a/ergotree-interpreter/src/eval/sheader.rs
+++ b/ergotree-interpreter/src/eval/sheader.rs
@@ -2,10 +2,8 @@
 
 use std::convert::TryInto;
 
-use ergotree_ir::{
-    bigint256::BigInt256, chain::header::Header, mir::constant::TryExtractInto,
-    sigma_protocol::dlog_group::EcPoint,
-};
+use ergo_chain_types::{EcPoint, Header};
+use ergotree_ir::{bigint256::BigInt256, mir::constant::TryExtractInto};
 
 use super::{EvalError, EvalFn};
 
@@ -101,12 +99,10 @@ mod tests {
     use std::convert::{TryFrom, TryInto};
     use std::rc::Rc;
 
-    use ergo_chain_types::{BlockId, Digest, Digest32};
+    use ergo_chain_types::{BlockId, Digest, Digest32, EcPoint, Votes};
     use ergotree_ir::{
         bigint256::BigInt256,
-        chain::votes::Votes,
         mir::{coll_by_index::ByIndex, expr::Expr, property_call::PropertyCall},
-        sigma_protocol::dlog_group::EcPoint,
         types::{scontext, sheader, smethod::SMethod},
     };
     use sigma_test_util::force_any_val;
diff --git a/ergotree-interpreter/src/eval/spreheader.rs b/ergotree-interpreter/src/eval/spreheader.rs
index 7ba08bb12..22d12747c 100644
--- a/ergotree-interpreter/src/eval/spreheader.rs
+++ b/ergotree-interpreter/src/eval/spreheader.rs
@@ -1,4 +1,5 @@
-use ergotree_ir::{chain::preheader::PreHeader, mir::constant::TryExtractInto};
+use ergo_chain_types::PreHeader;
+use ergotree_ir::mir::constant::TryExtractInto;
 
 use super::EvalFn;
 
@@ -44,11 +45,9 @@ mod tests {
     use std::convert::{TryFrom, TryInto};
     use std::rc::Rc;
 
-    use ergo_chain_types::BlockId;
+    use ergo_chain_types::{BlockId, EcPoint, Votes};
     use ergotree_ir::{
-        chain::votes::Votes,
         mir::{expr::Expr, property_call::PropertyCall},
-        sigma_protocol::dlog_group::EcPoint,
         types::{scontext, smethod::SMethod, spreheader},
     };
     use sigma_test_util::force_any_val;
diff --git a/ergotree-interpreter/src/sigma_protocol/dht_protocol.rs b/ergotree-interpreter/src/sigma_protocol/dht_protocol.rs
index ca7d60986..54cc2ca5c 100644
--- a/ergotree-interpreter/src/sigma_protocol/dht_protocol.rs
+++ b/ergotree-interpreter/src/sigma_protocol/dht_protocol.rs
@@ -1,8 +1,8 @@
 //! Discrete logarithm signature protocol
 
 use super::ProverMessage;
+use ergo_chain_types::EcPoint;
 use ergotree_ir::serialization::SigmaSerializable;
-use ergotree_ir::sigma_protocol::dlog_group::EcPoint;
 use k256::Scalar;
 
 /// a = g^r, b = h^r
@@ -60,16 +60,17 @@ pub mod interactive_prover {
         public_input: &ProveDhTuple,
         challenge: &Challenge,
     ) -> (FirstDhTupleProverMessage, SecondDhTupleProverMessage) {
+        use ergo_chain_types::ec_point::exponentiate;
         //SAMPLE a random z <- Zq
         let z = dlog_group::random_scalar_in_group_range(crypto_utils::secure_rng());
 
         // COMPUTE a = g^z*u^(-e) and b = h^z*v^{-e}  (where -e here means -e mod q)
         let e: Scalar = challenge.clone().into();
         let minus_e = e.negate();
-        let h_to_z = dlog_group::exponentiate(&public_input.h, &z);
-        let g_to_z = dlog_group::exponentiate(&public_input.g, &z);
-        let u_to_minus_e = dlog_group::exponentiate(&public_input.u, &minus_e);
-        let v_to_minus_e = dlog_group::exponentiate(&public_input.v, &minus_e);
+        let h_to_z = exponentiate(&public_input.h, &z);
+        let g_to_z = exponentiate(&public_input.g, &z);
+        let u_to_minus_e = exponentiate(&public_input.u, &minus_e);
+        let v_to_minus_e = exponentiate(&public_input.v, &minus_e);
         let a = g_to_z.mul(&u_to_minus_e);
         let b = h_to_z.mul(&v_to_minus_e);
         (
@@ -84,9 +85,10 @@ pub mod interactive_prover {
     ///
     /// In this case (DH tuple) "a" is also a tuple
     pub fn first_message(public_input: &ProveDhTuple) -> (Scalar, FirstDhTupleProverMessage) {
+        use ergo_chain_types::ec_point::exponentiate;
         let r = dlog_group::random_scalar_in_group_range(crypto_utils::secure_rng());
-        let a = dlog_group::exponentiate(&public_input.g, &r);
-        let b = dlog_group::exponentiate(&public_input.h, &r);
+        let a = exponentiate(&public_input.g, &r);
+        let b = exponentiate(&public_input.h, &r);
         (r, FirstDhTupleProverMessage::new(a, b))
     }
 
@@ -128,14 +130,16 @@ pub mod interactive_prover {
 
         let e: Scalar = challenge.clone().into();
 
-        let g_to_z = dlog_group::exponentiate(&g, &z);
-        let h_to_z = dlog_group::exponentiate(&h, &z);
+        use ergo_chain_types::ec_point::{exponentiate, inverse};
 
-        let u_to_e = dlog_group::exponentiate(&u, &e);
-        let v_to_e = dlog_group::exponentiate(&v, &e);
+        let g_to_z = exponentiate(&g, &z);
+        let h_to_z = exponentiate(&h, &z);
 
-        let a = g_to_z.mul(&dlog_group::inverse(&u_to_e));
-        let b = h_to_z.mul(&dlog_group::inverse(&v_to_e));
+        let u_to_e = exponentiate(&u, &e);
+        let v_to_e = exponentiate(&v, &e);
+
+        let a = g_to_z.mul(&inverse(&u_to_e));
+        let b = h_to_z.mul(&inverse(&v_to_e));
         (a, b)
     }
 }
diff --git a/ergotree-interpreter/src/sigma_protocol/dlog_protocol.rs b/ergotree-interpreter/src/sigma_protocol/dlog_protocol.rs
index 485f8e23c..a6c8729ba 100644
--- a/ergotree-interpreter/src/sigma_protocol/dlog_protocol.rs
+++ b/ergotree-interpreter/src/sigma_protocol/dlog_protocol.rs
@@ -1,8 +1,8 @@
 //! Discrete logarithm signature protocol
 
 use super::ProverMessage;
+use ergo_chain_types::EcPoint;
 use ergotree_ir::serialization::SigmaSerializable;
-use ergotree_ir::sigma_protocol::dlog_group::EcPoint;
 use k256::Scalar;
 
 /// First message from the prover (message `a` of `SigmaProtocol`) for discrete logarithm case
@@ -43,8 +43,11 @@ pub mod interactive_prover {
     use super::{FirstDlogProverMessage, SecondDlogProverMessage};
     use crate::sigma_protocol::crypto_utils;
     use crate::sigma_protocol::{private_input::DlogProverInput, Challenge};
+    use ergo_chain_types::{
+        ec_point::{exponentiate, generator, inverse},
+        EcPoint,
+    };
     use ergotree_ir::sigma_protocol::dlog_group;
-    use ergotree_ir::sigma_protocol::dlog_group::EcPoint;
     use ergotree_ir::sigma_protocol::sigma_boolean::ProveDlog;
     use k256::Scalar;
 
@@ -62,8 +65,8 @@ pub mod interactive_prover {
         //COMPUTE a = g^z*h^(-e)  (where -e here means -e mod q)
         let e: Scalar = challenge.clone().into();
         let minus_e = e.negate();
-        let h_to_e = dlog_group::exponentiate(&public_input.h, &minus_e);
-        let g_to_z = dlog_group::exponentiate(&dlog_group::generator(), &z);
+        let h_to_e = exponentiate(&public_input.h, &minus_e);
+        let g_to_z = exponentiate(&generator(), &z);
         let a = g_to_z * &h_to_e;
         (
             FirstDlogProverMessage(a.into()),
@@ -76,8 +79,8 @@ pub mod interactive_prover {
     /// that leaf to compute the necessary randomness "r" and the commitment "a"
     pub fn first_message() -> (Scalar, FirstDlogProverMessage) {
         let r = dlog_group::random_scalar_in_group_range(crypto_utils::secure_rng());
-        let g = dlog_group::generator();
-        let a = dlog_group::exponentiate(&g, &r);
+        let g = generator();
+        let a = exponentiate(&g, &r);
         (r, FirstDlogProverMessage(a.into()))
     }
 
@@ -108,12 +111,12 @@ pub mod interactive_prover {
         challenge: &Challenge,
         second_message: &SecondDlogProverMessage,
     ) -> EcPoint {
-        let g = dlog_group::generator();
+        let g = generator();
         let h = *proposition.h.clone();
         let e: Scalar = challenge.clone().into();
-        let g_z = dlog_group::exponentiate(&g, &second_message.z);
-        let h_e = dlog_group::exponentiate(&h, &e);
-        g_z * &dlog_group::inverse(&h_e)
+        let g_z = exponentiate(&g, &second_message.z);
+        let h_e = exponentiate(&h, &e);
+        g_z * &inverse(&h_e)
     }
 }
 
diff --git a/ergotree-interpreter/src/sigma_protocol/private_input.rs b/ergotree-interpreter/src/sigma_protocol/private_input.rs
index 72cef260f..9322d26d6 100644
--- a/ergotree-interpreter/src/sigma_protocol/private_input.rs
+++ b/ergotree-interpreter/src/sigma_protocol/private_input.rs
@@ -76,8 +76,8 @@ impl DlogProverInput {
     /// public key of discrete logarithm signature protocol
     pub fn public_image(&self) -> ProveDlog {
         // test it, see https://github.com/ergoplatform/sigma-rust/issues/38
-        let g = dlog_group::generator();
-        ProveDlog::new(dlog_group::exponentiate(&g, &self.w))
+        let g = ergo_chain_types::ec_point::generator();
+        ProveDlog::new(ergo_chain_types::ec_point::exponentiate(&g, &self.w))
     }
 
     /// Return true if the secret is 0
@@ -108,14 +108,15 @@ impl DhTupleProverInput {
     /// Create random secret and Diffie-Hellman tuple
     #[allow(clippy::many_single_char_names)]
     pub fn random() -> DhTupleProverInput {
-        let g = dlog_group::generator();
-        let h = dlog_group::exponentiate(
-            &dlog_group::generator(),
+        use ergo_chain_types::ec_point::{exponentiate, generator};
+        let g = generator();
+        let h = exponentiate(
+            &generator(),
             &dlog_group::random_scalar_in_group_range(crypto_utils::secure_rng()),
         );
         let w = dlog_group::random_scalar_in_group_range(crypto_utils::secure_rng());
-        let u = dlog_group::exponentiate(&g, &w);
-        let v = dlog_group::exponentiate(&h, &w);
+        let u = exponentiate(&g, &w);
+        let v = exponentiate(&h, &w);
         let common_input = ProveDhTuple::new(g, h, u, v);
         DhTupleProverInput { w, common_input }
     }
diff --git a/ergotree-ir/Cargo.toml b/ergotree-ir/Cargo.toml
index fe15d45c6..455c190d3 100644
--- a/ergotree-ir/Cargo.toml
+++ b/ergotree-ir/Cargo.toml
@@ -28,7 +28,6 @@ impl-trait-for-tuples = "0.2.0"
 proptest-derive = {version = "0.3.0", optional = true }
 bs58 = "0.4.0"
 base16 = "0.2.1"
-byteorder = "1"
 num-bigint = "0.4.0"
 bounded-vec = { version = "^0.6.0", features=["serde"] }
 num256 = "0.3.1"
diff --git a/ergotree-ir/src/chain.rs b/ergotree-ir/src/chain.rs
index 936b72749..5c3d826e0 100644
--- a/ergotree-ir/src/chain.rs
+++ b/ergotree-ir/src/chain.rs
@@ -2,10 +2,7 @@
 
 pub mod address;
 pub mod ergo_box;
-pub mod header;
 #[cfg(feature = "json")]
 pub mod json;
-pub mod preheader;
 pub mod token;
 pub mod tx_id;
-pub mod votes;
diff --git a/ergotree-ir/src/chain/address.rs b/ergotree-ir/src/chain/address.rs
index f5f4fff71..b780c755a 100644
--- a/ergotree-ir/src/chain/address.rs
+++ b/ergotree-ir/src/chain/address.rs
@@ -18,12 +18,12 @@ use crate::mir::value::NativeColl::CollByte;
 use crate::serialization::SigmaParsingError;
 use crate::serialization::SigmaSerializable;
 use crate::serialization::SigmaSerializationError;
-use crate::sigma_protocol::dlog_group::EcPoint;
 use crate::sigma_protocol::sigma_boolean::ProveDlog;
 use crate::sigma_protocol::sigma_boolean::SigmaBoolean;
 use crate::sigma_protocol::sigma_boolean::SigmaProofOfKnowledgeTree;
 use crate::sigma_protocol::sigma_boolean::SigmaProp;
 use crate::types::stype::SType;
+use ergo_chain_types::EcPoint;
 
 use sigma_util::hash::blake2b256_hash;
 use sigma_util::AsVecU8;
diff --git a/ergotree-ir/src/chain/json.rs b/ergotree-ir/src/chain/json.rs
index 2f17a99dc..2dc5bf7f2 100644
--- a/ergotree-ir/src/chain/json.rs
+++ b/ergotree-ir/src/chain/json.rs
@@ -2,12 +2,10 @@
 
 use serde::Serializer;
 
-pub(crate) mod autolykos_solution;
 pub(crate) mod box_value;
 pub(crate) mod ergo_box;
 pub mod ergo_tree;
 pub(crate) mod token;
-pub(crate) mod votes;
 
 /// Serialize bytes ([u8]) as base16 encoded string
 pub fn serialize_bytes<S, T>(bytes: T, serializer: S) -> Result<S::Ok, S::Error>
diff --git a/ergotree-ir/src/mir/constant.rs b/ergotree-ir/src/mir/constant.rs
index 753621e32..365eb9536 100644
--- a/ergotree-ir/src/mir/constant.rs
+++ b/ergotree-ir/src/mir/constant.rs
@@ -10,8 +10,8 @@ use crate::serialization::SigmaSerializable;
 use crate::serialization::SigmaSerializationError;
 use crate::sigma_protocol::sigma_boolean::SigmaBoolean;
 use crate::sigma_protocol::sigma_boolean::SigmaProofOfKnowledgeTree;
+use crate::sigma_protocol::sigma_boolean::SigmaProp;
 use crate::sigma_protocol::sigma_boolean::{ProveDhTuple, ProveDlog};
-use crate::sigma_protocol::{dlog_group::EcPoint, sigma_boolean::SigmaProp};
 use crate::types::stuple::STuple;
 use crate::types::stuple::TupleItems;
 use crate::types::stype::LiftIntoSType;
@@ -19,6 +19,7 @@ use crate::types::stype::SType;
 use ergo_chain_types::ADDigest;
 use ergo_chain_types::Base16DecodedBytes;
 use ergo_chain_types::Digest32;
+use ergo_chain_types::EcPoint;
 use impl_trait_for_tuples::impl_for_tuples;
 use sigma_util::AsVecI8;
 use sigma_util::AsVecU8;
diff --git a/ergotree-ir/src/mir/value.rs b/ergotree-ir/src/mir/value.rs
index ba8b02c2d..d23af558c 100644
--- a/ergotree-ir/src/mir/value.rs
+++ b/ergotree-ir/src/mir/value.rs
@@ -8,13 +8,11 @@ use sigma_util::AsVecI8;
 
 use crate::bigint256::BigInt256;
 use crate::chain::ergo_box::ErgoBox;
-use crate::chain::header::Header;
-use crate::chain::preheader::PreHeader;
-use crate::sigma_protocol::dlog_group::EcPoint;
 use crate::sigma_protocol::sigma_boolean::SigmaProp;
 use crate::types::stuple::TupleItems;
 use crate::types::stype::LiftIntoSType;
 use crate::types::stype::SType;
+use ergo_chain_types::{EcPoint, Header, PreHeader};
 
 use super::avl_tree_data::AvlTreeData;
 use super::constant::Literal;
diff --git a/ergotree-ir/src/serialization/data.rs b/ergotree-ir/src/serialization/data.rs
index c829cd288..008d3ae32 100644
--- a/ergotree-ir/src/serialization/data.rs
+++ b/ergotree-ir/src/serialization/data.rs
@@ -12,11 +12,10 @@ use crate::serialization::SigmaSerializeResult;
 use crate::serialization::{
     sigma_byte_reader::SigmaByteRead, SigmaParsingError, SigmaSerializable,
 };
-use crate::sigma_protocol::{
-    dlog_group::EcPoint, sigma_boolean::SigmaBoolean, sigma_boolean::SigmaProp,
-};
+use crate::sigma_protocol::{sigma_boolean::SigmaBoolean, sigma_boolean::SigmaProp};
 use crate::types::stuple;
 use crate::types::stype::SType;
+use ergo_chain_types::EcPoint;
 
 use super::sigma_byte_writer::SigmaByteWrite;
 use std::convert::TryInto;
diff --git a/ergotree-ir/src/serialization/sigmaboolean.rs b/ergotree-ir/src/serialization/sigmaboolean.rs
index cc19631f2..f8f8702d5 100644
--- a/ergotree-ir/src/serialization/sigmaboolean.rs
+++ b/ergotree-ir/src/serialization/sigmaboolean.rs
@@ -4,12 +4,10 @@ use crate::has_opcode::{HasOpCode, HasStaticOpCode};
 use crate::serialization::{
     sigma_byte_reader::SigmaByteRead, SigmaParsingError, SigmaSerializable,
 };
-use crate::sigma_protocol::{
-    dlog_group::EcPoint,
-    sigma_boolean::{
-        ProveDhTuple, ProveDlog, SigmaBoolean, SigmaConjecture, SigmaProofOfKnowledgeTree,
-    },
+use crate::sigma_protocol::sigma_boolean::{
+    ProveDhTuple, ProveDlog, SigmaBoolean, SigmaConjecture, SigmaProofOfKnowledgeTree,
 };
+use ergo_chain_types::EcPoint;
 
 use crate::sigma_protocol::sigma_boolean::cand::Cand;
 use crate::sigma_protocol::sigma_boolean::cor::Cor;
diff --git a/ergotree-ir/src/sigma_protocol/dlog_group.rs b/ergotree-ir/src/sigma_protocol/dlog_group.rs
index 4a84e51f2..8d43b65b4 100644
--- a/ergotree-ir/src/sigma_protocol/dlog_group.rs
+++ b/ergotree-ir/src/sigma_protocol/dlog_group.rs
@@ -22,116 +22,14 @@ use crate::serialization::{
     sigma_byte_reader::SigmaByteRead, SigmaParsingError, SigmaSerializable,
 };
 use elliptic_curve::group::ff::PrimeField;
-use elliptic_curve::group::prime::PrimeCurveAffine;
 use elliptic_curve::rand_core::RngCore;
-use k256::elliptic_curve::sec1::ToEncodedPoint;
-use k256::{ProjectivePoint, PublicKey, Scalar};
+use k256::Scalar;
 use num_bigint::Sign;
 use num_bigint::ToBigUint;
 use num_bigint::{BigInt, BigUint};
 use num_traits::ToPrimitive;
-use sigma_ser::vlq_encode::{ReadSigmaVlqExt, WriteSigmaVlqExt};
-use sigma_ser::{ScorexParsingError, ScorexSerializable, ScorexSerializeResult};
+use sigma_ser::ScorexSerializable;
 use std::convert::TryFrom;
-use std::ops::{Add, Mul, Neg};
-
-/// Elliptic curve point
-#[derive(PartialEq, Clone, Default)]
-#[cfg_attr(
-    feature = "json",
-    derive(serde::Serialize, serde::Deserialize),
-    serde(into = "String", try_from = "String")
-)]
-pub struct EcPoint(ProjectivePoint);
-
-#[allow(clippy::unwrap_used)]
-impl std::fmt::Debug for EcPoint {
-    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-        f.write_str("EC:")?;
-        f.write_str(&base16::encode_lower(
-            &self.sigma_serialize_bytes().unwrap(),
-        ))
-    }
-}
-
-impl EcPoint {
-    /// Number of bytes to represent any group element as byte array
-    pub const GROUP_SIZE: usize = 33;
-
-    /// Attempts to parse from Base16-encoded string
-    pub fn from_base16_str(str: String) -> Option<Self> {
-        base16::decode(&str)
-            .ok()
-            .and_then(|bytes| Self::sigma_parse_bytes(&bytes).ok())
-    }
-}
-
-impl TryFrom<String> for EcPoint {
-    type Error = String;
-    fn try_from(value: String) -> Result<Self, Self::Error> {
-        EcPoint::from_base16_str(value)
-            .ok_or_else(|| String::from("Ecpoint: error parsing from base16-encoded string"))
-    }
-}
-
-impl From<EcPoint> for String {
-    fn from(value: EcPoint) -> String {
-        #[allow(clippy::unwrap_used)]
-        {
-            let bytes = value.sigma_serialize_bytes().unwrap();
-            base16::encode_lower(&bytes)
-        }
-    }
-}
-
-impl Eq for EcPoint {}
-
-impl Mul<&EcPoint> for EcPoint {
-    type Output = EcPoint;
-
-    fn mul(self, other: &EcPoint) -> EcPoint {
-        EcPoint(ProjectivePoint::add(self.0, &other.0))
-    }
-}
-
-impl Neg for EcPoint {
-    type Output = EcPoint;
-
-    fn neg(self) -> EcPoint {
-        EcPoint(ProjectivePoint::neg(self.0))
-    }
-}
-
-/// The generator g of the group is an element of the group such that, when written multiplicatively, every element
-/// of the group is a power of g.
-pub fn generator() -> EcPoint {
-    EcPoint(ProjectivePoint::GENERATOR)
-}
-
-/// The identity(infinity) element
-pub const fn identity() -> EcPoint {
-    EcPoint(ProjectivePoint::IDENTITY)
-}
-
-/// Check if point is identity(infinity) element
-pub fn is_identity(ge: &EcPoint) -> bool {
-    *ge == identity()
-}
-
-/// Calculates the inverse of the given group element
-pub fn inverse(ec: &EcPoint) -> EcPoint {
-    -ec.clone()
-}
-
-/// Raises the base GroupElement to the exponent. The result is another GroupElement.
-pub fn exponentiate(base: &EcPoint, exponent: &Scalar) -> EcPoint {
-    if !is_identity(base) {
-        // we treat EC as a multiplicative group, therefore, exponentiate point is multiply.
-        EcPoint(base.0 * exponent)
-    } else {
-        base.clone()
-    }
-}
 
 // /// Creates a random member of this Dlog group
 // pub fn random_element() -> EcPoint {
@@ -186,7 +84,7 @@ pub fn bigint256_to_scalar(bi: BigInt256) -> Option<Scalar> {
     Scalar::from_repr(bytes.into()).into()
 }
 
-impl SigmaSerializable for EcPoint {
+impl SigmaSerializable for ergo_chain_types::EcPoint {
     fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> SigmaSerializeResult {
         let _ = self.scorex_serialize(w)?;
         Ok(())
@@ -198,34 +96,6 @@ impl SigmaSerializable for EcPoint {
     }
 }
 
-impl ScorexSerializable for EcPoint {
-    fn scorex_serialize<W: WriteSigmaVlqExt>(&self, w: &mut W) -> ScorexSerializeResult {
-        let caff = self.0.to_affine();
-        if caff.is_identity().into() {
-            // infinity point
-            let zeroes = [0u8; EcPoint::GROUP_SIZE];
-            w.write_all(&zeroes)?;
-        } else {
-            w.write_all(caff.to_encoded_point(true).as_bytes())?;
-        }
-        Ok(())
-    }
-
-    fn scorex_parse<R: ReadSigmaVlqExt>(r: &mut R) -> Result<Self, ScorexParsingError> {
-        let mut buf = [0; EcPoint::GROUP_SIZE];
-        r.read_exact(&mut buf[..])?;
-        if buf[0] != 0 {
-            let pubkey = PublicKey::from_sec1_bytes(&buf[..]).map_err(|e| {
-                ScorexParsingError::Misc(format!("failed to parse PK from bytes: {:?}", e))
-            })?;
-            Ok(EcPoint(pubkey.to_projective()))
-        } else {
-            // infinity point
-            Ok(EcPoint(ProjectivePoint::IDENTITY))
-        }
-    }
-}
-
 /// Order of the secp256k1 elliptic curve
 pub fn order() -> BigInt {
     #[allow(clippy::unwrap_used)]
@@ -236,33 +106,11 @@ pub fn order() -> BigInt {
     .unwrap()
 }
 
-/// Arbitrary impl for EcPoint
-#[cfg(feature = "arbitrary")]
-mod arbitrary {
-    use super::*;
-    use proptest::prelude::*;
-
-    impl Arbitrary for EcPoint {
-        type Parameters = ();
-        type Strategy = BoxedStrategy<Self>;
-
-        fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
-            prop_oneof![
-                Just(generator()),
-                Just(identity()), /*Just(random_element()),*/
-            ]
-            .boxed()
-        }
-    }
-}
-
 #[allow(clippy::unwrap_used)]
 #[cfg(test)]
 #[allow(clippy::panic)]
 mod tests {
     use super::*;
-    use crate::mir::expr::Expr;
-    use crate::serialization::sigma_serialize_roundtrip;
     use num_bigint::BigUint;
     use num_bigint::ToBigUint;
     use proptest::prelude::*;
@@ -308,12 +156,6 @@ mod tests {
 
     proptest! {
 
-        #[test]
-        fn ser_roundtrip(v in any::<EcPoint>()) {
-            let e: Expr = v.into();
-            prop_assert_eq![sigma_serialize_roundtrip(&e), e];
-        }
-
         #[test]
         fn scalar_biguint_roundtrip(scalar in scalar()) {
             let bu = scalar_to_biguint(&scalar).unwrap();
diff --git a/ergotree-ir/src/sigma_protocol/sigma_boolean.rs b/ergotree-ir/src/sigma_protocol/sigma_boolean.rs
index fe4ffc567..0c1da3b93 100644
--- a/ergotree-ir/src/sigma_protocol/sigma_boolean.rs
+++ b/ergotree-ir/src/sigma_protocol/sigma_boolean.rs
@@ -4,13 +4,13 @@ use self::cand::Cand;
 use self::cor::Cor;
 use self::cthreshold::Cthreshold;
 
-use super::dlog_group::EcPoint;
 use crate::ergo_tree::{ErgoTree, ErgoTreeError};
 use crate::has_opcode::{HasOpCode, HasStaticOpCode};
 use crate::mir::constant::Constant;
 use crate::mir::expr::Expr;
 use crate::serialization::op_code::OpCode;
 use crate::serialization::SigmaSerializable;
+use ergo_chain_types::EcPoint;
 use std::convert::TryFrom;
 use std::convert::TryInto;
 
diff --git a/ergotree-ir/src/types/stype.rs b/ergotree-ir/src/types/stype.rs
index 024a88e48..eba90fea1 100644
--- a/ergotree-ir/src/types/stype.rs
+++ b/ergotree-ir/src/types/stype.rs
@@ -7,11 +7,11 @@ use impl_trait_for_tuples::impl_for_tuples;
 
 use crate::bigint256::BigInt256;
 use crate::chain::ergo_box::ErgoBox;
-use crate::sigma_protocol::dlog_group::EcPoint;
 use crate::sigma_protocol::sigma_boolean::SigmaBoolean;
 use crate::sigma_protocol::sigma_boolean::SigmaProofOfKnowledgeTree;
 use crate::sigma_protocol::sigma_boolean::SigmaProp;
 use crate::sigma_protocol::sigma_boolean::{ProveDhTuple, ProveDlog};
+use ergo_chain_types::EcPoint;
 
 use super::sfunc::SFunc;
 use super::stuple::STuple;


Test patch: