diff --git a/blockchain-sys/build.rs b/blockchain-sys/build.rs
index b6287c0209b73ccf5a88e9337d2221cf7c24589a..cc0a5cd8d40d654b76441c7286dbeef5db138dc5 100644
--- a/blockchain-sys/build.rs
+++ b/blockchain-sys/build.rs
@@ -4,7 +4,8 @@ fn main() {
     // Rust build scripts can give commands back to cargo using println... (?)
 
     // Rerun this script when our C++ library changes.
-    println!("cargo:rerun-if-changed=../libblockchain/*");
+    println!("cargo:rerun-if-changed=../libblockchain/src/lib.h");
+    println!("cargo:rerun-if-changed=../libblockchain/src/lib.cpp");
 
     // Build the library. We use the cmake crate to build. Beyond simply invoking our CmakeLists.txt, it respects profiles (Debug/Release buids) and also targets (for cross compiling).
     let dst = cmake::Config::new("../libblockchain").build();
@@ -23,7 +24,7 @@ fn main() {
         .with_codegen_config(bindgen::CodegenConfig::FUNCTIONS | bindgen::CodegenConfig::TYPES)
         // Only generate functions that have our prefix. Otherwise bindgen will generate a bunch of stuff from c std headers that we don't want.
         .whitelist_function("^libbc_.+$")
-        .whitelist_type("^libbc_.+$")
+        .whitelist_type("^LibBc.+$")
         .size_t_is_usize(true)
         .generate()
         .expect("Error generating Bindings");
diff --git a/blockchain-sys/src/bindings.rs b/blockchain-sys/src/bindings.rs
index 15103972e5f2d2fb54b90469cf79b116d088e7f6..454d6b951203d3f3d17fd1040f44bb48cfc34ce0 100644
--- a/blockchain-sys/src/bindings.rs
+++ b/blockchain-sys/src/bindings.rs
@@ -4,43 +4,54 @@ pub type __uint8_t = ::std::os::raw::c_uchar;
 pub type __uint64_t = ::std::os::raw::c_ulong;
 #[repr(C)]
 #[derive(Debug, Copy, Clone)]
-pub struct libbc_Payload {
+pub struct LibBcBlockchain {
+    _unused: [u8; 0],
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct LibBcPayload {
     pub data: *const u8,
     pub len: usize,
 }
 #[test]
-fn bindgen_test_layout_libbc_Payload() {
+fn bindgen_test_layout_LibBcPayload() {
     assert_eq!(
-        ::std::mem::size_of::<libbc_Payload>(),
+        ::std::mem::size_of::<LibBcPayload>(),
         16usize,
-        concat!("Size of: ", stringify!(libbc_Payload))
+        concat!("Size of: ", stringify!(LibBcPayload))
     );
     assert_eq!(
-        ::std::mem::align_of::<libbc_Payload>(),
+        ::std::mem::align_of::<LibBcPayload>(),
         8usize,
-        concat!("Alignment of ", stringify!(libbc_Payload))
+        concat!("Alignment of ", stringify!(LibBcPayload))
     );
     assert_eq!(
-        unsafe { &(*(::std::ptr::null::<libbc_Payload>())).data as *const _ as usize },
+        unsafe { &(*(::std::ptr::null::<LibBcPayload>())).data as *const _ as usize },
         0usize,
         concat!(
             "Offset of field: ",
-            stringify!(libbc_Payload),
+            stringify!(LibBcPayload),
             "::",
             stringify!(data)
         )
     );
     assert_eq!(
-        unsafe { &(*(::std::ptr::null::<libbc_Payload>())).len as *const _ as usize },
+        unsafe { &(*(::std::ptr::null::<LibBcPayload>())).len as *const _ as usize },
         8usize,
         concat!(
             "Offset of field: ",
-            stringify!(libbc_Payload),
+            stringify!(LibBcPayload),
             "::",
             stringify!(len)
         )
     );
 }
 extern "C" {
-    pub fn libbc_handle_message(id: u64, payload: libbc_Payload);
+    pub fn libbc_new_blockchain() -> *mut LibBcBlockchain;
+}
+extern "C" {
+    pub fn libbc_blockchain_add(bc: *mut LibBcBlockchain, id: u64, payload: LibBcPayload);
+}
+extern "C" {
+    pub fn libbc_blockchain_print(bc: *mut LibBcBlockchain);
 }
diff --git a/libblockchain/src/lib.cpp b/libblockchain/src/lib.cpp
index b04c898ab4cd86edd2f2756e4fc1e8c512e2919e..c1d2b5ddac8c4ad8395df6fdaa828401bd6c4e39 100644
--- a/libblockchain/src/lib.cpp
+++ b/libblockchain/src/lib.cpp
@@ -1,28 +1,41 @@
 #include <iostream>
 #include <string>
+#include <vector>
 
 #include "lib.h"
 
-class Blockchain
-{
+class LibBcBlockchain {
 private:
-    std::string message;
+    std::vector<std::string> data;
 
 public:
-    Blockchain(std::string &&message) : message(message) {}
+    LibBcBlockchain();
+    void add_data(const std::string &&data);
+    void print();
+};
+
+LibBcBlockchain::LibBcBlockchain() : data() {}
+
+void LibBcBlockchain::add_data(const std::string &&data) {
+    this->data.emplace_back(data);
+}
 
-    const std::string &get()
-    {
-        return this->message;
+LibBcBlockchain *libbc_new_blockchain() {
+    return new LibBcBlockchain();
+}
+
+void LibBcBlockchain::print() {
+    for (auto &data : this->data) {
+        std::cout << data << std::endl;
     }
-};
+}
 
-void libbc_handle_message(uint64_t id, struct libbc_Payload payload)
-{
-    // Some C++ code in the implementation
-    auto s = std::string(payload.data, payload.data + payload.len);
+void libbc_blockchain_add(LibBcBlockchain *bc, uint64_t id, struct LibBcPayload payload) {
+    std::string s(payload.data, payload.data + payload.len);
+    std::cout << "Added data " << id << " to Blockchain: " << s << std::endl;
+    bc->add_data(std::move(s));
+}
 
-    Blockchain blockchain(std::move(s));
-    
-    std::cout << "C++ says: " << blockchain.get() << std::endl;
+void libbc_blockchain_print(LibBcBlockchain *bc) {
+    bc->print();
 }
\ No newline at end of file
diff --git a/libblockchain/src/lib.h b/libblockchain/src/lib.h
index abacc6a6e9d593c374ed51ceea8806cd7853a5f6..ff839d1e50a836110c8ce509c00382e1a044467b 100644
--- a/libblockchain/src/lib.h
+++ b/libblockchain/src/lib.h
@@ -5,6 +5,13 @@
 //size_t
 #include <stddef.h>
 
+// https://isocpp.org/wiki/faq/mixing-c-and-cpp#cpp-objs-passed-to-c
+#ifdef __cplusplus
+class LibBcBlockchain;
+#else
+typedef struct LibBcBlockchain LibBcBlockchain;
+#endif
+
 // Tell C++ to export the function without name-mangling and with C calling conventions.
 // If we omit this, the linker will not find our function.
 // The extern block should only contain C functions and types. No C++.
@@ -13,14 +20,18 @@ extern "C"
 {
 #endif
 
-    struct libbc_Payload {
-        const  uint8_t *data;
+    struct LibBcPayload
+    {
+        const uint8_t *data;
         size_t len;
     };
 
+    LibBcBlockchain *libbc_new_blockchain();
+
     // Its a good idea to prefix our C functions with something due to the lack of namespaces.
     // Prefixes also makes usign bindgen easier (see blockchain-sys/build.rs).
-    void libbc_handle_message(uint64_t id, struct libbc_Payload payload);
+    void libbc_blockchain_add(LibBcBlockchain *bc, uint64_t id, struct LibBcPayload payload);
+    void libbc_blockchain_print(LibBcBlockchain *bc);
 
 #ifdef __cplusplus
 }
diff --git a/program/src/main.rs b/program/src/main.rs
index 1cffa683c247c393c0aa323607e500c5e76cf432..313abb1271970fc79e131003b45ccd5f878582b6 100644
--- a/program/src/main.rs
+++ b/program/src/main.rs
@@ -1,22 +1,42 @@
-use blockchain_sys::libbc_handle_message;
-use blockchain_sys::libbc_Payload;
-
-// It's a good idea to wrap unsafe functions in safe functions that express the ownership semantics for Rust.
-// In this case we don't pass ownership to C, so write a function that borrows a slice.
-fn handle_message(id: u64, message: &[u8]) {
-    let payload = libbc_Payload {
-        data: message.as_ptr(),
-        len: message.len(),
-    };
-    
-    // Safety: message is borrowed for the duration of this function.
-    unsafe {
-        libbc_handle_message(id, payload);
+use blockchain_sys::LibBcBlockchain;
+use blockchain_sys::LibBcPayload;
+use blockchain_sys::libbc_new_blockchain;
+use blockchain_sys::libbc_blockchain_add;
+
+struct Blockchain {
+    inner: *mut LibBcBlockchain,
+}
+
+impl Blockchain {
+    pub fn new() -> Self {
+        Self {
+            inner: unsafe { libbc_new_blockchain() }
+        }
+    }
+
+    // It's a good idea to wrap unsafe functions in safe functions that express the ownership semantics for Rust.
+    // In this case we don't pass ownership to C, so write a function that borrows a slice.
+    pub fn add(&mut self, id: u64, message: &[u8]) {
+        let payload = LibBcPayload {
+            data: message.as_ptr(),
+            len: message.len(),
+        };
+
+        unsafe {
+            libbc_blockchain_add(self.inner, id, payload);
+        }
     }
 }
 
+
+
 fn main() {
-    let s = "hello world";
+    let mut blockchain = Blockchain::new();
 
-    handle_message(0, s.as_bytes());
+    blockchain.add(0, "hello world".as_bytes());
+    blockchain.add(1, "hello again".as_bytes());
+
+    unsafe {
+        blockchain_sys::libbc_blockchain_print(blockchain.inner);
+    }
 }