Skip to content

Commit

Permalink
Multisig (#268)
Browse files Browse the repository at this point in the history
* Multisig

* Refactoring and documentation

* Increment multisig addresses security according to absorbed digests

* Move signInputsAndReturn in signing namespace

* Include <algorithm>

* Merge address and multisig address

* Include <cstdint>

* Explicit type address ctor

* Use a specific release of google test

* SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING

* Fix silence TR1

* Prevent overriding the parent project's compiler/linker settings on Windows

* Set gtest_force_shared_crt before compiling

* Add googletest dependency

* Pass -Dgtest_force_shared_crt=ON to gtest

* Add operator << to print addresses

* Operator << to print seed, tag and transaction

* Forward flags to gtest

* Append silence TR1 to forward flags

* Pass address by reference

* Alignement test : removing address type

* Alignement test : removing kerl

* Bring back address type

* Bring back kerl

* Kerl as a shared_ptr

* Include memory

* Bring back tests

* Bring back all AppVeyor builds
  • Loading branch information
thibault-martinez authored and Cylix committed May 9, 2018
1 parent 985e910 commit f054dc9
Show file tree
Hide file tree
Showing 20 changed files with 544 additions and 127 deletions.
22 changes: 11 additions & 11 deletions cmake/gtest_settings.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,23 @@
#

set(GOOGLETEST_ROOT external/googletest/googletest CACHE STRING "Google Test source root")
set(GOOGLEMOCK_ROOT external/googletest/googlemock CACHE STRING "Google Mock source root")

########## GOOGLE TEST SOURCES ##########

set(GOOGLETEST_SOURCES
${CMAKE_SOURCE_DIR}/${GOOGLETEST_ROOT}/src/gtest-all.cc
${CMAKE_SOURCE_DIR}/${GOOGLEMOCK_ROOT}/src/gmock-all.cc
${CMAKE_SOURCE_DIR}/${GOOGLEMOCK_ROOT}/src/gmock_main.cc
)
ExternalProject_Add("googletest_dep"
SOURCE_DIR "${CMAKE_SOURCE_DIR}/${GOOGLETEST_ROOT}"
CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${CMAKE_SOURCE_DIR}/deps"
CMAKE_ARGS "-DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=${CMAKE_SOURCE_DIR}/deps/lib"
CMAKE_ARGS "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${CMAKE_SOURCE_DIR}/deps/lib"
CMAKE_ARGS "-Dgtest_force_shared_crt=ON" # Prevent overriding the parent project's compiler/linker settings on Windows
CMAKE_ARGS "-DCMAKE_C_FLAGS=${FORWARD_FLAGS} -D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING"
CMAKE_ARGS "-DCMAKE_CXX_FLAGS=${FORWARD_FLAGS} -D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING"
UPDATE_COMMAND git checkout tags/release-1.8.0
INSTALL_COMMAND "")

########## GOOGLE TEST INCLUDES DIRECTORIES ##########

include_directories(
${CMAKE_SOURCE_DIR}/${GOOGLETEST_ROOT}
${CMAKE_SOURCE_DIR}/${GOOGLETEST_ROOT}/include
${CMAKE_SOURCE_DIR}/${GOOGLEMOCK_ROOT}
${CMAKE_SOURCE_DIR}/${GOOGLEMOCK_ROOT}/include
)

add_library(googletest ${GOOGLETEST_SOURCES})
add_dependencies(${CMAKE_PROJECT_NAME} googletest_dep)
2 changes: 1 addition & 1 deletion external/googletest
Submodule googletest updated 50 files
+0 −1 .gitignore
+1 −1 CMakeLists.txt
+1 −1 googlemock/CMakeLists.txt
+6 −16 googlemock/README.md
+9 −12 googlemock/docs/CookBook.md
+1 −1 googlemock/docs/ForDummies.md
+7 −10 googlemock/docs/v1_5/CookBook.md
+7 −10 googlemock/docs/v1_6/CookBook.md
+7 −10 googlemock/docs/v1_7/CookBook.md
+60 −58 googlemock/include/gmock/gmock-matchers.h
+25 −28 googlemock/include/gmock/gmock-spec-builders.h
+5 −4 googlemock/include/gmock/internal/gmock-internal-utils.h
+1 −1 googlemock/src/gmock-cardinalities.cc
+3 −2 googlemock/src/gmock-internal-utils.cc
+5 −4 googlemock/src/gmock-matchers.cc
+5 −4 googlemock/src/gmock-spec-builders.cc
+57 −57 googlemock/test/gmock-generated-actions_test.cc
+18 −20 googlemock/test/gmock-generated-function-mockers_test.cc
+36 −36 googlemock/test/gmock-generated-matchers_test.cc
+13 −12 googlemock/test/gmock-internal-utils_test.cc
+78 −84 googlemock/test/gmock-matchers_test.cc
+74 −77 googlemock/test/gmock-more-actions_test.cc
+14 −13 googlemock/test/gmock-nice-strict_test.cc
+6 −5 googlemock/test/gmock-spec-builders_test.cc
+1 −1 googlemock/test/gmock_stress_test.cc
+1 −1 googletest/CMakeLists.txt
+2 −105 googletest/README.md
+1 −3 googletest/cmake/internal_utils.cmake
+2 −2 googletest/docs/AdvancedGuide.md
+1 −1 googletest/docs/FAQ.md
+43 −56 googletest/include/gtest/gtest-printers.h
+3 −2 googletest/include/gtest/gtest-spi.h
+3 −4 googletest/include/gtest/gtest-typed-test.h
+2 −6 googletest/include/gtest/gtest.h
+0 −3 googletest/include/gtest/internal/custom/gtest-port.h
+0 −4 googletest/include/gtest/internal/custom/gtest.h
+3 −4 googletest/include/gtest/internal/gtest-internal.h
+10 −9 googletest/include/gtest/internal/gtest-param-util.h
+0 −2 googletest/include/gtest/internal/gtest-port-arch.h
+12 −49 googletest/include/gtest/internal/gtest-port.h
+4 −3 googletest/src/gtest-death-test.cc
+15 −15 googletest/src/gtest-internal-inl.h
+20 −2 googletest/src/gtest-port.cc
+20 −40 googletest/src/gtest.cc
+1 −1 googletest/test/gtest-death-test_test.cc
+0 −7 googletest/test/gtest-port_test.cc
+27 −29 googletest/test/gtest-printers_test.cc
+1 −1 googletest/test/gtest_catch_exceptions_test_.cc
+6 −5 googletest/test/gtest_unittest.cc
+0 −47 googletest/xcode/gtest.xcodeproj/project.pbxproj
4 changes: 0 additions & 4 deletions include/iota/api/extended.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,10 +374,6 @@ class Extended : public Core {
const std::vector<Models::Transfer>& transfers) const;

private:
std::vector<Types::Trytes> signInputsAndReturn(
const Models::Seed& seed, const std::vector<Models::Address>& inputs, Models::Bundle& bundle,
const std::vector<Types::Trytes>& signatureFragments) const;

void traverseBundles(const std::vector<Types::Trytes>& trxs,
const std::vector<std::reference_wrapper<Models::Bundle>>& bundles,
bool throwOnFail) const;
Expand Down
1 change: 1 addition & 0 deletions include/iota/crypto/keccak384.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#pragma once

#include <cstdint>
#include <vector>

extern "C" {
Expand Down
83 changes: 83 additions & 0 deletions include/iota/crypto/multi_signing.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//
// MIT License
//
// Copyright (c) 2017-2018 Thibault Martinez and Simon Ninon
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
//

#pragma once

#include <iota/models/address.hpp>

namespace IOTA {

namespace Crypto {

/**
* Multi signing related functions.
*/
namespace MultiSigning {

/**
* Derive a private key from a seed.
*
* @param seedBytes Seed in bytes to be used for address generation.
* @param index The index to start the generation from.
* @param security The security to use for address generation.
*
* @return The key as bytes.
*/
std::vector<uint8_t> key(const std::vector<uint8_t>& seedBytes, uint32_t index, uint32_t security);

/**
* Compute digests from key.
*
* @param keyBytes The key in bytes.
*
* @return The digests.
*/
std::vector<uint8_t> digests(const std::vector<uint8_t>& keyBytes);

/**
* Adds the cosigner signatures to the corresponding bundle transaction
*
* @param bundleToSign Bundle to be signed.
* @param inputAddress Input address.
* @param key Key to sign with.
*/
void addSignature(Models::Bundle& bundleToSign, const Models::Address& inputAddress,
const std::vector<uint8_t>& key);

/**
* Validate the signature fragment.
*
* @param signedBundle The bundle.
* @param inputAddress The address.
*
* @return whether the signatures are valid or not.
*/
bool validateSignatures(const Models::Bundle& signedBundle, const Models::Address& inputAddress);

} // namespace MultiSigning

} // namespace Crypto

} // namespace IOTA
11 changes: 8 additions & 3 deletions include/iota/crypto/signing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace Signing {
/**
* Derive a private key from a seed.
*
* @param seed Seed to be used for address generation.
* @param seedBytes Seed in bytes to be used for address generation.
* @param index The index to start the generation from.
* @param security The security to use for address generation.
*
Expand All @@ -53,11 +53,11 @@ std::vector<uint8_t> key(const std::vector<uint8_t>& seedBytes, uint32_t index =
/**
* Compute digests from key.
*
* @param key The key.
* @param keyBytes The key in bytes.
*
* @return The digests.
*/
std::vector<uint8_t> digests(const std::vector<uint8_t>& key);
std::vector<uint8_t> digests(const std::vector<uint8_t>& keyBytes);

/**
* Compute address from digests.
Expand Down Expand Up @@ -90,6 +90,11 @@ std::vector<uint8_t> digest(const std::vector<int8_t>& normalizedBundleFragment
Types::Trits signatureFragment(const std::vector<int8_t>& normalizedBundleFragment,
const Types::Trits& keyFragment);

std::vector<Types::Trytes> signInputs(const Models::Seed& seed,
const std::vector<Models::Address>& inputs,
Models::Bundle& bundle,
const std::vector<Types::Trytes>& signatureFragments);

/**
* Validate signature fragments.
*
Expand Down
66 changes: 59 additions & 7 deletions include/iota/models/address.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@

#pragma once

#include <memory>

#include <iota/crypto/kerl.hpp>
#include <iota/types/trinary.hpp>

namespace IOTA {
Expand All @@ -38,6 +41,9 @@ namespace Models {
* Any addresses stored represented with this class are ensured to be valid.
*/
class Address {
public:
enum Type { NORMAL, MULTISIG };

public:
/**
* Ctor.
Expand All @@ -48,7 +54,7 @@ class Address {
* @param security The security level of the address.
*/
Address(const Types::Trytes& address = "", const int64_t& balance = 0,
const int32_t& keyIndex = 0, const int32_t& security = 2);
const int32_t& keyIndex = 0, const int32_t& security = 2, const Type& type = NORMAL);

/**
* Ctor, char* based to make implicitly convertion to Address more flexible.
Expand All @@ -59,7 +65,14 @@ class Address {
* @param security The security level of the address.
*/
Address(const char* address, const int64_t& balance = 0, const int32_t& keyIndex = 0,
const int32_t& security = 2);
const int32_t& security = 2, const Type& type = NORMAL);

/**
* Ctor - mainly to used to build multisig addresses.
*
* @param type The address type, normal or multisig.
*/
explicit Address(const Type& type);

/**
* Default dtor.
Expand Down Expand Up @@ -109,6 +122,32 @@ class Address {
*/
bool empty() const;

/**
* Multisig address related methods.
*/
public:
/**
* Absorbs key digests
* Increments security according to digests.
*
* @param digests The key digests in bytes.
**/
void absorbDigests(const std::vector<uint8_t>& digests);

/**
* Finalizes and set the multisig address.
**/
void finalize();

/**
* Validates a generated multisig address.
*
* @param digests The keys digests.
*
* @return whether the multisig address is valid or not.
**/
bool validate(const std::vector<std::vector<uint8_t>>& digests);

public:
/**
* @return Balance.
Expand Down Expand Up @@ -186,11 +225,6 @@ class Address {
*/
Types::Trytes address_;

/**
* address checksum
*/
Types::Trytes checksum_;

/**
* The balance.
*/
Expand All @@ -205,8 +239,26 @@ class Address {
* The security.
*/
int32_t security_ = 2;

/**
* Type of the address (normal/multisig)
*/
Type type_;

/**
* address checksum
*/
Types::Trytes checksum_;

/**
* Instance of Kerl for multisig addresses.
* Due to an alignement issue on MSVC15/32bits, kerl has been made a shared_ptr.
*/
std::shared_ptr<Crypto::Kerl> k_;
};

std::ostream& operator<<(std::ostream& os, const Address& address);

} // namespace Models

} // namespace IOTA
2 changes: 2 additions & 0 deletions include/iota/models/seed.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ class Seed {
int security_;
};

std::ostream& operator<<(std::ostream& os, const Seed& seed);

} // namespace Models

} // namespace IOTA
2 changes: 2 additions & 0 deletions include/iota/models/tag.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ class Tag {
Types::Trytes paddedTag_;
};

std::ostream& operator<<(std::ostream& os, const Tag& tag);

} // namespace Models

} // namespace IOTA
2 changes: 2 additions & 0 deletions include/iota/models/transaction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,8 @@ class Transaction {
bool persistence_ = false;
};

std::ostream& operator<<(std::ostream& os, const Transaction& transaction);

} // namespace Models

} // namespace IOTA

0 comments on commit f054dc9

Please sign in to comment.