diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000000..33536958aad --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,6 @@ +# These owners will be the default owners for everything in +# the repo. Unless a later match takes precedence, +# @global-owner1 and @global-owner2 will be requested for +# review when someone opens a pull request. + +* @hewigovens @catenocrypt diff --git a/.github/workflows/android-ci.yml b/.github/workflows/android-ci.yml new file mode 100644 index 00000000000..c38c0dfdf7f --- /dev/null +++ b/.github/workflows/android-ci.yml @@ -0,0 +1,37 @@ +name: Android CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: [macos-10.15] + + steps: + - uses: actions/checkout@v2 + - name: Install system dependencies + run: brew install boost ninja + - name: Install Android Dependencies + run: | + $ANDROID_HOME/tools/bin/sdkmanager --verbose "cmake;3.10.2.4988404" "ndk-bundle" + $ANDROID_HOME/tools/bin/sdkmanager "system-images;android-26;google_apis;x86" + - name: Accept Licenses + run: echo -e "y\ny\ny\ny\ny\n" | $ANDROID_HOME/tools/bin/sdkmanager --licenses + - name: Cache internal dependencies + id: internal_cache + uses: actions/cache@v1.1.2 + with: + path: build/local + key: ${{ runner.os }}-internal-${{ hashFiles('tools/install-dependencies') }} + - name: Install internal dependencies + run: | + tools/install-dependencies + if: steps.internal_cache.outputs.cache-hit != 'true' + - name: Run test + run: | + tools/generate-files + tools/android-test diff --git a/.github/workflows/ios-ci.yml b/.github/workflows/ios-ci.yml new file mode 100644 index 00000000000..e3ad8eb88a2 --- /dev/null +++ b/.github/workflows/ios-ci.yml @@ -0,0 +1,32 @@ +name: iOS CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + runs-on: [macos-10.15] + steps: + - uses: actions/checkout@v2 + - name: Install system dependencies + run: | + brew install boost ninja xcodegen + - name: Cache internal dependencies + id: internal_cache + uses: actions/cache@v1.1.2 + with: + path: build/local + key: ${{ runner.os }}-internal-${{ hashFiles('tools/install-dependencies') }} + - name: Install internal dependencies + run: | + tools/install-dependencies + if: steps.internal_cache.outputs.cache-hit != 'true' + - name: Run codegen tests + run: tools/codegen-test + - name: Run iOS tests + run: | + tools/generate-files + tools/ios-test diff --git a/.github/workflows/linux-ci.yml b/.github/workflows/linux-ci.yml new file mode 100644 index 00000000000..666c0343f1c --- /dev/null +++ b/.github/workflows/linux-ci.yml @@ -0,0 +1,43 @@ +name: Linux CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + runs-on: [ubuntu-18.04] + steps: + - uses: actions/checkout@v2 + - name: Install system dependencies + run: | + # build-essential libboost-all-dev clang-9 ruby-full cmake + sudo apt-get install libc++-dev libc++abi-dev ninja-build lcov llvm + - name: Cache internal dependencies + id: internal_cache + uses: actions/cache@v1.1.2 + with: + path: build/local + key: ${{ runner.os }}-internal-${{ hashFiles('tools/install-dependencies') }} + - name: Install internal dependencies + run: | + tools/install-dependencies + env: + CC: /usr/bin/clang + CXX: /usr/bin/clang++ + if: steps.internal_cache.outputs.cache-hit != 'true' + - name: Build and test + run: | + tools/generate-files + cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=Debug -DCODE_COVERAGE=ON -DBOOST_ROOT=${BOOST_ROOT_1_72_0} + make -Cbuild + build/tests/tests tests --gtest_output=xml + env: + CC: /usr/bin/clang + CXX: /usr/bin/clang++ + - name: Gather code coverage + run: | + sudo rm -rf coverage.info + tools/coverage diff --git a/.gitignore b/.gitignore index 7a5561d7def..9e6a32631ab 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ xcode/ cmake-build-debug/ .cquery_cache/ .cxx/ +CMakeCache.txt +CMakeFiles/ # Dependencies node_modules diff --git a/CMakeLists.txt b/CMakeLists.txt index 151bb0fed14..59675c42667 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,11 @@ project(TrustWalletCore) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") +if(ANDROID) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") +else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++") +endif() set(CMAKE_EXPORT_COMPILE_COMMANDS 1) set(CMAKE_POSITION_INDEPENDENT_CODE ON) @@ -18,6 +22,7 @@ else() set(PREFIX "$ENV{PREFIX}") endif() + include_directories(${PREFIX}/include) link_directories(${PREFIX}/lib) @@ -88,3 +93,19 @@ if(NOT ANDROID AND NOT IOS_PLATFORM AND NOT WASM) endif() configure_file(${CMAKE_CURRENT_SOURCE_DIR}/swift/cpp.xcconfig.in ${CMAKE_CURRENT_SOURCE_DIR}/swift/cpp.xcconfig @ONLY) + +if(ANDROID) + # Workaround: + include_directories(BEFORE SYSTEM + $ENV{NDK_DIR}/sources/android/support/include + $ENV{NDK_DIR}/toolchains/llvm/prebuilt/linux-x86_64/lib64/clang/9.0.8/include # stddef.h + $ENV{NDK_DIR}/sysroot/usr/include + $ENV{NDK_DIR}/sources/cxx-stl/llvm-libc++abi/include + $ENV{NDK_DIR}/sources/cxx-stl/llvm-libc++/include + ) +else() + include_directories(BEFORE SYSTEM + /usr/include/x86_64-linux-gnu/c++/7.5.0 + /usr/include/c++/7.5.0 + ) +endif() diff --git a/README.md b/README.md index a42187be546..827eca33c04 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ Trust Wallet Core is a cross-platform library that implements low-level cryptographic wallet functionality for all supported blockchains. Most of the code is C++ with a set of strict exported C interfaces. The library provides idiomatic interfaces for all supported languages (currently Swift for iOS and Java for Android). -[![iOS status](https://dev.azure.com/TrustWallet/Trust%20Wallet%20Core/_apis/build/status/Wallet%20Core%20iOS)](https://dev.azure.com/TrustWallet/Trust%20Wallet%20Core/_build/latest?definitionId=13) -[![Android status](https://dev.azure.com/TrustWallet/Trust%20Wallet%20Core/_apis/build/status/Wallet%20Core%20Android)](https://dev.azure.com/TrustWallet/Trust%20Wallet%20Core/_build/latest?definitionId=11) -[![Linux status](https://dev.azure.com/TrustWallet/Trust%20Wallet%20Core/_apis/build/status/Wallet%20Core%20Linux)](https://dev.azure.com/TrustWallet/Trust%20Wallet%20Core/_build/latest?definitionId=24) +![iOS CI](https://github.com/trustwallet/wallet-core/workflows/iOS%20CI/badge.svg) +![Android CI](https://github.com/trustwallet/wallet-core/workflows/Android%20CI/badge.svg) +![Linux CI](https://github.com/trustwallet/wallet-core/workflows/Linux%20CI/badge.svg) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/82e76f6ea4ba4f0d9029e8846c04c093)](https://www.codacy.com/app/hewigovens/wallet-core?utm_source=github.com&utm_medium=referral&utm_content=TrustWallet/wallet-core&utm_campaign=Badge_Grade) ![Codecov](https://codecov.io/gh/TrustWallet/wallet-core/branch/master/graph/badge.svg) diff --git a/TrustWalletCore.podspec b/TrustWalletCore.podspec index 028cb115716..3182e93d445 100644 --- a/TrustWalletCore.podspec +++ b/TrustWalletCore.podspec @@ -28,7 +28,7 @@ Pod::Spec.new do |s| end s.subspec 'Core' do |ss| - protobuf_source_dir = 'build/protobuf/staging/protobuf-3.9.0' + protobuf_source_dir = 'build/local/src/protobuf/protobuf-3.9.0' include_dir = 'build/local/include' ss.source_files = 'src/**/*.{c,cc,cpp,h}', diff --git a/android/app/build.gradle b/android/app/build.gradle index 609fbaf8b18..7b010347f9e 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -3,12 +3,14 @@ apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-android' android { - compileSdkVersion 28 - buildToolsVersion '28.0.3' + compileSdkVersion 29 + buildToolsVersion '29.0.3' + ndkVersion '21.1.6352462' + defaultConfig { applicationId "com.trustwallet.core.app" minSdkVersion 23 - targetSdkVersion 28 + targetSdkVersion 29 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -24,19 +26,34 @@ android { dependencies { implementation project(':trustwalletcore') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation 'androidx.appcompat:appcompat:1.0.2' + implementation 'androidx.appcompat:appcompat:1.2.0-beta01' // Tests - testImplementation 'junit:junit:4.12' - androidTestImplementation("androidx.test.espresso:espresso-core:3.1.0-beta02", { + testImplementation 'junit:junit:4.13' + androidTestImplementation('androidx.test.espresso:espresso-core:3.3.0-beta01', { exclude group: "com.android.support", module: "support-annotations" }) - androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.1.1' - androidTestImplementation 'androidx.test:runner:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.2.0' + androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'android.arch.core:core-testing:1.1.1' - implementation 'io.grpc:grpc-protobuf:1.24.2' + implementation 'io.grpc:grpc-protobuf:1.29.0' + + debugImplementation 'com.github.DonaldDu:FixUnhandledEvent:1.0' } + repositories { mavenCentral() + maven { url "https://jitpack.io" } +} + +configurations.all { + resolutionStrategy.eachDependency { DependencyResolveDetails details -> + def requested = details.requested + if (requested.group == "com.android.support") { + if (!requested.name.startsWith("multidex")) { + details.useVersion "${targetSdk}.+" + } + } + } } diff --git a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/CoinAddressDerivationTests.kt b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/CoinAddressDerivationTests.kt index 8bfe4dd5268..18ab0a98320 100644 --- a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/CoinAddressDerivationTests.kt +++ b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/CoinAddressDerivationTests.kt @@ -83,5 +83,6 @@ class CoinAddressDerivationTests { CARDANO -> assertEquals("addr1snpa4z7ntyfszv7ckquprdw75w4qjqh0qmya9jtkpxxlzxghlqyvv7l0yjamh8fxraw06p3ua8sj2g2gv98v4849s43t9g2999kquuu5egnprk", address) NEO -> assertEquals("AT6w7PJvwPcSqHvtbNBY2aHPDv12eW5Uuf", address) FILECOIN -> assertEquals("f1zzykebxldfcakj5wdb5n3n7priul522fnmjzori", address) + ELROND -> assertEquals("erd1jfcy8aeru6vlx4fe6h3pc3vlpe2cnnur5zetxdhp879yagq7vqvs8na4f8", address) } } diff --git a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/digitalgold/TestDigitalGoldAddress.kt b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/digitalgold/TestDigitalGoldAddress.kt new file mode 100644 index 00000000000..686b33d4ac4 --- /dev/null +++ b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/digitalgold/TestDigitalGoldAddress.kt @@ -0,0 +1,33 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +package com.trustwallet.core.app.blockchains.digitalgold + +import com.trustwallet.core.app.utils.toHex +import com.trustwallet.core.app.utils.toHexByteArray +import org.junit.Assert.assertEquals +import org.junit.Test +import wallet.core.jni.* + +class TestDigitalGoldAddress { + + init { + System.loadLibrary("TrustWalletCore") + } + + @Test + fun testAddress() { + // TODO: Check and finalize implementation + + val key = PrivateKey("__PRIVATE_KEY_DATA__".toHexByteArray()) + val pubkey = key.publicKeyEd25519 + val address = AnyAddress(pubkey, CoinType.DIGITALGOLD) + val expected = AnyAddress("__EXPECTED_RESULT_ADDRESS__", CoinType.DIGITALGOLD) + + assertEquals(pubkey.data().toHex(), "0x__EXPECTED_PUBKEY_DATA__") + assertEquals(address.description(), expected.description()) + } +} diff --git a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/digitalgold/TestDigitalGoldSigner.kt b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/digitalgold/TestDigitalGoldSigner.kt new file mode 100644 index 00000000000..b3e2107b3b5 --- /dev/null +++ b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/digitalgold/TestDigitalGoldSigner.kt @@ -0,0 +1,45 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +package com.trustwallet.core.app.blockchains.digitalgold + +import com.google.protobuf.ByteString +import com.trustwallet.core.app.utils.Numeric +import com.trustwallet.core.app.utils.toHexByteArray +import com.trustwallet.core.app.utils.toHexBytes +import com.trustwallet.core.app.utils.toHexBytesInByteString +import junit.framework.Assert.assertEquals +import org.junit.Test +import wallet.core.jni.BitcoinSigner +import wallet.core.jni.proto.Bitcoin + +class TestDigitalGoldSigner { + + init { + System.loadLibrary("TrustWalletCore") + } + + @Test + fun DigitalGoldTransactionSigning() { + // TODO: Finalize implementation + + //val transfer = DigitalGold.TransferMessage.newBuilder() + // .setTo("...") + // .setAmount(...) + // ... + // .build() + //val signingInput = DigitalGold.SigningInput.newBuilder() + // ... + // .build() + + //val output: DigitalGold.SigningOutput = DigitalGoldSigner.sign(signingInput) + + //assertEquals( + // "__EXPECTED_RESULT_DATA__", + // Numeric.toHexString(output.encoded.toByteArray()) + //) + } +} diff --git a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/elrond/TestElrondAddress.kt b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/elrond/TestElrondAddress.kt new file mode 100644 index 00000000000..05c17837ddc --- /dev/null +++ b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/elrond/TestElrondAddress.kt @@ -0,0 +1,49 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +package com.trustwallet.core.app.blockchains.elrond + +import com.trustwallet.core.app.utils.toHex +import com.trustwallet.core.app.utils.toHexByteArray +import org.junit.Assert.assertEquals +import org.junit.Test +import wallet.core.jni.* + +class TestElrondAddress { + + init { + System.loadLibrary("TrustWalletCore") + } + + private val aliceBech32 = "erd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2fsmsgldz" + private var aliceSeedHex = "1a927e2af5306a9bb2ea777f73e06ecc0ac9aaa72fb4ea3fecf659451394cccf" + private var alicePubKeyHex = "0xfd691bb5e85d102687d81079dffce842d4dc328276d2d4c60d8fd1c3433c3293" + + @Test + fun testAddressFromPrivateKey() { + val key = PrivateKey(aliceSeedHex.toHexByteArray()) + val pubKey = key.publicKeyEd25519 + val address = AnyAddress(pubKey, CoinType.ELROND) + + assertEquals(alicePubKeyHex, pubKey.data().toHex()) + assertEquals(aliceBech32, address.description()) + } + + @Test + fun testAddressFromPublicKey() { + val pubKey = PublicKey(alicePubKeyHex.toHexByteArray(), PublicKeyType.ED25519) + val address = AnyAddress(pubKey, CoinType.ELROND) + + assertEquals(aliceBech32, address.description()) + } + + @Test + fun testAddressFromString() { + val address = AnyAddress(aliceBech32, CoinType.ELROND) + + assertEquals(aliceBech32, address.description()) + } +} diff --git a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/elrond/TestElrondSigner.kt b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/elrond/TestElrondSigner.kt new file mode 100644 index 00000000000..160dd9d7765 --- /dev/null +++ b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/elrond/TestElrondSigner.kt @@ -0,0 +1,57 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +package com.trustwallet.core.app.blockchains.elrond + +import com.google.protobuf.ByteString +import com.trustwallet.core.app.utils.toHexByteArray +import junit.framework.Assert.assertEquals +import org.junit.Test +import wallet.core.java.AnySigner +import wallet.core.jni.CoinType +import wallet.core.jni.PrivateKey +import wallet.core.jni.proto.Elrond + +class TestElrondSigner { + + init { + System.loadLibrary("TrustWalletCore") + } + + val aliceBech32 = "erd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2fsmsgldz" + var aliceSeedHex = "1a927e2af5306a9bb2ea777f73e06ecc0ac9aaa72fb4ea3fecf659451394cccf" + var alicePubKeyHex = "fd691bb5e85d102687d81079dffce842d4dc328276d2d4c60d8fd1c3433c3293" + + val bobBech32 = "erd1cux02zersde0l7hhklzhywcxk4u9n4py5tdxyx7vrvhnza2r4gmq4vw35r" + var bobSeedHex = "e3a3a3d1ac40d42d8fd4c569a9749b65a1250dd3d10b6f4e438297662ea4850e" + var bobPubKeyHex = "c70cf50b238372fffaf7b7c5723b06b57859d424a2da621bcc1b2f317543aa36" + + @Test + fun signTransaction() { + val transaction = Elrond.TransactionMessage.newBuilder() + .setNonce(0) + .setValue("0") + .setSender(aliceBech32) + .setReceiver(bobBech32) + .setGasPrice(200000000000000) + .setGasLimit(500000000) + .setData("foo") + .build() + + val privateKey = ByteString.copyFrom(PrivateKey(aliceSeedHex.toHexByteArray()).data()) + + val signingInput = Elrond.SigningInput.newBuilder() + .setPrivateKey(privateKey) + .setTransaction(transaction) + .build() + + val output = AnySigner.sign(signingInput, CoinType.ELROND, Elrond.SigningOutput.parser()) + val expectedSignature = "b88ad2fe98a7316ea432a0a76c18cd87200fe75f27a8f053ea6532b40317dbec5136c5463aef132ae951b7e60d45d921caaa5903e70821dcda98f237d4ec4308" + + assertEquals(expectedSignature, output.signature) + assertEquals("""{"nonce":0,"value":"0","receiver":"$bobBech32","sender":"$aliceBech32","gasPrice":200000000000000,"gasLimit":500000000,"data":"foo","signature":"$expectedSignature"}""", output.encoded) + } +} diff --git a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/iotex/TestIotexSigning.kt b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/iotex/TestIotexSigning.kt new file mode 100644 index 00000000000..1871c6c0d76 --- /dev/null +++ b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/iotex/TestIotexSigning.kt @@ -0,0 +1,227 @@ +package com.trustwallet.core.app.blockchains.IoTeX + +import com.google.protobuf.ByteString +import com.trustwallet.core.app.utils.toHex +import com.trustwallet.core.app.utils.Numeric +import com.trustwallet.core.app.utils.toHexBytes +import org.junit.Assert.assertEquals +import org.junit.Test +import wallet.core.java.AnySigner +import wallet.core.jni.CoinType.IOTEX +import wallet.core.jni.proto.IoTeX +import wallet.core.jni.proto.IoTeX.SigningOutput + +class TestIotexSigning { + + init { + System.loadLibrary("TrustWalletCore") + } + + @Test + fun testIotexSigningCreate() { + val input = IoTeX.SigningInput.newBuilder() + .setVersion(1) + .setNonce(0) + .setGasLimit(1000000) + .setGasPrice("10") + .setPrivateKey(ByteString.copyFrom(Numeric.hexStringToByteArray("cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1"))) + // test sign Create + val create = IoTeX.Staking.Create.newBuilder().apply { + candidateName = "io19d0p3ah4g8ww9d7kcxfq87yxe7fnr8rpth5shj" + stakedAmount = "100" + stakedDuration = 10000 + autoStake = true + payload = ByteString.copyFrom("payload".toByteArray()) + }.build() + + input.apply { + stakeCreate = create + } + + val sign = AnySigner.sign(input.build(), IOTEX, SigningOutput.parser()) + val signBytes = sign.encoded + assertEquals(signBytes.toByteArray().toHex(), "0x0a4b080118c0843d22023130c2023e0a29696f313964307033616834673877773964376b63786671383779786537666e7238727074683573686a120331303018904e20012a077061796c6f6164124104755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf331a412e8bac421bab88dcd99c26ac8ffbf27f11ee57a41e7d2537891bfed5aed8e2e026d46e55d1b856787bc1cd7c1216a6e2534c5b5d1097c3afe8e657aa27cbbb0801") + } + fun testIotexSigningAddDeposit() { + val input = IoTeX.SigningInput.newBuilder() + .setVersion(1) + .setNonce(0) + .setGasLimit(1000000) + .setGasPrice("10") + .setPrivateKey(ByteString.copyFrom(Numeric.hexStringToByteArray("cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1"))) + // test sign AddDeposit + val adddeposit = IoTeX.Staking.AddDeposit.newBuilder().apply { + bucketIndex = 10 + amount = "10" + payload = ByteString.copyFrom("payload".toByteArray()) + }.build() + + input.apply { + stakeAddDeposit = adddeposit + } + + var signAddDeposit = AnySigner.sign(input.build(), IOTEX, SigningOutput.parser()) + var signBytesAddDeposit = signAddDeposit.encoded + assertEquals(signBytesAddDeposit.toByteArray().toHex(), "0x0a1c080118c0843d22023130da020f080a120231301a077061796c6f6164124104755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf331a41a48ab1feba8181d760de946aefed7d815a89fd9b1ab503d2392bb55e1bb75eec42dddc8bd642f89accc3a37b3cf15a103a95d66695fdf0647b202869fdd66bcb01") + } + fun testIotexSigningUnstake() { + val input = IoTeX.SigningInput.newBuilder() + .setVersion(1) + .setNonce(0) + .setGasLimit(1000000) + .setGasPrice("10") + .setPrivateKey(ByteString.copyFrom(Numeric.hexStringToByteArray("cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1"))) + // test sign Unstake + val unstake = IoTeX.Staking.Reclaim.newBuilder().apply { + bucketIndex = 10 + payload = ByteString.copyFrom("payload".toByteArray()) + }.build() + + input.apply { + stakeUnstake = unstake + } + + val signUnstake = AnySigner.sign(input.build(), IOTEX, SigningOutput.parser()) + val signBytesUnstake = signUnstake.encoded + assertEquals(signBytesUnstake.toByteArray().toHex(), "0x0a18080118c0843d22023130ca020b080a12077061796c6f6164124104755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf331a4100adee39b48e1d3dbbd65298a57c7889709fc4df39987130da306f6997374a184b7e7c232a42f21e89b06e6e7ceab81303c6b7483152d08d19ac829b22eb81e601") + } + fun testIotexSigningWithdraw() { + val input = IoTeX.SigningInput.newBuilder() + .setVersion(1) + .setNonce(0) + .setGasLimit(1000000) + .setGasPrice("10") + .setPrivateKey(ByteString.copyFrom(Numeric.hexStringToByteArray("cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1"))) + // test sign Withdraw + val withdraw = IoTeX.Staking.Reclaim.newBuilder().apply { + bucketIndex = 10 + payload = ByteString.copyFrom("payload".toByteArray()) + }.build() + + input.apply { + stakeWithdraw = withdraw + } + + val signWithdraw = AnySigner.sign(input.build(), IOTEX, SigningOutput.parser()) + val signBytesWithdraw = signWithdraw.encoded + assertEquals(signBytesWithdraw.toByteArray().toHex(), "0x0a18080118c0843d22023130d2020b080a12077061796c6f6164124104755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf331a4152644d102186be6640d46b517331f3402e24424b0d85129595421d28503d75340b2922f5a0d4f667bbd6f576d9816770286b2ce032ba22eaec3952e24da4756b00") + } + fun testIotexSigningRestake() { + val input = IoTeX.SigningInput.newBuilder() + .setVersion(1) + .setNonce(0) + .setGasLimit(1000000) + .setGasPrice("10") + .setPrivateKey(ByteString.copyFrom(Numeric.hexStringToByteArray("cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1"))) + // test sign Restake + val restake = IoTeX.Staking.Restake.newBuilder().apply { + bucketIndex = 10 + stakedDuration = 1000 + autoStake = true + payload = ByteString.copyFrom("payload".toByteArray()) + }.build() + + input.apply { + stakeRestake = restake + } + + val signRestake = AnySigner.sign(input.build(), IOTEX, SigningOutput.parser()) + val signBytesRestake = signRestake.encoded + assertEquals(signBytesRestake.toByteArray().toHex(), "0x0a1d080118c0843d22023130e20210080a10e807180122077061796c6f6164124104755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf331a41e2e763aed5b1fd1a8601de0f0ae34eb05162e34b0389ae3418eedbf762f64959634a968313a6516dba3a97b34efba4753bbed3a33d409ecbd45ac75007cd8e9101") + } + fun testIotexSigningChangeCandidate() { + val input = IoTeX.SigningInput.newBuilder() + .setVersion(1) + .setNonce(0) + .setGasLimit(1000000) + .setGasPrice("10") + .setPrivateKey(ByteString.copyFrom(Numeric.hexStringToByteArray("cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1"))) + // test sign ChangeCandidate + val changecandidate = IoTeX.Staking.ChangeCandidate.newBuilder().apply { + bucketIndex = 10 + candidateName = "io1xpq62aw85uqzrccg9y5hnryv8ld2nkpycc3gza" + payload = ByteString.copyFrom("payload".toByteArray()) + }.build() + + input.apply { + stakeChangeCandidate = changecandidate + } + + val signChangeCandidate = AnySigner.sign(input.build(), IOTEX, SigningOutput.parser()) + val signBytesChangeCandidate = signChangeCandidate.encoded + assertEquals(signBytesChangeCandidate.toByteArray().toHex(), "0x0a43080118c0843d22023130ea0236080a1229696f3178707136326177383575717a72636367397935686e727976386c64326e6b7079636333677a611a077061796c6f6164124104755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf331a41d519eb3747163b945b862989b7e82a7f8468001e9683757cb88d5ddd95f81895047429e858bd48f7d59a88bfec92de231d216293aeba1e4fbe11461d9c9fc99801") + } + fun testIotexSigningTransferOwnership() { + val input = IoTeX.SigningInput.newBuilder() + .setVersion(1) + .setNonce(0) + .setGasLimit(1000000) + .setGasPrice("10") + .setPrivateKey(ByteString.copyFrom(Numeric.hexStringToByteArray("cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1"))) + // test sign TransferOwnership + val transfer = IoTeX.Staking.TransferOwnership.newBuilder().apply { + bucketIndex = 10 + voterAddress = "io1xpq62aw85uqzrccg9y5hnryv8ld2nkpycc3gza" + payload = ByteString.copyFrom("payload".toByteArray()) + }.build() + + input.apply { + stakeTransferOwnership = transfer + } + + val signTransferOwnership = AnySigner.sign(input.build(), IOTEX, SigningOutput.parser()) + val signBytesTransferOwnership = signTransferOwnership.encoded + assertEquals(signBytesTransferOwnership.toByteArray().toHex(), "0x0a43080118c0843d22023130f20236080a1229696f3178707136326177383575717a72636367397935686e727976386c64326e6b7079636333677a611a077061796c6f6164124104755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf331a41fa26db427ab87a56a129196c1604f2e22c4dd2a1f99b2217bc916260757d00093d9e6dccdf53e3b0b64e41a69d71c238fbf9281625164694a74dfbeba075d0ce01") + } + fun testIotexSigningCandidateBasicInfo() { + val input = IoTeX.SigningInput.newBuilder() + .setVersion(1) + .setNonce(0) + .setGasLimit(1000000) + .setGasPrice("10") + .setPrivateKey(ByteString.copyFrom(Numeric.hexStringToByteArray("cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1"))) + // test sign CandidateBasicInfo + val cbi = IoTeX.Staking.CandidateBasicInfo.newBuilder().apply { + name = "test" + operatorAddress = "io1cl6rl2ev5dfa988qmgzg2x4hfazmp9vn2g66ng" + rewardAddress = "io1juvx5g063eu4ts832nukp4vgcwk2gnc5cu9ayd" + }.build() + + input.apply { + candidateUpdate = cbi + } + + val signCandidateBasicInfo = AnySigner.sign(input.build(), IOTEX, SigningOutput.parser()) + val signBytesCandidateBasicInfo = signCandidateBasicInfo.encoded + assertEquals(signBytesCandidateBasicInfo.toByteArray().toHex(), "0x0a69080118c0843d2202313082035c0a04746573741229696f31636c36726c32657635646661393838716d677a673278346866617a6d7039766e326736366e671a29696f316a757678356730363365753474733833326e756b7034766763776b32676e6335637539617964124104755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf331a4101885c9c6684a4a8f2f5bf11f8326f27be48658f292e8f55ec8a11a604bb0c563a11ebf12d995ca1c152e00f8e0f0edf288db711aa10dbdfd5b7d73b4a28e1f701") + } + fun testIotexSigningCandidateRegister() { + val input = IoTeX.SigningInput.newBuilder() + .setVersion(1) + .setNonce(0) + .setGasLimit(1000000) + .setGasPrice("1000") + .setPrivateKey(ByteString.copyFrom(Numeric.hexStringToByteArray("cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1"))) + // test sign CandidateBasicInfo + val cbi = IoTeX.Staking.CandidateBasicInfo.newBuilder().apply { + name = "test" + operatorAddress = "io10a298zmzvrt4guq79a9f4x7qedj59y7ery84he" + rewardAddress = "io13sj9mzpewn25ymheukte4v39hvjdtrfp00mlyv" + }.build() + val cr = IoTeX.Staking.CandidateRegister.newBuilder().apply { + candidate = cbi + stakedAmount = "100" + stakedDuration = 10000 + autoStake = false + ownerAddress ="io19d0p3ah4g8ww9d7kcxfq87yxe7fnr8rpth5shj" + payload = ByteString.copyFrom("payload".toByteArray()) + }.build() + input.apply { + candidateRegister = cr + } + + val signCandidateRegister = AnySigner.sign(input.build(), IOTEX, SigningOutput.parser()) + val signBytesCandidateRegister = signCandidateRegister.encoded + assertEquals(signBytesCandidateRegister.toByteArray().toHex(), "0x0aaa01080118c0843d220431303030fa029a010a5c0a04746573741229696f3130613239387a6d7a7672743467757137396139663478377165646a35397937657279383468651a29696f3133736a396d7a7065776e3235796d6865756b74653476333968766a647472667030306d6c7976120331303018904e2a29696f313964307033616834673877773964376b63786671383779786537666e7238727074683573686a32077061796c6f6164124104755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf331a417819b5bcb635e3577acc8ca757f2c3d6afa451c2b6ff8a9179b141ac68e2c50305679e5d09d288da6f0fb52876a86c74deab6a5247edc6d371de5c2f121e159400") + } +} diff --git a/android/app/src/androidTest/java/com/trustwallet/core/app/utils/TestKeyStore.kt b/android/app/src/androidTest/java/com/trustwallet/core/app/utils/TestKeyStore.kt index 3a19d9c2218..3832db95139 100644 --- a/android/app/src/androidTest/java/com/trustwallet/core/app/utils/TestKeyStore.kt +++ b/android/app/src/androidTest/java/com/trustwallet/core/app/utils/TestKeyStore.kt @@ -13,9 +13,9 @@ class TestKeyStore { @Test fun testDecryptMnemonic() { - val keyStore = StoredKey("Test Wallet", "password") - val result = keyStore.decryptMnemonic("wrong") - val result2 = keyStore.decryptMnemonic("password") + val keyStore = StoredKey("Test Wallet", "password".toByteArray()) + val result = keyStore.decryptMnemonic("wrong".toByteArray()) + val result2 = keyStore.decryptMnemonic("password".toByteArray()) assertNull(result) assertNotNull(result2) @@ -23,7 +23,7 @@ class TestKeyStore { @Test fun testRemoveCoins() { - val password = "password" + val password = "password".toByteArray() val keyStore = StoredKey("Test Wallet", password) val wallet = keyStore.wallet(password) @@ -37,15 +37,47 @@ class TestKeyStore { assertEquals(keyStore.account(0).coin(), CoinType.ETHEREUM) } + @Test + fun testLongHexPassword() { + val json = """ + { + "address": "34bae2218c254ed190c0f5b1dd4323aee8e7da09", + "id": "86066d8c-8dba-4d81-afd4-934e2a2b72a2", + "version": 3, + "crypto": { + "cipher": "aes-128-ctr", + "cipherparams": { + "iv": "a4976ad73057007ad788d1f792db851d" + }, + "ciphertext": "5e4458d69964172c492616b751d6589b4ad7da4217dcfccecc3f4e515a934bb8", + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "n": 4096, + "p": 6, + "r": 8, + "salt": "24c72d92bf88a4f7c7b3f5e3cb3620714d71fceabbb0bc6099f50c6d5d898e7c" + }, + "mac": "c15e3035ddcaca766dfc56648978d33e94d3c57d4a5e13fcf8b5f8dbb0902900" + } + } + """.trimIndent() + val password = "2d6eefbfbd4622efbfbdefbfbd516718efbfbdefbfbdefbfbdefbfbd59efbfbd30efbfbdefbfbd3a4348efbfbd2aefbfbdefbfbd49efbfbd27efbfbd0638efbfbdefbfbdefbfbd4cefbfbd6befbfbdefbfbd6defbfbdefbfbd63efbfbd5aefbfbd61262b70efbfbdefbfbdefbfbdefbfbdefbfbdc7aa373163417cefbfbdefbfbdefbfbd44efbfbdefbfbd1d10efbfbdefbfbdefbfbd61dc9e5b124befbfbd11efbfbdefbfbd2fefbfbdefbfbd3d7c574868efbfbdefbfbdefbfbd37043b7b5c1a436471592f02efbfbd18efbfbdefbfbd2befbfbdefbfbd7218efbfbd6a68efbfbdcb8e5f3328773ec48174efbfbd67efbfbdefbfbdefbfbdefbfbdefbfbd2a31efbfbd7f60efbfbdd884efbfbd57efbfbd25efbfbd590459efbfbd37efbfbd2bdca20fefbfbdefbfbdefbfbdefbfbd39450113efbfbdefbfbdefbfbd454671efbfbdefbfbdd49fefbfbd47efbfbdefbfbdefbfbdefbfbd00efbfbdefbfbdefbfbdefbfbd05203f4c17712defbfbd7bd1bbdc967902efbfbdc98a77efbfbd707a36efbfbd12efbfbdefbfbd57c78cefbfbdefbfbdefbfbd10efbfbdefbfbdefbfbde1a1bb08efbfbdefbfbd26efbfbdefbfbd58efbfbdefbfbdc4b1efbfbd295fefbfbd0eefbfbdefbfbdefbfbd0e6eefbfbd" + val pass = password.toHexByteArray() + val keyStore = StoredKey.importJSON(json.toByteArray()) + val privateKey = keyStore.decryptPrivateKey(pass) + assertEquals(privateKey.toHex(), "0x043c5429c7872502531708ec0d821c711691402caf37ef7ba78a8c506f10653b") + } + @Test fun testExportJSON() { - val password = "password" + val password = "password".toByteArray() val keyStore = StoredKey("Test Wallet", password) val json = keyStore.exportJSON() assertNotNull(json) val newKeyStore = StoredKey.importJSON(json) - val privateKey = newKeyStore.decryptPrivateKey("") + val privateKey = newKeyStore.decryptPrivateKey("".toByteArray()) assertNull(privateKey) } } diff --git a/android/app/src/main/java/com/trustwallet/core/app/MainActivity.kt b/android/app/src/main/java/com/trustwallet/core/app/MainActivity.kt index 4634a387fc4..6461f8e5de4 100644 --- a/android/app/src/main/java/com/trustwallet/core/app/MainActivity.kt +++ b/android/app/src/main/java/com/trustwallet/core/app/MainActivity.kt @@ -2,11 +2,144 @@ package com.trustwallet.core.app import androidx.appcompat.app.AppCompatActivity import android.os.Bundle +import android.widget.TextView +import com.google.protobuf.ByteString +import kotlinx.android.synthetic.main.activity_main.* +import wallet.core.jni.CoinType +import wallet.core.jni.HDWallet +import wallet.core.java.AnySigner +import wallet.core.jni.proto.Ethereum +import wallet.core.jni.BitcoinScript +import wallet.core.jni.BitcoinSigHashType +import wallet.core.jni.proto.Bitcoin +import java.math.BigInteger +import kotlin.experimental.and class MainActivity : AppCompatActivity() { + init { + System.loadLibrary("TrustWalletCore") + } + + private val seedPhrase = "agree auto mandate shaft latin blade arrive card betray expand fog vanish" + private val passphrase = "" + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) + + // 'Import' a wallet + val wallet = HDWallet(seedPhrase, passphrase) + showLog("Mnemonic: \n${wallet.mnemonic()}") + + /* + // Ethereum example + val coinEth: CoinType = CoinType.ETHEREUM + // Get the default address + val addressEth = wallet.getAddressForCoin(coinEth) + showLog("Default ETH address: \n$addressEth") + + // Signing a transaction (using EthereumSigner) + val secretPrivateKey = wallet.getKeyForCoin(coinEth) + val dummyReceiverAddress = "0xC37054b3b48C3317082E7ba872d7753D13da4986" + + val signerInput = Ethereum.SigningInput.newBuilder().apply { + this.chainId = ByteString.copyFrom(BigInteger("01").toByteArray()) + this.gasPrice = BigInteger("d693a400", 16).toByteString() // decimal 3600000000 + this.gasLimit = BigInteger("5208", 16).toByteString() // decimal 21000 + this.toAddress = dummyReceiverAddress + this.amount = BigInteger("0348bca5a16000", 16).toByteString() + this.privateKey = ByteString.copyFrom(secretPrivateKey.data()) + }.build() + val signerOutput = AnySigner.sign(signerInput, CoinType.ETHEREUM, Ethereum.SigningOutput.parser()) + showLog("Signed transaction: \n${signerOutput.encoded.toByteArray().toHexString(false)}") + + */ + + // Bitcoin example + val coinBtc: CoinType = CoinType.DIGITALGOLD + // Get the default address + val addressBtc = wallet.getAddressForCoin(coinBtc) + showLog("Default DGLD address: \n$addressBtc") + + // Build a transaction + val utxoTxId = "050d00e2e18ef13969606f1ceee290d3f49bd940684ce39898159352952b8ce2".hexStringToByteArray(); + val secretPrivateKeyBtc = wallet.getKeyForCoin(coinBtc) + val toAddress = "GJCMxPGMH3LVoGtZ3yEhPYbMVnYwSybBzi" + val changeAddress = "GcbkjFtaCsfvnGPXfVsXRaN8QnRDtHywML" + val script = BitcoinScript.buildForAddress(addressBtc, coinBtc).data() + //showLog("script: $script") + + val outPoint = Bitcoin.OutPoint.newBuilder().apply { + this.hash = ByteString.copyFrom(utxoTxId) + this.index = 2 + }.build() + //showLog("outPoint: $outPoint") + + val utxo = Bitcoin.UnspentTransaction.newBuilder().apply { + this.amount = 5151 + this.outPoint = outPoint + this.script = ByteString.copyFrom(script) + }.build() + //showLog("utxo: $utxo") + + val input = Bitcoin.SigningInput.newBuilder().apply { + this.amount = 600 + this.hashType = BitcoinSigHashType.ALL.value().or(BitcoinSigHashType.FORK.value()) + this.toAddress = toAddress + this.changeAddress = changeAddress + this.byteFee = 1 + this.coinType = coinBtc.value() + this.addUtxo(utxo) + this.addPrivateKey(ByteString.copyFrom(secretPrivateKeyBtc.data())) + } + //showLog("input: $input") + + // Calculate fee (plan a tranaction) + val plan = AnySigner.plan(input.build(), coinBtc, Bitcoin.TransactionPlan.parser()) + //showLog("plan: $plan") + + // Set the precomputed plan + input.plan = plan + val output = AnySigner.sign(input.build(), coinBtc, Bitcoin.SigningOutput.parser()) + //showLog("output: $output") + + assert(output.error.isEmpty()) + val signedTransaction = output.encoded?.toByteArray() + showLog("Signed DGLD transaction: \n${signedTransaction?.toHexString()}") + } + + private fun ByteArray.toHexString(withPrefix: Boolean = true): String { + val stringBuilder = StringBuilder() + if(withPrefix) { + stringBuilder.append("0x") + } + for (element in this) { + stringBuilder.append(String.format("%02x", element and 0xFF.toByte())) + } + return stringBuilder.toString() + } + + private fun BigInteger.toByteString(): ByteString { + return ByteString.copyFrom(this.toByteArray()) + } + + private fun String.hexStringToByteArray() : ByteArray { + val HEX_CHARS = "0123456789ABCDEF" + val result = ByteArray(length / 2) + for (i in 0 until length step 2) { + val firstIndex = HEX_CHARS.indexOf(this[i].toUpperCase()); + val secondIndex = HEX_CHARS.indexOf(this[i + 1].toUpperCase()); + val octet = firstIndex.shl(4).or(secondIndex) + result.set(i.shr(1), octet.toByte()) + } + return result + } + + private fun showLog(log: String) { + val tv = TextView(this) + tv.text = log + logView.addView(tv) + println(log) } } diff --git a/android/app/src/main/res/layout/activity_main.xml b/android/app/src/main/res/layout/activity_main.xml index b3837857f0e..8f453ca10b9 100644 --- a/android/app/src/main/res/layout/activity_main.xml +++ b/android/app/src/main/res/layout/activity_main.xml @@ -1,7 +1,10 @@ - - \ No newline at end of file + android:orientation="vertical" + tools:context=".MainActivity"> + + \ No newline at end of file diff --git a/android/build.gradle b/android/build.gradle index c3b350a38ce..8d60b26e84e 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,13 +1,13 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.3.21' + ext.kotlin_version = '1.3.72' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.6.1' + classpath 'com.android.tools.build:gradle:3.6.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' diff --git a/android/trustwalletcore/build.gradle b/android/trustwalletcore/build.gradle index 83bc1d15148..c091b2c9c8b 100644 --- a/android/trustwalletcore/build.gradle +++ b/android/trustwalletcore/build.gradle @@ -3,11 +3,12 @@ apply plugin: 'maven-publish' group='com.github.trustwallet' android { - compileSdkVersion 28 + compileSdkVersion 29 + ndkVersion '21.1.6352462' defaultConfig { minSdkVersion 23 - targetSdkVersion 28 + targetSdkVersion 29 versionCode 1 versionName "1.0" } @@ -33,10 +34,11 @@ android { path "../../CMakeLists.txt" } } + buildToolsVersion = '29.0.3' } dependencies { - implementation 'io.grpc:grpc-protobuf:1.24.2' + implementation 'io.grpc:grpc-protobuf:1.29.0' } apply from: 'maven-push.gradle' diff --git a/bootstrap.sh b/bootstrap.sh index e5ddf642a52..51f0eb67298 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -10,7 +10,7 @@ echo "#### Generating files... ####" tools/generate-files echo "#### Building... ####" -cmake -H. -Bbuild -DCMAKE_BUILD_TYPE=Debug +cmake . -Bbuild -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ make -Cbuild tests TrezorCryptoTests if [ -x "$(command -v clang-tidy)" ]; then @@ -25,3 +25,5 @@ build/trezor-crypto/tests/TrezorCryptoTests ROOT="`dirname \"$0\"`" TESTS_ROOT="`(cd \"$ROOT/tests\" && pwd)`" build/tests/tests "$TESTS_ROOT" + +make -Cbuild walletconsole diff --git a/cmake/Protobuf.cmake b/cmake/Protobuf.cmake index c9a6af88215..7f27286911e 100644 --- a/cmake/Protobuf.cmake +++ b/cmake/Protobuf.cmake @@ -1,5 +1,5 @@ -set(protobuf_SOURCE_DIR ${CMAKE_SOURCE_DIR}/wallet-core/build/protobuf/staging/protobuf-3.9.0) -set(protobuf_source_dir ${CMAKE_SOURCE_DIR}/wallet-core/build/protobuf/staging/protobuf-3.9.0) +set(protobuf_SOURCE_DIR ${CMAKE_SOURCE_DIR}/build/local/src/protobuf/protobuf-3.9.0) +set(protobuf_source_dir ${CMAKE_SOURCE_DIR}/build/local/src/protobuf/protobuf-3.9.0) # Updated from https://github.com/protocolbuffers/protobuf/blob/master/cmake/libprotopuf.cmake diff --git a/coins.json b/coins.json index 5fc87eb88cb..efcb8591e1a 100644 --- a/coins.json +++ b/coins.json @@ -571,9 +571,9 @@ "xpub": "xpub", "xprv": "xprv", "explorer": { - "url": "https://sochain.com", - "txPath": "/tx/ZEC/", - "accountPath": "/address/ZEC/" + "url": "https://blockchair.com/zcash", + "txPath": "/transaction/", + "accountPath": "/address/" }, "info": { "url": "https://z.cash", @@ -682,7 +682,7 @@ "curve": "ed25519", "publicKeyType": "ed25519", "explorer": { - "url": "https://stellarscan.io", + "url": "https://blockchair.com/stellar", "txPath": "/transaction/", "accountPath": "/account/" }, @@ -858,7 +858,6 @@ "curve": "ed25519Blake2bNano", "publicKeyType": "ed25519Blake2b", "url": "https://nano.org", - "rpcNodeInfo": "https://github.com/nanocurrency/nano-node", "explorer": { "url": "https://nanocrawler.cc", "txPath": "/explorer/block/", @@ -1073,18 +1072,17 @@ "derivationPath": "m/44'/235'/0'/0/0", "curve": "secp256k1", "publicKeyType": "secp256k1", - "url": "https://fio.foundation", - "rpcNodeInfo": "https://fio.foundation", + "url": "https://fioprotocol.io/", "explorer": { - "url": "https://fio.foundation", - "txPath": "/?", - "accountPath": "/?" + "url": "https://explorer.fioprotocol.io", + "txPath": "/transaction/", + "accountPath": "/account/" }, "info": { - "url": "https://fio.foundation", - "client": "https://fio.foundation", - "clientPublic": "", - "clientDocs": "https://fio.foundation" + "url": "https://fioprotocol.io", + "client": "https://github.com/fioprotocol/fio", + "clientPublic": "https://mainnet.fioprotocol.io", + "clientDocs": "https://developers.fioprotocol.io" } }, { @@ -1332,5 +1330,57 @@ "clientPublic": "", "clientDocs": "https://docs.lotu.sh" } + }, + { + "id": "elrond", + "name": "Elrond", + "symbol": "ERD", + "decimals": 18, + "blockchain": "ElrondNetwork", + "derivationPath": "m/44'/508'/0'/0'/0'", + "curve": "ed25519", + "publicKeyType": "ed25519", + "hrp": "erd", + "explorer": { + "url": "https://explorer.elrond.com", + "txPath": "/transactions/", + "accountPath": "/address/" + }, + "info": { + "url": "https://elrond.com/", + "client": "https://github.com/ElrondNetwork/elrond-go", + "clientPublic": "https://api.elrond.com", + "clientDocs": "https://docs.elrond.com" + } + }, + { + "id": "dgld", + "name": "DigitalGold", + "symbol": "DGLD", + "decimals": 8, + "blockchain": "Bitcoin", + "derivationPath": "m/44'/452'/0'/0/0", + "curve": "secp256k1", + "publicKeyType": "secp256k1", + "p2pkhPrefix": 38, + "p2shPrefix": 97, + "hrp": "bc", + "publicKeyHasher": "sha256ripemd", + "base58Hasher": "sha256d", + "xpub": "zpub", + "xprv": "zprv", + "explorer": { + "url": "https://explorer.dgld.ch", + "txPath": "/tx/", + "accountPath": "/address/", + "sampleTx": "68e203d1837aad907f4c09b22835e78304a7ae5c4268d0c2487958e3a1858b6e", + "sampleAccount": "g3X4Jwf9WLuBqET7tr2bCkDX3A2FGBrUm8" + }, + "info": { + "url": "https://dgld.ch/", + "client": "https://github.com/goldtokensa/ocean-wallet/releases", + "clientPublic": "https://dgld.ch/wallet-id", + "clientDocs": "https://github.com/goldtokensa/ocean-wallet/releases" + } } ] diff --git a/docs/coins.md b/docs/coins.md index bd8b83ac4f5..82818d00437 100644 --- a/docs/coins.md +++ b/docs/coins.md @@ -27,7 +27,7 @@ This list is generated from [./coins.json](../coins.json) | 178 | POA Network | POA | | | | 194 | EOS | EOS | | | | 195 | Tron | TRX | | | -| 235 | FIO | FIO | | | +| 235 | FIO | FIO | | | | 242 | Nimiq | NIM | | | | 283 | Algorand | ALGO | | | | 304 | IoTeX | IOTX | | | @@ -38,11 +38,13 @@ This list is generated from [./coins.json](../coins.json) | 397 | NEAR | NEAR | | | | 425 | Aion | AION | | | | 434 | Kusama | KSM | | | +| 452 | DigitalGold | DGLD | | | | 457 | Aeternity | AE | | | | 459 | Kava | KAVA | | | | 461 | Filecoin | FIL | | | | 500 | Theta | THETA | | | | 501 | Solana | SOL | | | +| 508 | Elrond | ERD | | | | 714 | Binance | BNB | | | | 818 | VeChain | VET | | | | 820 | Callisto | CLO | | | diff --git a/include/TrustWalletCore/TWBitcoinScript.h b/include/TrustWalletCore/TWBitcoinScript.h index a50499fa4db..a382328c45d 100644 --- a/include/TrustWalletCore/TWBitcoinScript.h +++ b/include/TrustWalletCore/TWBitcoinScript.h @@ -49,6 +49,10 @@ bool TWBitcoinScriptIsPayToScriptHash(const struct TWBitcoinScript *_Nonnull scr TW_EXPORT_PROPERTY bool TWBitcoinScriptIsPayToWitnessScriptHash(const struct TWBitcoinScript *_Nonnull script); +/// Determines whether this is a pay-to-witness-public-key-hash (P2WPKH) script. +TW_EXPORT_PROPERTY +bool TWBitcoinScriptIsPayToWitnessPublicKeyHash(const struct TWBitcoinScript *_Nonnull script); + /// Determines whether this is a witness programm script. TW_EXPORT_PROPERTY bool TWBitcoinScriptIsWitnessProgram(const struct TWBitcoinScript *_Nonnull script); diff --git a/include/TrustWalletCore/TWBlockchain.h b/include/TrustWalletCore/TWBlockchain.h index 8b1b82d6028..6a174d8af7c 100644 --- a/include/TrustWalletCore/TWBlockchain.h +++ b/include/TrustWalletCore/TWBlockchain.h @@ -45,6 +45,7 @@ enum TWBlockchain { TWBlockchainCardano = 30, TWBlockchainNEO = 31, TWBlockchainFilecoin = 32, + TWBlockchainElrondNetwork = 33, }; TW_EXTERN_C_END diff --git a/include/TrustWalletCore/TWCoinType.h b/include/TrustWalletCore/TWCoinType.h index 0c2a152cec0..41acbd6af0b 100644 --- a/include/TrustWalletCore/TWCoinType.h +++ b/include/TrustWalletCore/TWCoinType.h @@ -79,6 +79,8 @@ enum TWCoinType { TWCoinTypeKusama = 434, TWCoinTypePolkadot = 354, TWCoinTypeFilecoin = 461, + TWCoinTypeElrond = 508, + TWCoinTypeDigitalGold = 452, }; /// Returns the blockchain for a coin type. diff --git a/include/TrustWalletCore/TWStoredKey.h b/include/TrustWalletCore/TWStoredKey.h index 784339fd6e0..bb2048d236f 100644 --- a/include/TrustWalletCore/TWStoredKey.h +++ b/include/TrustWalletCore/TWStoredKey.h @@ -21,88 +21,88 @@ struct TWStoredKey; /// Loads a key from a file. TW_EXPORT_STATIC_METHOD -struct TWStoredKey *_Nullable TWStoredKeyLoad(TWString *_Nonnull path); +struct TWStoredKey* _Nullable TWStoredKeyLoad(TWString* _Nonnull path); /// Imports a private key. TW_EXPORT_STATIC_METHOD -struct TWStoredKey *_Nullable TWStoredKeyImportPrivateKey(TWData *_Nonnull privateKey, TWString *_Nonnull name, TWString *_Nonnull password, enum TWCoinType coin); +struct TWStoredKey* _Nullable TWStoredKeyImportPrivateKey(TWData* _Nonnull privateKey, TWString* _Nonnull name, TWData* _Nonnull password, enum TWCoinType coin); /// Imports an HD wallet. TW_EXPORT_STATIC_METHOD -struct TWStoredKey *_Nullable TWStoredKeyImportHDWallet(TWString *_Nonnull mnemonic, TWString *_Nonnull name, TWString *_Nonnull password, enum TWCoinType coin); +struct TWStoredKey* _Nullable TWStoredKeyImportHDWallet(TWString* _Nonnull mnemonic, TWString* _Nonnull name, TWData* _Nonnull password, enum TWCoinType coin); /// Imports a key from JSON. TW_EXPORT_STATIC_METHOD -struct TWStoredKey *_Nullable TWStoredKeyImportJSON(TWData *_Nonnull json); +struct TWStoredKey* _Nullable TWStoredKeyImportJSON(TWData* _Nonnull json); /// Creates a new key. TW_EXPORT_STATIC_METHOD -struct TWStoredKey *_Nonnull TWStoredKeyCreate(TWString *_Nonnull name, TWString *_Nonnull password); +struct TWStoredKey* _Nonnull TWStoredKeyCreate(TWString* _Nonnull name, TWData* _Nonnull password); TW_EXPORT_METHOD -void TWStoredKeyDelete(struct TWStoredKey *_Nonnull key); +void TWStoredKeyDelete(struct TWStoredKey* _Nonnull key); /// Stored key uniqie identifier. TW_EXPORT_PROPERTY -TWString *_Nullable TWStoredKeyIdentifier(struct TWStoredKey *_Nonnull key); +TWString* _Nullable TWStoredKeyIdentifier(struct TWStoredKey* _Nonnull key); /// Stored key namer. TW_EXPORT_PROPERTY -TWString *_Nonnull TWStoredKeyName(struct TWStoredKey *_Nonnull key); +TWString* _Nonnull TWStoredKeyName(struct TWStoredKey* _Nonnull key); /// Whether this key is a mnemonic phrase for a HD wallet. TW_EXPORT_PROPERTY -bool TWStoredKeyIsMnemonic(struct TWStoredKey *_Nonnull key); +bool TWStoredKeyIsMnemonic(struct TWStoredKey* _Nonnull key); /// The number of accounts. TW_EXPORT_PROPERTY -size_t TWStoredKeyAccountCount(struct TWStoredKey *_Nonnull key); +size_t TWStoredKeyAccountCount(struct TWStoredKey* _Nonnull key); /// Returns the account at a given index. TW_EXPORT_METHOD -struct TWAccount *_Nullable TWStoredKeyAccount(struct TWStoredKey *_Nonnull key, size_t index); +struct TWAccount* _Nullable TWStoredKeyAccount(struct TWStoredKey* _Nonnull key, size_t index); /// Returns the account for a specific coin, creating it if necessary. TW_EXPORT_METHOD -struct TWAccount *_Nullable TWStoredKeyAccountForCoin(struct TWStoredKey *_Nonnull key, enum TWCoinType coin, struct TWHDWallet *_Nullable wallet); +struct TWAccount* _Nullable TWStoredKeyAccountForCoin(struct TWStoredKey* _Nonnull key, enum TWCoinType coin, struct TWHDWallet* _Nullable wallet); /// Remove the account for a specific coin TW_EXPORT_METHOD -void TWStoredKeyRemoveAccountForCoin(struct TWStoredKey *_Nonnull key, enum TWCoinType coin); +void TWStoredKeyRemoveAccountForCoin(struct TWStoredKey* _Nonnull key, enum TWCoinType coin); /// Adds a new account. TW_EXPORT_METHOD -void TWStoredKeyAddAccount(struct TWStoredKey *_Nonnull key, TWString *_Nonnull address, TWString *_Nonnull derivationPath, TWString *_Nonnull extetndedPublicKey); +void TWStoredKeyAddAccount(struct TWStoredKey* _Nonnull key, TWString* _Nonnull address, TWString* _Nonnull derivationPath, TWString* _Nonnull extetndedPublicKey); /// Saves the key to a file. TW_EXPORT_METHOD -bool TWStoredKeyStore(struct TWStoredKey *_Nonnull key, TWString *_Nonnull path); +bool TWStoredKeyStore(struct TWStoredKey* _Nonnull key, TWString* _Nonnull path); /// Decrypts the private key. TW_EXPORT_METHOD -TWData *_Nullable TWStoredKeyDecryptPrivateKey(struct TWStoredKey *_Nonnull key, TWString *_Nonnull password); +TWData* _Nullable TWStoredKeyDecryptPrivateKey(struct TWStoredKey* _Nonnull key, TWData* _Nonnull password); /// Decrypts the mnemonic phrase. TW_EXPORT_METHOD -TWString *_Nullable TWStoredKeyDecryptMnemonic(struct TWStoredKey *_Nonnull key, TWString *_Nonnull password); +TWString* _Nullable TWStoredKeyDecryptMnemonic(struct TWStoredKey* _Nonnull key, TWData* _Nonnull password); /// Returns the private key for a specific coin. TW_EXPORT_METHOD -struct TWPrivateKey *_Nullable TWStoredKeyPrivateKey(struct TWStoredKey *_Nonnull key, enum TWCoinType coin, TWString *_Nonnull password); +struct TWPrivateKey* _Nullable TWStoredKeyPrivateKey(struct TWStoredKey* _Nonnull key, enum TWCoinType coin, TWData* _Nonnull password); /// Dercrypts and returns the HD Wallet for mnemonic phrase keys. TW_EXPORT_METHOD -struct TWHDWallet *_Nullable TWStoredKeyWallet(struct TWStoredKey *_Nonnull key, TWString *_Nonnull password); +struct TWHDWallet* _Nullable TWStoredKeyWallet(struct TWStoredKey* _Nonnull key, TWData* _Nonnull password); /// Exports the key as JSON TW_EXPORT_METHOD -TWData *_Nullable TWStoredKeyExportJSON(struct TWStoredKey *_Nonnull key); +TWData* _Nullable TWStoredKeyExportJSON(struct TWStoredKey* _Nonnull key); /// Fills in empty and invalid addresses. /// /// This method needs the encryption password to re-derive addresses from private keys. /// @returns `false` if the password is incorrect. TW_EXPORT_METHOD -bool TWStoredKeyFixAddresses(struct TWStoredKey *_Nonnull key, TWString *_Nonnull password); +bool TWStoredKeyFixAddresses(struct TWStoredKey* _Nonnull key, TWData* _Nonnull password); TW_EXTERN_C_END diff --git a/samples/android/app/build.gradle b/samples/android/app/build.gradle index 53d7c729e47..6dcd7757e4a 100644 --- a/samples/android/app/build.gradle +++ b/samples/android/app/build.gradle @@ -24,7 +24,7 @@ android { } project.ext { - walletcore_version = "2.0.3" + walletcore_version = "2.0.5" } dependencies { diff --git a/samples/android/build.gradle b/samples/android/build.gradle index a706027ba80..b908ed10fd6 100644 --- a/samples/android/build.gradle +++ b/samples/android/build.gradle @@ -8,7 +8,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.6.1' + classpath 'com.android.tools.build:gradle:3.6.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/samples/cpp/CMakeLists.txt b/samples/cpp/CMakeLists.txt index 9f4dbfbde76..79b9aa62845 100644 --- a/samples/cpp/CMakeLists.txt +++ b/samples/cpp/CMakeLists.txt @@ -39,7 +39,7 @@ else () add_compile_options (-Werror=switch) endif () -set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++") set (CMAKE_C_STANDARD 11) set (CMAKE_C_STANDARD_REQUIRED ON) diff --git a/samples/go/main.go b/samples/go/main.go index 3f56b5241a9..38507a3a341 100644 --- a/samples/go/main.go +++ b/samples/go/main.go @@ -1,7 +1,7 @@ package main -// #cgo CFLAGS: -I/wallet-core/include -// #cgo LDFLAGS: -L/wallet-core/build -L/wallet-core/build/trezor-crypto -lTrustWalletCore -lprotobuf -lTrezorCrypto -lc++ -lm +// #cgo CFLAGS: -I../../include +// #cgo LDFLAGS: -L../../build -L../../build/trezor-crypto -lTrustWalletCore -lprotobuf -lTrezorCrypto -lc++ -lm // #include // #include // #include diff --git a/src/Aeternity/Address.cpp b/src/Aeternity/Address.cpp index ff256597044..101ba527854 100644 --- a/src/Aeternity/Address.cpp +++ b/src/Aeternity/Address.cpp @@ -13,7 +13,7 @@ using namespace TW::Aeternity; /// Determines whether a string makes a valid address. -bool Address::isValid(const std::string &string) { +bool Address::isValid(const std::string& string) { if (string.empty()) { return false; } @@ -34,7 +34,7 @@ Address::Address(const PublicKey &publicKey) { } /// Initializes an address from a string representation. -Address::Address(const std::string &string) { +Address::Address(const std::string& string) { if (!isValid(string)) { throw std::invalid_argument("Invalid address"); } @@ -48,11 +48,11 @@ std::string Address::string() const { return Identifiers::prefixAccountPubkey + Base58::bitcoin.encodeCheck(bytes); } -bool Address::checkType(const std::string &type) { +bool Address::checkType(const std::string& type) { return type == Identifiers::prefixAccountPubkey; } -bool Address::checkPayload(const std::string &payload) { +bool Address::checkPayload(const std::string& payload) { unsigned long base58 = Base58::bitcoin.decodeCheck(payload).size(); return base58 == size; } diff --git a/src/Aeternity/Address.h b/src/Aeternity/Address.h index 0f8b4e24724..07e9b732939 100644 --- a/src/Aeternity/Address.h +++ b/src/Aeternity/Address.h @@ -15,10 +15,10 @@ class Address { Data bytes; /// Determines whether a string makes a valid address. - static bool isValid(const std::string &string); + static bool isValid(const std::string& string); /// Initializes an address from a string representation. - explicit Address(const std::string &string); + explicit Address(const std::string& string); /// Initializes an address from a public key. explicit Address(const PublicKey &publicKey); @@ -28,8 +28,8 @@ class Address { private: - static bool checkType(const std::string &type); - static bool checkPayload(const std::string &payload); + static bool checkType(const std::string& type); + static bool checkPayload(const std::string& payload); }; inline bool operator==(const Address& lhs, const Address& rhs) { diff --git a/src/Aeternity/Signer.cpp b/src/Aeternity/Signer.cpp index 02a6c0412a2..7c9adf1fafa 100644 --- a/src/Aeternity/Signer.cpp +++ b/src/Aeternity/Signer.cpp @@ -48,7 +48,7 @@ Proto::SigningOutput Signer::sign(const TW::PrivateKey &privateKey, Transaction return createProtoOutput(signature, signedEncodedTx); } -Data Signer::buildRlpTxRaw(Data &txRaw, Data &sigRaw) { +Data Signer::buildRlpTxRaw(Data& txRaw, Data& sigRaw) { auto rlpTxRaw = Data(); auto signaturesList = Data(); append(signaturesList, Ethereum::RLP::encode(sigRaw)); @@ -61,7 +61,7 @@ Data Signer::buildRlpTxRaw(Data &txRaw, Data &sigRaw) { return Ethereum::RLP::encodeList(rlpTxRaw); } -Data Signer::buildMessageToSign(Data &txRaw) { +Data Signer::buildMessageToSign(Data& txRaw) { auto data = Data(); Data bytes(Identifiers::networkId.begin(), Identifiers::networkId.end()); append(data, bytes); @@ -69,7 +69,7 @@ Data Signer::buildMessageToSign(Data &txRaw) { return data; } -Proto::SigningOutput Signer::createProtoOutput(std::string &signature, const std::string &signedTx) { +Proto::SigningOutput Signer::createProtoOutput(std::string& signature, const std::string& signedTx) { auto output = Proto::SigningOutput(); output.set_signature(signature); @@ -77,7 +77,7 @@ Proto::SigningOutput Signer::createProtoOutput(std::string &signature, const std return output; } -std::string Signer::encodeBase64WithChecksum(const std::string &prefix, const TW::Data &rawTx) { +std::string Signer::encodeBase64WithChecksum(const std::string& prefix, const TW::Data& rawTx) { auto checksum = Hash::sha256(Hash::sha256(rawTx)); std::vector checksumPart(checksum.begin(), checksum.begin() + checkSumSize); diff --git a/src/Aeternity/Signer.h b/src/Aeternity/Signer.h index eae11aa4bc4..dd289e5487d 100644 --- a/src/Aeternity/Signer.h +++ b/src/Aeternity/Signer.h @@ -21,14 +21,14 @@ class Signer { private: static const uint8_t checkSumSize = 4; - static Data buildRlpTxRaw(Data &txRaw, Data &sigRaw); + static Data buildRlpTxRaw(Data& txRaw, Data& sigRaw); - static Data buildMessageToSign(Data &txRaw); + static Data buildMessageToSign(Data& txRaw); - static Proto::SigningOutput createProtoOutput(std::string &signature, const std::string &signedTx); + static Proto::SigningOutput createProtoOutput(std::string& signature, const std::string& signedTx); /// Encode a byte array into base64 with prefix and a checksum - static std::string encodeBase64WithChecksum(const std::string &prefix, const TW::Data &rawTx); + static std::string encodeBase64WithChecksum(const std::string& prefix, const TW::Data& rawTx); }; } // namespace TW::Aeternity diff --git a/src/Aeternity/Transaction.cpp b/src/Aeternity/Transaction.cpp index 198df6c3af0..416531544b5 100644 --- a/src/Aeternity/Transaction.cpp +++ b/src/Aeternity/Transaction.cpp @@ -26,11 +26,11 @@ Data Transaction::encode() { append(encoded, encodeSafeZero(nonce)); append(encoded, Ethereum::RLP::encode(payload)); - const Data &raw = Ethereum::RLP::encodeList(encoded); + const Data& raw = Ethereum::RLP::encodeList(encoded); return raw; } -TW::Data Transaction::buildTag(const std::string &address) { +TW::Data Transaction::buildTag(const std::string& address) { auto payload = address.substr(Identifiers::prefixTransaction.size(), address.size()); auto data = Data(); diff --git a/src/Aeternity/Transaction.h b/src/Aeternity/Transaction.h index 979d9b8312d..6bace4629b8 100644 --- a/src/Aeternity/Transaction.h +++ b/src/Aeternity/Transaction.h @@ -31,11 +31,11 @@ class Transaction { uint64_t nonce; Transaction( - std::string &sender_id, - std::string &recipientId, + std::string& sender_id, + std::string& recipientId, uint256_t amount, uint256_t fee, - std::string &payload, + std::string& payload, uint64_t ttl, uint64_t nonce ) @@ -51,7 +51,7 @@ class Transaction { //// buildIDTag assemble an id() object //// see https://github.com/aeternity/protocol/blob/epoch-v0.22.0/serializations.md#the-id-type - static Data buildTag(const std::string &address); + static Data buildTag(const std::string& address); /// Awternity network does not accept zero int values as rlp param, /// instead empty byte array should be encoded diff --git a/src/Aion/Transaction.h b/src/Aion/Transaction.h index e1c8013e5bf..c87e5bc0256 100644 --- a/src/Aion/Transaction.h +++ b/src/Aion/Transaction.h @@ -28,7 +28,7 @@ class Transaction { std::vector signature; Transaction(uint128_t nonce, uint128_t gasPrice, uint128_t gasLimit, Address to, - uint128_t amount, Data payload) + uint128_t amount, const Data& payload) : nonce(std::move(nonce)) , gasPrice(std::move(gasPrice)) , gasLimit(std::move(gasLimit)) diff --git a/src/Algorand/BinaryCoding.h b/src/Algorand/BinaryCoding.h index 87895a97daa..3a169cf3e00 100644 --- a/src/Algorand/BinaryCoding.h +++ b/src/Algorand/BinaryCoding.h @@ -11,7 +11,7 @@ namespace TW::Algorand { -static inline void encodeString(std::string string, Data &data) { +static inline void encodeString(std::string string, Data& data) { // encode string header auto bytes = Data(string.begin(), string.end()); if (bytes.size() < 0x20) { @@ -36,7 +36,7 @@ static inline void encodeString(std::string string, Data &data) { append(data, bytes); } -static inline void encodeNumber(uint64_t number, Data &data) { +static inline void encodeNumber(uint64_t number, Data& data) { if (number < 0x80) { // positive fixint data.push_back(static_cast(number)); @@ -59,7 +59,7 @@ static inline void encodeNumber(uint64_t number, Data &data) { } } -static inline void encodeBytes(const Data &bytes, Data &data) { +static inline void encodeBytes(const Data& bytes, Data& data) { auto size = bytes.size(); if (size < 0x100) { // bin 8 diff --git a/src/Algorand/Transaction.cpp b/src/Algorand/Transaction.cpp index a2f6cdd7820..ac608af5b3e 100644 --- a/src/Algorand/Transaction.cpp +++ b/src/Algorand/Transaction.cpp @@ -71,7 +71,7 @@ Data Transaction::serialize() const { return data; } -Data Transaction::serialize(Data &signature) const { +Data Transaction::serialize(Data& signature) const { /* Algorand transaction and signature are encoded with msgpack: { "sig": diff --git a/src/Algorand/Transaction.h b/src/Algorand/Transaction.h index a545d65d48f..f7b9c3dd694 100644 --- a/src/Algorand/Transaction.h +++ b/src/Algorand/Transaction.h @@ -27,7 +27,7 @@ class Transaction { Data genesisHash; Transaction(Address &from, Address &to, uint64_t fee, uint64_t amount, uint64_t firstRound, - uint64_t lastRound, Data ¬e, std::string type, std::string &genesisIdg, Data &genesisHash) + uint64_t lastRound, Data& note, std::string type, std::string& genesisIdg, Data& genesisHash) : from(from) , to(to) , fee(fee), amount(amount) , firstRound(firstRound), lastRound(lastRound) @@ -36,7 +36,7 @@ class Transaction { public: Data serialize() const; - Data serialize(Data &signature) const; + Data serialize(Data& signature) const; }; } // namespace TW::Algorand diff --git a/src/Base58.cpp b/src/Base58.cpp index 207809114c3..d11312b3605 100644 --- a/src/Base58.cpp +++ b/src/Base58.cpp @@ -11,6 +11,7 @@ #include #include +#include using namespace TW; @@ -77,7 +78,7 @@ Data Base58::decode(const char* begin, const char* end) const { auto it = begin; // Skip leading spaces. - it = std::find_if_not(it, end, std::isspace); + it = std::find_if_not(it, end, [](unsigned char ch) -> bool { return std::isspace(ch); }); // Skip and count leading zeros. std::size_t zeroes = 0; @@ -118,7 +119,7 @@ Data Base58::decode(const char* begin, const char* end) const { } // Skip trailing spaces. - it = std::find_if_not(it, end, std::isspace); + it = std::find_if_not(it, end, [](unsigned char ch) -> bool { return std::isspace(ch); }); if (it != end) { // Extra charaters at the end return {}; diff --git a/src/Base58Address.h b/src/Base58Address.h index c294f364161..1a887cc9c63 100644 --- a/src/Base58Address.h +++ b/src/Base58Address.h @@ -26,10 +26,13 @@ class Base58Address { std::array bytes; /// Determines whether a collection of bytes makes a valid address. - template - static bool isValid(const T& data) { + static bool isValid(const Data& data) { return data.size() == size; } + /*template + static bool isValid(const T& data) { + return data.size() == size; + }*/ /// Determines whether a string makes a valid address. static bool isValid(const std::string& string) { diff --git a/src/Bech32Address.h b/src/Bech32Address.h index a5aea665805..23b4c06a640 100644 --- a/src/Bech32Address.h +++ b/src/Bech32Address.h @@ -48,7 +48,7 @@ class Bech32Address { Bech32Address(const std::string& hrp, HasherType hasher, const PublicKey& publicKey); void setHrp(const std::string& hrp_in) { hrp = std::move(hrp_in); } - void setKey(Data keyHash_in) { keyHash = std::move(keyHash_in); } + void setKey(const Data& keyHash_in) { keyHash = std::move(keyHash_in); } inline const std::string& getHrp() const { return hrp; } diff --git a/src/Binance/Address.h b/src/Binance/Address.h index 412fac043c0..198540e0962 100644 --- a/src/Binance/Address.h +++ b/src/Binance/Address.h @@ -17,12 +17,12 @@ class Address: public Bech32Address { public: static const std::string hrp; // HRP_BINANCE - static bool isValid(const std::string addr) { return Bech32Address::isValid(addr, hrp); } + static bool isValid(const std::string& addr) { return Bech32Address::isValid(addr, hrp); } Address() : Bech32Address(hrp) {} /// Initializes an address with a key hash. - Address(Data keyHash) : Bech32Address(hrp, keyHash) {} + Address(const Data& keyHash) : Bech32Address(hrp, keyHash) {} /// Initializes an address with a public key. Address(const PublicKey& publicKey) : Bech32Address(hrp, HASHER_SHA2_RIPEMD, publicKey) {} diff --git a/src/BinaryCoding.h b/src/BinaryCoding.h index f5c6ff18067..36cca69a41e 100644 --- a/src/BinaryCoding.h +++ b/src/BinaryCoding.h @@ -12,6 +12,7 @@ #include #include #include +#include namespace TW { diff --git a/src/Bitcoin/Entry.cpp b/src/Bitcoin/Entry.cpp index a64de869007..2d548ee17ec 100644 --- a/src/Bitcoin/Entry.cpp +++ b/src/Bitcoin/Entry.cpp @@ -22,6 +22,7 @@ bool Entry::validateAddress(TWCoinType coin, const string& address, TW::byte p2p case TWCoinTypeMonacoin: case TWCoinTypeQtum: case TWCoinTypeViacoin: + case TWCoinTypeDigitalGold: return SegwitAddress::isValid(address, hrp) || Address::isValid(address, {{p2pkh}, {p2sh}}); @@ -71,6 +72,7 @@ string Entry::deriveAddress(TWCoinType coin, const PublicKey& publicKey, TW::byt case TWCoinTypeQtum: case TWCoinTypeRavencoin: case TWCoinTypeZcoin: + case TWCoinTypeDigitalGold: default: return Address(publicKey, p2pkh).string(); } diff --git a/src/Bitcoin/Entry.h b/src/Bitcoin/Entry.h index 51e0de06ad8..8a9ec707f88 100644 --- a/src/Bitcoin/Entry.h +++ b/src/Bitcoin/Entry.h @@ -27,6 +27,7 @@ class Entry: public CoinEntry { TWCoinTypeRavencoin, TWCoinTypeViacoin, TWCoinTypeZcoin, + TWCoinTypeDigitalGold, }; } virtual bool validateAddress(TWCoinType coin, const std::string& address, TW::byte p2pkh, TW::byte p2sh, const char* hrp) const; diff --git a/src/Bitcoin/Script.cpp b/src/Bitcoin/Script.cpp index bf1ce32aad7..358e030b3e6 100644 --- a/src/Bitcoin/Script.cpp +++ b/src/Bitcoin/Script.cpp @@ -42,6 +42,11 @@ bool Script::isPayToScriptHash() const { bool Script::isPayToWitnessScriptHash() const { // Extra-fast test for pay-to-witness-script-hash + return bytes.size() == 34 && bytes[0] == OP_0 && bytes[1] == 0x20; +} + +bool Script::isPayToWitnessPublicKeyHash() const { + // Extra-fast test for pay-to-witness-public-key-hash return bytes.size() == 22 && bytes[0] == OP_0 && bytes[1] == 0x14; } @@ -55,7 +60,7 @@ bool Script::isWitnessProgram() const { return bytes[1] + 2 == bytes.size(); } -bool Script::matchPayToPubkey(Data& result) const { +bool Script::matchPayToPublicKey(Data& result) const { if (bytes.size() == PublicKey::secp256k1ExtendedSize + 2 && bytes[0] == PublicKey::secp256k1ExtendedSize && bytes.back() == OP_CHECKSIG) { result.clear(); @@ -73,7 +78,7 @@ bool Script::matchPayToPubkey(Data& result) const { return false; } -bool Script::matchPayToPubkeyHash(Data& result) const { +bool Script::matchPayToPublicKeyHash(Data& result) const { if (bytes.size() == 25 && bytes[0] == OP_DUP && bytes[1] == OP_HASH160 && bytes[2] == 20 && bytes[23] == OP_EQUALVERIFY && bytes[24] == OP_CHECKSIG) { result.clear(); @@ -93,30 +98,21 @@ bool Script::matchPayToScriptHash(Data& result) const { } bool Script::matchPayToWitnessPublicKeyHash(Data& result) const { - if (bytes.size() == 22 && bytes[0] == OP_0 && bytes[1] == 0x14) { - result.clear(); - std::copy(std::begin(bytes) + 2, std::end(bytes), std::back_inserter(result)); - return true; + if (!isPayToWitnessPublicKeyHash()) { + return false; } - return false; + result.clear(); + std::copy(std::begin(bytes) + 2, std::end(bytes), std::back_inserter(result)); + return true; } bool Script::matchPayToWitnessScriptHash(Data& result) const { - if (bytes.size() == 34 && bytes[0] == OP_0 && bytes[1] == 0x20) { - result.clear(); - std::copy(std::begin(bytes) + 2, std::end(bytes), std::back_inserter(result)); - return true; - } - return false; -} - -/// Decodes a small integer -static inline int decodeNumber(uint8_t opcode) { - if (opcode == OP_0) { - return 0; + if (!isPayToWitnessScriptHash()) { + return false; } - assert(opcode >= OP_1 && opcode <= OP_16); - return static_cast(opcode) - static_cast(OP_1 - 1); + result.clear(); + std::copy(std::begin(bytes) + 2, std::end(bytes), std::back_inserter(result)); + return true; } bool Script::matchMultisig(std::vector& keys, int& required) const { @@ -185,7 +181,7 @@ bool Script::getScriptOp(size_t& index, uint8_t& opcode, Data& operand) const { if (bytes.size() - index < 1) { return false; } - size = index; + size = bytes[index]; index += 1; } else if (opcode == OP_PUSHDATA2) { if (bytes.size() - index < 2) { @@ -240,11 +236,13 @@ Script Script::buildPayToWitnessProgram(const Data& program) { return script; } -Script Script::buildPayToWitnessPubkeyHash(const Data& hash) { +Script Script::buildPayToWitnessPublicKeyHash(const Data& hash) { + assert(hash.size() == 20); return Script::buildPayToWitnessProgram(hash); } Script Script::buildPayToWitnessScriptHash(const Data& scriptHash) { + assert(scriptHash.size() == 32); return Script::buildPayToWitnessProgram(scriptHash); } diff --git a/src/Bitcoin/Script.h b/src/Bitcoin/Script.h index f6b5de13427..736b547d8de 100644 --- a/src/Bitcoin/Script.h +++ b/src/Bitcoin/Script.h @@ -13,6 +13,7 @@ #include #include +#include namespace TW::Bitcoin { @@ -43,14 +44,17 @@ class Script { /// Determines whether this is a pay-to-witness-script-hash (P2WSH) script. bool isPayToWitnessScriptHash() const; + /// Determines whether this is a pay-to-witness-public-key-hash (P2WPKH) script. + bool isPayToWitnessPublicKeyHash() const; + /// Determines whether this is a witness programm script. bool isWitnessProgram() const; /// Matches the script to a pay-to-public-key (P2PK) script. - bool matchPayToPubkey(Data& publicKey) const; + bool matchPayToPublicKey(Data& publicKey) const; /// Matches the script to a pay-to-public-key-hash (P2PKH). - bool matchPayToPubkeyHash(Data& keyHash) const; + bool matchPayToPublicKeyHash(Data& keyHash) const; /// Matches the script to a pay-to-script-hash (P2SH). bool matchPayToScriptHash(Data& scriptHash) const; @@ -58,7 +62,7 @@ class Script { /// Matches the script to a pay-to-witness-public-key-hash (P2WPKH). bool matchPayToWitnessPublicKeyHash(Data& keyHash) const; - /// Matches the script to a pay-to-witness-script-hash (P2WSH). + /// Matches the script to a pay-to-witness-script-hash (P2WSH). Returns the script hash, a SHA256 of the witness script. bool matchPayToWitnessScriptHash(Data& scriptHash) const; /// Matches the script to a multisig script. @@ -75,7 +79,7 @@ class Script { /// Builds a pay-to-witness-public-key-hash (P2WPKH) script from a public /// key hash. - static Script buildPayToWitnessPubkeyHash(const Data& hash); + static Script buildPayToWitnessPublicKeyHash(const Data& hash); /// Builds a pay-to-witness-script-hash (P2WSH) script from a script hash. static Script buildPayToWitnessScriptHash(const Data& scriptHash); @@ -88,7 +92,7 @@ class Script { void encode(Data& data) const; /// Encodes a small integer - static uint8_t encodeNumber(int n) { + static inline uint8_t encodeNumber(int n) { assert(n >= 0 && n <= 16); if (n == 0) { return OP_0; @@ -96,8 +100,17 @@ class Script { return OP_1 + uint8_t(n - 1); } - private: + /// Decodes a small integer + static inline int decodeNumber(uint8_t opcode) { + if (opcode == OP_0) { + return 0; + } + assert(opcode >= OP_1 && opcode <= OP_16); + return static_cast(opcode) - static_cast(OP_1 - 1); + } + /// Extracts a single opcode at the given index including its operand. + /// Public for testability. /// /// \param index [in/out] index where the operation starts, on return the /// index of the next operation. \param opcode [out] the opcode. \param diff --git a/src/Bitcoin/TransactionSigner.cpp b/src/Bitcoin/TransactionSigner.cpp index 6260242854d..acf191cf11d 100644 --- a/src/Bitcoin/TransactionSigner.cpp +++ b/src/Bitcoin/TransactionSigner.cpp @@ -169,7 +169,7 @@ Result> TransactionSigner::si } results.resize(required + 1); return Result>::success(std::move(results)); - } else if (script.matchPayToPubkey(data)) { + } else if (script.matchPayToPublicKey(data)) { auto keyHash = TW::Hash::ripemd(TW::Hash::sha256(data)); auto key = keyForPublicKeyHash(keyHash); if (key.empty()) { @@ -183,7 +183,7 @@ Result> TransactionSigner::si return Result>::failure("Failed to sign."); } return Result>::success({signature}); - } else if (script.matchPayToPubkeyHash(data)) { + } else if (script.matchPayToPublicKeyHash(data)) { auto key = keyForPublicKeyHash(data); if (key.empty()) { // Error: Missing keyxs diff --git a/src/Cardano/AddressV3.h b/src/Cardano/AddressV3.h index 2c9655041be..960750ccee3 100644 --- a/src/Cardano/AddressV3.h +++ b/src/Cardano/AddressV3.h @@ -86,7 +86,7 @@ class AddressV3 { Data data() const; private: - AddressV3() : legacyAddressV2(nullptr) {} + AddressV3() : legacyAddressV2(nullptr), discrimination(Discrim_Production), kind(Kind_Single) {} }; inline bool operator==(const AddressV3& lhs, const AddressV3& rhs) { diff --git a/src/Cbor.cpp b/src/Cbor.cpp index ae2fccf1ab8..51304779b21 100644 --- a/src/Cbor.cpp +++ b/src/Cbor.cpp @@ -162,8 +162,8 @@ Decode Decode::skipClone(uint32_t offset) const { Decode::TypeDesc Decode::getTypeDesc() const { TypeDesc typeDesc; typeDesc.isIndefiniteValue = false; - typeDesc.majorType = (MajorType)(byte(0) >> 5); - auto minorType = (TW::byte)((uint8_t)byte(0) & 0x1F); + typeDesc.majorType = (MajorType)(getByte(0) >> 5); + auto minorType = (TW::byte)((uint8_t)getByte(0) & 0x1F); if (minorType < 24) { // direct value typeDesc.byteCount = 1; @@ -172,31 +172,31 @@ Decode::TypeDesc Decode::getTypeDesc() const { } if (minorType == 24) { typeDesc.byteCount = 1 + 1; - typeDesc.value = byte(1); + typeDesc.value = getByte(1); return typeDesc; } if (minorType == 25) { typeDesc.byteCount = 1 + 2; - typeDesc.value = (uint16_t)(((uint16_t)byte(1) << 8) + (uint16_t)byte(2)); + typeDesc.value = (uint16_t)(((uint16_t)getByte(1) << 8) + (uint16_t)getByte(2)); return typeDesc; } if (minorType == 26) { typeDesc.byteCount = 1 + 4; - typeDesc.value = (uint32_t)(((uint32_t)byte(1) << 24) + ((uint32_t)byte(2) << 16) + ((uint32_t)byte(3) << 8) + (uint32_t)byte(4)); + typeDesc.value = (uint32_t)(((uint32_t)getByte(1) << 24) + ((uint32_t)getByte(2) << 16) + ((uint32_t)getByte(3) << 8) + (uint32_t)getByte(4)); return typeDesc; } if (minorType == 27) { typeDesc.byteCount = 1 + 8; typeDesc.value = (uint64_t)( - ((uint64_t)byte(1) << 56) + - ((uint64_t)byte(2) << 48) + - ((uint64_t)byte(3) << 40) + - ((uint64_t)byte(4) << 32) + - ((uint64_t)byte(5) << 24) + - ((uint64_t)byte(6) << 16) + - ((uint64_t)byte(7) << 8) + - ((uint64_t)byte(8))); + ((uint64_t)getByte(1) << 56) + + ((uint64_t)getByte(2) << 48) + + ((uint64_t)getByte(3) << 40) + + ((uint64_t)getByte(4) << 32) + + ((uint64_t)getByte(5) << 24) + + ((uint64_t)getByte(6) << 16) + + ((uint64_t)getByte(7) << 8) + + ((uint64_t)getByte(8))); return typeDesc; } if (minorType >= 28 && minorType <= 30) { diff --git a/src/Cbor.h b/src/Cbor.h index 653bd23bfb9..71de1adb2e0 100644 --- a/src/Cbor.h +++ b/src/Cbor.h @@ -118,7 +118,7 @@ class Decode { /// Skip ahead: form other Decode data with offset Decode skipClone(uint32_t offset) const; /// Get the Nth byte - inline TW::byte byte(uint32_t idx) const { + inline TW::byte getByte(uint32_t idx) const { if (subStart + idx >= data->origData.size()) { throw std::invalid_argument("CBOR data too short"); } return data->origData[subStart + idx]; } diff --git a/src/Coin.cpp b/src/Coin.cpp index c6135ddbec0..9ea55ffbfb9 100644 --- a/src/Coin.cpp +++ b/src/Coin.cpp @@ -51,6 +51,7 @@ #include "Waves/Entry.h" #include "Zcash/Entry.h" #include "Zilliqa/Entry.h" +#include "Elrond/Entry.h" // end_of_coin_includes_marker_do_not_modify using namespace TW; @@ -100,6 +101,7 @@ void setupDispatchers() { new Waves::Entry(), new Zcash::Entry(), new Zilliqa::Entry(), + new Elrond::Entry(), }; // end_of_coin_entries_marker_do_not_modify dispatchMap.clear(); @@ -147,7 +149,7 @@ bool TW::validateAddress(TWCoinType coin, const std::string& string) { return dispatcher->validateAddress(coin, string, p2pkh, p2sh, hrp); } -std::string TW::normalizeAddress(TWCoinType coin, const std::string &address) { +std::string TW::normalizeAddress(TWCoinType coin, const std::string& address) { if (!TW::validateAddress(coin, address)) { // invalid address, not normalizing return ""; diff --git a/src/Cosmos/Address.h b/src/Cosmos/Address.h index 67d91040c07..49bf640d5cb 100644 --- a/src/Cosmos/Address.h +++ b/src/Cosmos/Address.h @@ -20,7 +20,7 @@ class Address: public Bech32Address { Address() : Bech32Address("") {} /// Initializes an address with a key hash. - Address(const std::string& hrp, Data keyHash) : Bech32Address(hrp, keyHash) {} + Address(const std::string& hrp, const Data& keyHash) : Bech32Address(hrp, keyHash) {} /// Initializes an address with a public key. Address(const std::string& hrp, const PublicKey& publicKey) : Bech32Address(hrp, HASHER_SHA2_RIPEMD, publicKey) {} diff --git a/src/Data.h b/src/Data.h index 4e80e18865a..3592ff89196 100644 --- a/src/Data.h +++ b/src/Data.h @@ -28,6 +28,10 @@ inline Data data(const byte* data, size_t size) { return std::vector(data, data + size); } +inline Data data(byte b) { + return std::vector({b}); +} + inline void append(Data& data, const Data& suffix) { data.insert(data.end(), suffix.begin(), suffix.end()); } diff --git a/src/Decred/Signer.cpp b/src/Decred/Signer.cpp index 2a7b99ca0a3..09ddf587313 100644 --- a/src/Decred/Signer.cpp +++ b/src/Decred/Signer.cpp @@ -108,7 +108,7 @@ Result> Signer::signStep(Bitcoin::Script script, size_t index) std::vector keys; int required; - if (script.matchPayToPubkey(data)) { + if (script.matchPayToPublicKey(data)) { auto keyHash = TW::Hash::ripemd(TW::Hash::blake256(data)); auto key = keyForPublicKeyHash(keyHash); if (key.empty()) { @@ -121,7 +121,7 @@ Result> Signer::signStep(Bitcoin::Script script, size_t index) return Result>::failure("Failed to sign."); } return Result>::success({signature}); - } else if (script.matchPayToPubkeyHash(data)) { + } else if (script.matchPayToPublicKeyHash(data)) { auto key = keyForPublicKeyHash(data); if (key.empty()) { // Error: Missing keyxs diff --git a/src/DerivationPath.cpp b/src/DerivationPath.cpp index 269a6a5c06a..e0f97ed8c71 100644 --- a/src/DerivationPath.cpp +++ b/src/DerivationPath.cpp @@ -24,7 +24,7 @@ DerivationPath::DerivationPath(const std::string& string) { while (it != end) { uint32_t value; - if (std::sscanf(it, "%d", &value) != 1) { + if (std::sscanf(it, "%ud", &value) != 1) { throw std::invalid_argument("Invalid component"); } while (it != end && isdigit(*it)) { diff --git a/src/DerivationPath.h b/src/DerivationPath.h index 9a254da1d0e..0955d24cc37 100644 --- a/src/DerivationPath.h +++ b/src/DerivationPath.h @@ -101,8 +101,8 @@ struct DerivationPath { /// Creates a `DerivationPath` by BIP44 components. DerivationPath(TWPurpose purpose, TWCoinType coin, uint32_t account, uint32_t change, - uint32_t address) { - indices = std::vector(5); + uint32_t address) + : indices(std::vector(5)) { setPurpose(purpose); setCoin(coin); setAccount(account); diff --git a/src/EOS/Asset.cpp b/src/EOS/Asset.cpp index 80d7e159665..17d03be7976 100644 --- a/src/EOS/Asset.cpp +++ b/src/EOS/Asset.cpp @@ -12,11 +12,11 @@ using namespace TW::EOS; -static const int64_t precision = 1000; -static const uint8_t maxDecimals = 18; +static const int64_t Precision = 1000; +static const uint8_t MaxDecimals = 18; Asset::Asset(int64_t amount, uint8_t decimals, const std::string& symbol) { - if (decimals > maxDecimals) { + if (decimals > MaxDecimals) { throw std::invalid_argument("Too many decimals!"); } this->symbol |= decimals; @@ -112,7 +112,7 @@ std::string Asset::string() const { int charsWritten = snprintf(buffer, maxBufferSize, "%.*f %s", decimals, - static_cast(amount) / precision, + static_cast(amount) / Precision, getSymbol().c_str()); if (charsWritten < 0 || charsWritten > maxBufferSize) { diff --git a/src/EOS/Transaction.cpp b/src/EOS/Transaction.cpp index 57138378b2d..e7ae58700aa 100644 --- a/src/EOS/Transaction.cpp +++ b/src/EOS/Transaction.cpp @@ -18,7 +18,7 @@ using namespace TW; using namespace TW::EOS; using json = nlohmann::json; -Signature::Signature(Data sig, Type type) : data(sig), type(type) { +Signature::Signature(const Data& sig, Type type) : data(sig), type(type) { if (sig.size() != DataSize) { throw std::invalid_argument("Invalid signature size!"); } diff --git a/src/EOS/Transaction.h b/src/EOS/Transaction.h index d2413e8aee1..5d6660c462a 100644 --- a/src/EOS/Transaction.h +++ b/src/EOS/Transaction.h @@ -25,7 +25,7 @@ class Signature { static const size_t DataSize = 65; static const size_t ChecksumSize = 4; - Signature(Data sig, Type type); + Signature(const Data& sig, Type type); virtual ~Signature() { } void serialize(Data& os) const noexcept; std::string string() const noexcept; @@ -36,7 +36,7 @@ class Extension { uint16_t type; Data buffer; - Extension(uint16_t type, Data buffer) : type(type), buffer(buffer) { } + Extension(uint16_t type, const Data& buffer) : type(type), buffer(buffer) { } virtual ~Extension() { } void serialize(Data& os) const noexcept; nlohmann::json serialize() const noexcept; diff --git a/src/Elrond/Address.cpp b/src/Elrond/Address.cpp new file mode 100644 index 00000000000..1af84ace200 --- /dev/null +++ b/src/Elrond/Address.cpp @@ -0,0 +1,17 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#include + +#include "Address.h" + +using namespace TW::Elrond; + +const std::string Address::hrp = HRP_ELROND; + +bool Address::isValid(const std::string& string) { + return Bech32Address::isValid(string, hrp); +} diff --git a/src/Elrond/Address.h b/src/Elrond/Address.h new file mode 100644 index 00000000000..1f96edc6700 --- /dev/null +++ b/src/Elrond/Address.h @@ -0,0 +1,38 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#pragma once + +#include "../Data.h" +#include "../PublicKey.h" +#include "../Bech32Address.h" + +#include + +namespace TW::Elrond { + +class Address : public Bech32Address { + public: + // The human-readable part of the address, as defined in "coins.json" + static const std::string hrp; // HRP_ELROND + + /// Determines whether a string makes a valid address. + static bool isValid(const std::string& string); + + Address() : Bech32Address(hrp) {} + + /// Initializes an address with a key hash. + Address(Data keyHash) : Bech32Address(hrp, keyHash) {} + + /// Initializes an address with a public key. + Address(const PublicKey& publicKey) : Bech32Address(hrp, publicKey.bytes) {} + + static bool decode(const std::string& addr, Address& obj_out) { + return Bech32Address::decode(addr, obj_out, hrp); + } +}; + +} // namespace TW::Elrond diff --git a/src/Elrond/Entry.cpp b/src/Elrond/Entry.cpp new file mode 100644 index 00000000000..76b806ff128 --- /dev/null +++ b/src/Elrond/Entry.cpp @@ -0,0 +1,31 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#include "Entry.h" + +#include "Address.h" +#include "Signer.h" + +using namespace TW::Elrond; +using namespace std; + +// Note: avoid business logic from here, rather just call into classes like Address, Signer, etc. + +bool Entry::validateAddress(TWCoinType coin, const string& address, TW::byte, TW::byte, const char*) const { + return Address::isValid(address); +} + +string Entry::deriveAddress(TWCoinType coin, const PublicKey& publicKey, TW::byte, const char*) const { + return Address(publicKey).string(); +} + +void Entry::sign(TWCoinType coin, const TW::Data& dataIn, TW::Data& dataOut) const { + signTemplate(dataIn, dataOut); +} + +string Entry::signJSON(TWCoinType coin, const std::string& json, const Data& key) const { + return Signer::signJSON(json, key); +} diff --git a/src/Elrond/Entry.h b/src/Elrond/Entry.h new file mode 100644 index 00000000000..78a5f60a39f --- /dev/null +++ b/src/Elrond/Entry.h @@ -0,0 +1,25 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#pragma once + +#include "../CoinEntry.h" + +namespace TW::Elrond { + +/// Entry point for implementation of Elrond coin. +/// Note: do not put the implementation here (no matter how simple), to avoid having coin-specific includes in this file +class Entry: public CoinEntry { +public: + virtual std::vector coinTypes() const { return {TWCoinTypeElrond}; } + virtual bool validateAddress(TWCoinType coin, const std::string& address, TW::byte p2pkh, TW::byte p2sh, const char* hrp) const; + virtual std::string deriveAddress(TWCoinType coin, const PublicKey& publicKey, TW::byte p2pkh, const char* hrp) const; + virtual void sign(TWCoinType coin, const Data& dataIn, Data& dataOut) const; + virtual bool supportsJSONSigning() const { return true; } + virtual std::string signJSON(TWCoinType coin, const std::string& json, const Data& key) const; +}; + +} // namespace TW::Elrond diff --git a/src/Elrond/Serialization.cpp b/src/Elrond/Serialization.cpp new file mode 100644 index 00000000000..193daf5d210 --- /dev/null +++ b/src/Elrond/Serialization.cpp @@ -0,0 +1,67 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#include "Serialization.h" + +#include "../Elrond/Address.h" +#include "../proto/Elrond.pb.h" +#include "Base64.h" +#include "PrivateKey.h" + +using namespace TW; + +std::map fields_order { + {"nonce", 1}, + {"value", 2}, + {"receiver", 3}, + {"sender", 4}, + {"gasPrice", 5}, + {"gasLimit", 6}, + {"data", 7}, + {"signature", 8} +}; + +struct FieldsSorter { + bool operator() (const string& lhs, const string& rhs) const { + return fields_order[lhs] < fields_order[rhs]; + } +}; + +template +using sorted_map = std::map; +using sorted_json = nlohmann::basic_json; + +string Elrond::serializeTransaction(const Proto::TransactionMessage& message) { + sorted_json payload { + {"nonce", json(message.nonce())}, + {"value", json(message.value())}, + {"receiver", json(message.receiver())}, + {"sender", json(message.sender())}, + {"gasPrice", json(message.gas_price())}, + {"gasLimit", json(message.gas_limit())}, + }; + + if (!message.data().empty()) { + payload["data"] = json(TW::Base64::encode(TW::data(message.data()))); + } + + return payload.dump(); +} + +string Elrond::serializeSignedTransaction(const Proto::TransactionMessage& message, string signature) { + sorted_json payload { + {"nonce", json(message.nonce())}, + {"value", json(message.value())}, + {"receiver", json(message.receiver())}, + {"sender", json(message.sender())}, + {"gasPrice", json(message.gas_price())}, + {"gasLimit", json(message.gas_limit())}, + {"data", json(message.data())}, + {"signature", json(signature)}, + }; + + return payload.dump(); +} diff --git a/src/Elrond/Serialization.h b/src/Elrond/Serialization.h new file mode 100644 index 00000000000..e56d8a5bf87 --- /dev/null +++ b/src/Elrond/Serialization.h @@ -0,0 +1,21 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#pragma once + +#include "../proto/Elrond.pb.h" +#include "Data.h" +#include + +using string = std::string; +using json = nlohmann::json; + +namespace TW::Elrond { + +string serializeTransaction(const Proto::TransactionMessage& message); +string serializeSignedTransaction(const Proto::TransactionMessage& message, string encodedSignature); + +} // namespace diff --git a/src/Elrond/Signer.cpp b/src/Elrond/Signer.cpp new file mode 100644 index 00000000000..20519c8b80a --- /dev/null +++ b/src/Elrond/Signer.cpp @@ -0,0 +1,38 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#include "Signer.h" +#include "Address.h" +#include "Serialization.h" +#include "../PublicKey.h" +#include "HexCoding.h" + +#include + +using namespace TW; +using namespace TW::Elrond; + +Proto::SigningOutput Signer::sign(const Proto::SigningInput &input) noexcept { + auto privateKey = PrivateKey(input.private_key()); + auto signableAsString = serializeTransaction(input.transaction()); + auto signableAsData = TW::data(signableAsString); + auto signature = privateKey.sign(signableAsData, TWCurveED25519); + auto encodedSignature = hex(signature); + auto encoded = serializeSignedTransaction(input.transaction(), encodedSignature); + + auto protoOutput = Proto::SigningOutput(); + protoOutput.set_signature(encodedSignature); + protoOutput.set_encoded(encoded); + return protoOutput; +} + +std::string Signer::signJSON(const std::string& json, const Data& key) { + auto input = Proto::SigningInput(); + google::protobuf::util::JsonStringToMessage(json, &input); + input.set_private_key(key.data(), key.size()); + auto output = sign(input); + return output.encoded(); +} diff --git a/src/Elrond/Signer.h b/src/Elrond/Signer.h new file mode 100644 index 00000000000..046f5e52d67 --- /dev/null +++ b/src/Elrond/Signer.h @@ -0,0 +1,28 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#pragma once + +#include "../Data.h" +#include "../PrivateKey.h" +#include "../proto/Elrond.pb.h" + +namespace TW::Elrond { + +/// Helper class that performs Elrond transaction signing. +class Signer { +public: + /// Hide default constructor + Signer() = delete; + + /// Signs a Proto::SigningInput transaction + static Proto::SigningOutput sign(const Proto::SigningInput& input) noexcept; + + /// Signs a json Proto::SigningInput with private key + static std::string signJSON(const std::string& json, const Data& key); +}; + +} // namespace TW::Elrond diff --git a/src/Encrypt.cpp b/src/Encrypt.cpp index 7492fdb8b54..9782fd42c7f 100644 --- a/src/Encrypt.cpp +++ b/src/Encrypt.cpp @@ -8,6 +8,7 @@ #include "Data.h" #include #include +#include namespace TW::Encrypt { diff --git a/src/Ethereum/ABI/Bytes.h b/src/Ethereum/ABI/Bytes.h index c2b85e2e5b1..69eb5aaede8 100644 --- a/src/Ethereum/ABI/Bytes.h +++ b/src/Ethereum/ABI/Bytes.h @@ -64,7 +64,7 @@ class ParamString: public ParamCollection public: ParamString() = default; ParamString(std::string val): ParamCollection() { setVal(val); } - void setVal(std::string& val) { _str = val; } + void setVal(const std::string& val) { _str = val; } const std::string& getVal() const { return _str; } virtual std::string getType() const { return "string"; }; virtual size_t getSize() const { return 32 + ValueEncoder::paddedTo32(_str.size()); } diff --git a/src/Ethereum/ABI/Function.h b/src/Ethereum/ABI/Function.h index cf3585096bd..11d020c8ab7 100644 --- a/src/Ethereum/ABI/Function.h +++ b/src/Ethereum/ABI/Function.h @@ -26,7 +26,7 @@ class Function { ParamSet _outParams; Function(std::string name) : name(std::move(name)) {} - Function(std::string name, std::vector> inParams) + Function(std::string name, const std::vector>& inParams) : name(std::move(name)), _inParams(ParamSet(inParams)) {} virtual ~Function() {} /// Add an input parameter. Returns the index of the parameter. diff --git a/src/Ethereum/Signer.cpp b/src/Ethereum/Signer.cpp index 2dd09f11b15..bbeeb7c8157 100644 --- a/src/Ethereum/Signer.cpp +++ b/src/Ethereum/Signer.cpp @@ -44,7 +44,7 @@ std::string Signer::signJSON(const std::string& json, const Data& key) { } std::tuple Signer::values(const uint256_t &chainID, - const Data &signature) noexcept { + const Data& signature) noexcept { boost::multiprecision::uint256_t r, s, v; import_bits(r, signature.begin(), signature.begin() + 32); import_bits(s, signature.begin() + 32, signature.begin() + 64); @@ -62,7 +62,7 @@ std::tuple Signer::values(const uint256_t &chai } std::tuple -Signer::sign(const uint256_t &chainID, const PrivateKey &privateKey, const Data &hash) noexcept { +Signer::sign(const uint256_t &chainID, const PrivateKey &privateKey, const Data& hash) noexcept { auto signature = privateKey.sign(hash, TWCurveSECP256k1); return values(chainID, signature); } diff --git a/src/Ethereum/Signer.h b/src/Ethereum/Signer.h index 50b279f5f9c..b041b64417f 100644 --- a/src/Ethereum/Signer.h +++ b/src/Ethereum/Signer.h @@ -46,13 +46,13 @@ class Signer { /// /// @returns the r, s, and v values of the transaction signature static std::tuple - sign(const uint256_t &chainID, const PrivateKey &privateKey, const Data &hash) noexcept; + sign(const uint256_t &chainID, const PrivateKey &privateKey, const Data& hash) noexcept; /// R, S, and V values for the given chain identifier and signature. /// /// @returns the r, s, and v values of the transaction signature static std::tuple values(const uint256_t &chainID, - const Data &signature) noexcept; + const Data& signature) noexcept; protected: /// Computes the transaction hash. diff --git a/src/Ethereum/Transaction.h b/src/Ethereum/Transaction.h index e16d5d8f17c..d5af92b3ed8 100644 --- a/src/Ethereum/Transaction.h +++ b/src/Ethereum/Transaction.h @@ -26,7 +26,7 @@ class Transaction { uint256_t r = uint256_t(); uint256_t s = uint256_t(); - Transaction(uint256_t nonce, uint256_t gasPrice, uint256_t gasLimit, Data to, uint256_t amount, + Transaction(uint256_t nonce, uint256_t gasPrice, uint256_t gasLimit, const Data& to, uint256_t amount, Data payload) : nonce(std::move(nonce)) , gasPrice(std::move(gasPrice)) diff --git a/src/FIO/Action.h b/src/FIO/Action.h index b88931a71f6..c79ef65a500 100644 --- a/src/FIO/Action.h +++ b/src/FIO/Action.h @@ -92,7 +92,7 @@ class AddPubAddressData { std::string tpid; std::string actor; - AddPubAddressData(const std::string& fioAddress, std::vector addresses, + AddPubAddressData(const std::string& fioAddress, const std::vector& addresses, uint64_t fee, const std::string& tpid, const std::string& actor) : fioAddress(fioAddress), addresses(addresses), fee(fee), tpid(tpid), actor(actor) {} diff --git a/src/Filecoin/Address.cpp b/src/Filecoin/Address.cpp index f12887c612d..06ddb6799eb 100644 --- a/src/Filecoin/Address.cpp +++ b/src/Filecoin/Address.cpp @@ -9,6 +9,8 @@ #include "../Base32.h" #include "../Data.h" +#include + using namespace TW; using namespace TW::Filecoin; diff --git a/src/Filecoin/Entry.cpp b/src/Filecoin/Entry.cpp index 8980a773fd8..ef98fcbdb87 100644 --- a/src/Filecoin/Entry.cpp +++ b/src/Filecoin/Entry.cpp @@ -25,3 +25,7 @@ string Entry::deriveAddress(TWCoinType coin, const PublicKey& publicKey, TW::byt void Entry::sign(TWCoinType coin, const TW::Data& dataIn, TW::Data& dataOut) const { signTemplate(dataIn, dataOut); } + +string Entry::signJSON(TWCoinType coin, const std::string& json, const Data& key) const { + return Signer::signJSON(json, key); +} diff --git a/src/Filecoin/Entry.h b/src/Filecoin/Entry.h index cb370ba5e3e..8259953005e 100644 --- a/src/Filecoin/Entry.h +++ b/src/Filecoin/Entry.h @@ -18,6 +18,8 @@ class Entry: public CoinEntry { virtual bool validateAddress(TWCoinType coin, const std::string& address, TW::byte p2pkh, TW::byte p2sh, const char* hrp) const; virtual std::string deriveAddress(TWCoinType coin, const PublicKey& publicKey, TW::byte p2pkh, const char* hrp) const; virtual void sign(TWCoinType coin, const Data& dataIn, Data& dataOut) const; + virtual bool supportsJSONSigning() const { return true; } + virtual std::string signJSON(TWCoinType coin, const std::string& json, const Data& key) const; }; } // namespace TW::Filecoin diff --git a/src/Filecoin/Signer.cpp b/src/Filecoin/Signer.cpp index adadc8b9c29..ed5363ba63e 100644 --- a/src/Filecoin/Signer.cpp +++ b/src/Filecoin/Signer.cpp @@ -5,6 +5,8 @@ // file LICENSE at the root of the source code distribution tree. #include "Signer.h" +#include "HexCoding.h" +#include using namespace TW; using namespace TW::Filecoin; @@ -38,3 +40,11 @@ Data Signer::sign(const PrivateKey& privateKey, Transaction& transaction) noexce auto signature = privateKey.sign(toSign, TWCurveSECP256k1); return Data(signature.begin(), signature.end()); } + +std::string Signer::signJSON(const std::string& json, const Data& key) { + auto input = Proto::SigningInput(); + google::protobuf::util::JsonStringToMessage(json, &input); + input.set_private_key(key.data(), key.size()); + auto output = Signer::sign(input); + return hex(output.encoded()); +} diff --git a/src/Filecoin/Signer.h b/src/Filecoin/Signer.h index 4509374f882..3d20617bcb4 100644 --- a/src/Filecoin/Signer.h +++ b/src/Filecoin/Signer.h @@ -23,6 +23,9 @@ class Signer { /// Signs a Proto::SigningInput transaction. static Proto::SigningOutput sign(const Proto::SigningInput& input) noexcept; + /// Signs a json Proto::SigningInput with private key + static std::string signJSON(const std::string& json, const Data& key); + /// Signs the given transaction. static Data sign(const PrivateKey& privateKey, Transaction& transaction) noexcept; }; diff --git a/src/HDWallet.cpp b/src/HDWallet.cpp index 9d13c0af0d6..bd706095d6e 100644 --- a/src/HDWallet.cpp +++ b/src/HDWallet.cpp @@ -18,6 +18,7 @@ #include #include +#include using namespace TW; @@ -139,7 +140,7 @@ std::string HDWallet::getExtendedPublicKey(TWPurpose purpose, TWCoinType coin, T return serialize(&node, fingerprintValue, version, true, base58Hasher(coin)); } -std::optional HDWallet::getPublicKeyFromExtended(const std::string &extended, const DerivationPath& path) { +std::optional HDWallet::getPublicKeyFromExtended(const std::string& extended, const DerivationPath& path) { const auto coin = path.coin(); const auto curve = TW::curve(coin); const auto hasher = TW::base58Hasher(coin); @@ -173,7 +174,7 @@ std::optional HDWallet::getPublicKeyFromExtended(const std::string &e } } -std::optional HDWallet::getPrivateKeyFromExtended(const std::string &extended, const DerivationPath& path) { +std::optional HDWallet::getPrivateKeyFromExtended(const std::string& extended, const DerivationPath& path) { const auto coin = path.coin(); const auto curve = TW::curve(coin); const auto hasher = TW::base58Hasher(coin); diff --git a/src/HDWallet.h b/src/HDWallet.h index fb2dd62e4ee..784dcbd0c34 100644 --- a/src/HDWallet.h +++ b/src/HDWallet.h @@ -83,10 +83,10 @@ class HDWallet { std::string getExtendedPublicKey(TWPurpose purpose, TWCoinType coin, TWHDVersion version) const; /// Computes the public key from an exteded public key representation. - static std::optional getPublicKeyFromExtended(const std::string &extended, const DerivationPath& path); + static std::optional getPublicKeyFromExtended(const std::string& extended, const DerivationPath& path); /// Computes the private key from an exteded private key representation. - static std::optional getPrivateKeyFromExtended(const std::string &extended, const DerivationPath& path); + static std::optional getPrivateKeyFromExtended(const std::string& extended, const DerivationPath& path); public: // Private key type (later could be moved out of HDWallet) diff --git a/src/Harmony/Address.h b/src/Harmony/Address.h index 2c65defc17e..a36d8507ec1 100644 --- a/src/Harmony/Address.h +++ b/src/Harmony/Address.h @@ -18,12 +18,12 @@ class Address: public Bech32Address { static const std::string hrp; // HRP_HARMONY - static bool isValid(const std::string addr) { return Bech32Address::isValid(addr, hrp); } + static bool isValid(const std::string& addr) { return Bech32Address::isValid(addr, hrp); } Address() : Bech32Address(hrp) {} /// Initializes an address with a key hash. - Address(Data keyHash) : Bech32Address(hrp, keyHash) { + Address(const Data& keyHash) : Bech32Address(hrp, keyHash) { if (getKeyHash().size() != Address::size) { throw std::invalid_argument("invalid address data"); } diff --git a/src/Harmony/Signer.cpp b/src/Harmony/Signer.cpp index a75d8110f75..0543facad72 100644 --- a/src/Harmony/Signer.cpp +++ b/src/Harmony/Signer.cpp @@ -13,7 +13,7 @@ using namespace TW; using namespace TW::Harmony; std::tuple Signer::values(const uint256_t &chainID, - const Data &signature) noexcept { + const Data& signature) noexcept { auto r = load(Data(signature.begin(), signature.begin() + 32)); auto s = load(Data(signature.begin() + 32, signature.begin() + 64)); auto v = load(Data(signature.begin() + 64, signature.begin() + 65)); @@ -22,13 +22,13 @@ std::tuple Signer::values(const uint256_t &chai } std::tuple -Signer::sign(const uint256_t &chainID, const PrivateKey &privateKey, const Data &hash) noexcept { +Signer::sign(const uint256_t &chainID, const PrivateKey &privateKey, const Data& hash) noexcept { auto signature = privateKey.sign(hash, TWCurveSECP256k1); return values(chainID, signature); } template -Proto::SigningOutput Signer::prepareOutput(const Data &encoded, const T &transaction) noexcept { +Proto::SigningOutput Signer::prepareOutput(const Data& encoded, const T &transaction) noexcept { auto protoOutput = Proto::SigningOutput(); auto v = store(transaction.v); @@ -322,7 +322,7 @@ Proto::SigningOutput Signer::signCollectRewards(const Proto::SigningInput &input } template -void Signer::sign(const PrivateKey &privateKey, const Data &hash, T &transaction) const noexcept { +void Signer::sign(const PrivateKey &privateKey, const Data& hash, T &transaction) const noexcept { auto tuple = sign(chainID, privateKey, hash); transaction.r = std::get<0>(tuple); transaction.s = std::get<1>(tuple); diff --git a/src/Harmony/Signer.h b/src/Harmony/Signer.h index a7aa10d5cbc..70d048838b9 100644 --- a/src/Harmony/Signer.h +++ b/src/Harmony/Signer.h @@ -52,23 +52,23 @@ class Signer { explicit Signer(uint256_t chainID) : chainID(std::move(chainID)) {} template - static Proto::SigningOutput prepareOutput(const Data &encoded, const T &transaction) noexcept; + static Proto::SigningOutput prepareOutput(const Data& encoded, const T &transaction) noexcept; /// Signs the given transaction. template - void sign(const PrivateKey &privateKey, const Data &hash, T &transaction) const noexcept; + void sign(const PrivateKey &privateKey, const Data& hash, T &transaction) const noexcept; /// Signs a hash with the given private key for the given chain identifier. /// /// @returns the r, s, and v values of the transaction signature static std::tuple - sign(const uint256_t &chainID, const PrivateKey &privateKey, const Data &hash) noexcept; + sign(const uint256_t &chainID, const PrivateKey &privateKey, const Data& hash) noexcept; /// R, S, and V values for the given chain identifier and signature. /// /// @returns the r, s, and v values of the transaction signature static std::tuple values(const uint256_t &chainID, - const Data &signature) noexcept; + const Data& signature) noexcept; std::string txnAsRLPHex(Transaction &transaction) const noexcept; diff --git a/src/Harmony/Transaction.h b/src/Harmony/Transaction.h index c06e4359513..ac43aa253f0 100644 --- a/src/Harmony/Transaction.h +++ b/src/Harmony/Transaction.h @@ -32,7 +32,7 @@ class Transaction { uint256_t s = uint256_t(); Transaction(uint256_t nonce, uint256_t gasPrice, uint256_t gasLimit, uint256_t fromShardID, - uint256_t toShardID, Address to, uint256_t amount, Data payload) + uint256_t toShardID, Address to, uint256_t amount, const Data& payload) : nonce(std::move(nonce)) , gasPrice(std::move(gasPrice)) , gasLimit(std::move(gasLimit)) diff --git a/src/IoTeX/Address.h b/src/IoTeX/Address.h index f34c353e704..a76743a4250 100644 --- a/src/IoTeX/Address.h +++ b/src/IoTeX/Address.h @@ -18,12 +18,12 @@ class Address: public Bech32Address { static const std::string hrp; // HRP_IOTEX - static bool isValid(const std::string addr) { return Bech32Address::isValid(addr, hrp); } + static bool isValid(const std::string& addr) { return Bech32Address::isValid(addr, hrp); } Address() : Bech32Address(hrp) {} /// Initializes an address with a key hash. - Address(Data keyHash) : Bech32Address(hrp, keyHash) { + Address(const Data& keyHash) : Bech32Address(hrp, keyHash) { if (getKeyHash().size() != Address::size) { throw std::invalid_argument("invalid address data"); } diff --git a/src/IoTeX/Protobuf/.gitignore b/src/IoTeX/Protobuf/.gitignore deleted file mode 100644 index 687ffbb426e..00000000000 --- a/src/IoTeX/Protobuf/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.cc -*.h diff --git a/src/IoTeX/Protobuf/action.pb.cc b/src/IoTeX/Protobuf/action.pb.cc new file mode 100644 index 00000000000..09aa0985126 --- /dev/null +++ b/src/IoTeX/Protobuf/action.pb.cc @@ -0,0 +1,1919 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: action.proto + +#include "action.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) +#include +extern PROTOBUF_INTERNAL_EXPORT_action_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_ActionCore_action_2eproto; +extern PROTOBUF_INTERNAL_EXPORT_action_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Execution_action_2eproto; +extern PROTOBUF_INTERNAL_EXPORT_action_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Transfer_action_2eproto; +namespace iotextypes { +class TransferDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _Transfer_default_instance_; +class ExecutionDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _Execution_default_instance_; +class ActionCoreDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; + const ::iotextypes::Transfer* transfer_; + const ::iotextypes::Execution* execution_; +} _ActionCore_default_instance_; +class ActionDefaultTypeInternal { + public: + ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed _instance; +} _Action_default_instance_; +} // namespace iotextypes +static void InitDefaultsscc_info_Action_action_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::iotextypes::_Action_default_instance_; + new (ptr) ::iotextypes::Action(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::iotextypes::Action::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_Action_action_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsscc_info_Action_action_2eproto}, { + &scc_info_ActionCore_action_2eproto.base,}}; + +static void InitDefaultsscc_info_ActionCore_action_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::iotextypes::_ActionCore_default_instance_; + new (ptr) ::iotextypes::ActionCore(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::iotextypes::ActionCore::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_ActionCore_action_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsscc_info_ActionCore_action_2eproto}, { + &scc_info_Transfer_action_2eproto.base, + &scc_info_Execution_action_2eproto.base,}}; + +static void InitDefaultsscc_info_Execution_action_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::iotextypes::_Execution_default_instance_; + new (ptr) ::iotextypes::Execution(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::iotextypes::Execution::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Execution_action_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsscc_info_Execution_action_2eproto}, {}}; + +static void InitDefaultsscc_info_Transfer_action_2eproto() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::iotextypes::_Transfer_default_instance_; + new (ptr) ::iotextypes::Transfer(); + ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); + } + ::iotextypes::Transfer::InitAsDefaultInstance(); +} + +::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Transfer_action_2eproto = + {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsscc_info_Transfer_action_2eproto}, {}}; + +static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_action_2eproto[4]; +static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_action_2eproto = nullptr; +static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_action_2eproto = nullptr; + +const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_action_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::iotextypes::Transfer, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::iotextypes::Transfer, amount_), + PROTOBUF_FIELD_OFFSET(::iotextypes::Transfer, recipient_), + PROTOBUF_FIELD_OFFSET(::iotextypes::Transfer, payload_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::iotextypes::Execution, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::iotextypes::Execution, amount_), + PROTOBUF_FIELD_OFFSET(::iotextypes::Execution, contract_), + PROTOBUF_FIELD_OFFSET(::iotextypes::Execution, data_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::iotextypes::ActionCore, _internal_metadata_), + ~0u, // no _extensions_ + PROTOBUF_FIELD_OFFSET(::iotextypes::ActionCore, _oneof_case_[0]), + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::iotextypes::ActionCore, version_), + PROTOBUF_FIELD_OFFSET(::iotextypes::ActionCore, nonce_), + PROTOBUF_FIELD_OFFSET(::iotextypes::ActionCore, gaslimit_), + PROTOBUF_FIELD_OFFSET(::iotextypes::ActionCore, gasprice_), + offsetof(::iotextypes::ActionCoreDefaultTypeInternal, transfer_), + offsetof(::iotextypes::ActionCoreDefaultTypeInternal, execution_), + PROTOBUF_FIELD_OFFSET(::iotextypes::ActionCore, action_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::iotextypes::Action, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + PROTOBUF_FIELD_OFFSET(::iotextypes::Action, core_), + PROTOBUF_FIELD_OFFSET(::iotextypes::Action, senderpubkey_), + PROTOBUF_FIELD_OFFSET(::iotextypes::Action, signature_), +}; +static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, sizeof(::iotextypes::Transfer)}, + { 8, -1, sizeof(::iotextypes::Execution)}, + { 16, -1, sizeof(::iotextypes::ActionCore)}, + { 28, -1, sizeof(::iotextypes::Action)}, +}; + +static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { + reinterpret_cast(&::iotextypes::_Transfer_default_instance_), + reinterpret_cast(&::iotextypes::_Execution_default_instance_), + reinterpret_cast(&::iotextypes::_ActionCore_default_instance_), + reinterpret_cast(&::iotextypes::_Action_default_instance_), +}; + +const char descriptor_table_protodef_action_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\014action.proto\022\niotextypes\">\n\010Transfer\022\016" + "\n\006amount\030\001 \001(\t\022\021\n\trecipient\030\002 \001(\t\022\017\n\007pay" + "load\030\003 \001(\014\";\n\tExecution\022\016\n\006amount\030\001 \001(\t\022" + "\020\n\010contract\030\002 \001(\t\022\014\n\004data\030\003 \001(\014\"\260\001\n\nActi" + "onCore\022\017\n\007version\030\001 \001(\r\022\r\n\005nonce\030\002 \001(\004\022\020" + "\n\010gasLimit\030\003 \001(\004\022\020\n\010gasPrice\030\004 \001(\t\022(\n\010tr" + "ansfer\030\n \001(\0132\024.iotextypes.TransferH\000\022*\n\t" + "execution\030\014 \001(\0132\025.iotextypes.ExecutionH\000" + "B\010\n\006action\"W\n\006Action\022$\n\004core\030\001 \001(\0132\026.iot" + "extypes.ActionCore\022\024\n\014senderPubKey\030\002 \001(\014" + "\022\021\n\tsignature\030\003 \001(\014b\006proto3" + ; +static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_action_2eproto_deps[1] = { +}; +static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_action_2eproto_sccs[4] = { + &scc_info_Action_action_2eproto.base, + &scc_info_ActionCore_action_2eproto.base, + &scc_info_Execution_action_2eproto.base, + &scc_info_Transfer_action_2eproto.base, +}; +static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_action_2eproto_once; +static bool descriptor_table_action_2eproto_initialized = false; +const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_action_2eproto = { + &descriptor_table_action_2eproto_initialized, descriptor_table_protodef_action_2eproto, "action.proto", 427, + &descriptor_table_action_2eproto_once, descriptor_table_action_2eproto_sccs, descriptor_table_action_2eproto_deps, 4, 0, + schemas, file_default_instances, TableStruct_action_2eproto::offsets, + file_level_metadata_action_2eproto, 4, file_level_enum_descriptors_action_2eproto, file_level_service_descriptors_action_2eproto, +}; + +// Force running AddDescriptors() at dynamic initialization time. +static bool dynamic_init_dummy_action_2eproto = ( ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_action_2eproto), true); +namespace iotextypes { + +// =================================================================== + +void Transfer::InitAsDefaultInstance() { +} +class Transfer::_Internal { + public: +}; + +Transfer::Transfer() + : ::PROTOBUF_NAMESPACE_ID::Message(), _internal_metadata_(nullptr) { + SharedCtor(); + // @@protoc_insertion_point(constructor:iotextypes.Transfer) +} +Transfer::Transfer(const Transfer& from) + : ::PROTOBUF_NAMESPACE_ID::Message(), + _internal_metadata_(nullptr) { + _internal_metadata_.MergeFrom(from._internal_metadata_); + amount_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from.amount().empty()) { + amount_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.amount_); + } + recipient_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from.recipient().empty()) { + recipient_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.recipient_); + } + payload_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from.payload().empty()) { + payload_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.payload_); + } + // @@protoc_insertion_point(copy_constructor:iotextypes.Transfer) +} + +void Transfer::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Transfer_action_2eproto.base); + amount_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + recipient_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + payload_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +Transfer::~Transfer() { + // @@protoc_insertion_point(destructor:iotextypes.Transfer) + SharedDtor(); +} + +void Transfer::SharedDtor() { + amount_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + recipient_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + payload_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void Transfer::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const Transfer& Transfer::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Transfer_action_2eproto.base); + return *internal_default_instance(); +} + + +void Transfer::Clear() { +// @@protoc_insertion_point(message_clear_start:iotextypes.Transfer) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + amount_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + recipient_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + payload_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + _internal_metadata_.Clear(); +} + +#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER +const char* Transfer::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // string amount = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(mutable_amount(), ptr, ctx, "iotextypes.Transfer.amount"); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string recipient = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(mutable_recipient(), ptr, ctx, "iotextypes.Transfer.recipient"); + CHK_(ptr); + } else goto handle_unusual; + continue; + // bytes payload = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(mutable_payload(), ptr, ctx); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, &_internal_metadata_, ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} +#else // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER +bool Transfer::MergePartialFromCodedStream( + ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + // @@protoc_insertion_point(parse_start:iotextypes.Transfer) + for (;;) { + ::std::pair<::PROTOBUF_NAMESPACE_ID::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); + tag = p.first; + if (!p.second) goto handle_unusual; + switch (::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // string amount = 1; + case 1: { + if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (10 & 0xFF)) { + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString( + input, this->mutable_amount())); + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->amount().data(), static_cast(this->amount().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE, + "iotextypes.Transfer.amount")); + } else { + goto handle_unusual; + } + break; + } + + // string recipient = 2; + case 2: { + if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (18 & 0xFF)) { + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString( + input, this->mutable_recipient())); + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->recipient().data(), static_cast(this->recipient().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE, + "iotextypes.Transfer.recipient")); + } else { + goto handle_unusual; + } + break; + } + + // bytes payload = 3; + case 3: { + if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (26 & 0xFF)) { + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadBytes( + input, this->mutable_payload())); + } else { + goto handle_unusual; + } + break; + } + + default: { + handle_unusual: + if (tag == 0) { + goto success; + } + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SkipField( + input, tag, _internal_metadata_.mutable_unknown_fields())); + break; + } + } + } +success: + // @@protoc_insertion_point(parse_success:iotextypes.Transfer) + return true; +failure: + // @@protoc_insertion_point(parse_failure:iotextypes.Transfer) + return false; +#undef DO_ +} +#endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER + +void Transfer::SerializeWithCachedSizes( + ::PROTOBUF_NAMESPACE_ID::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:iotextypes.Transfer) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // string amount = 1; + if (this->amount().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->amount().data(), static_cast(this->amount().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "iotextypes.Transfer.amount"); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteStringMaybeAliased( + 1, this->amount(), output); + } + + // string recipient = 2; + if (this->recipient().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->recipient().data(), static_cast(this->recipient().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "iotextypes.Transfer.recipient"); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteStringMaybeAliased( + 2, this->recipient(), output); + } + + // bytes payload = 3; + if (this->payload().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBytesMaybeAliased( + 3, this->payload(), output); + } + + if (_internal_metadata_.have_unknown_fields()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SerializeUnknownFields( + _internal_metadata_.unknown_fields(), output); + } + // @@protoc_insertion_point(serialize_end:iotextypes.Transfer) +} + +::PROTOBUF_NAMESPACE_ID::uint8* Transfer::InternalSerializeWithCachedSizesToArray( + ::PROTOBUF_NAMESPACE_ID::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:iotextypes.Transfer) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // string amount = 1; + if (this->amount().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->amount().data(), static_cast(this->amount().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "iotextypes.Transfer.amount"); + target = + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteStringToArray( + 1, this->amount(), target); + } + + // string recipient = 2; + if (this->recipient().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->recipient().data(), static_cast(this->recipient().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "iotextypes.Transfer.recipient"); + target = + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteStringToArray( + 2, this->recipient(), target); + } + + // bytes payload = 3; + if (this->payload().size() > 0) { + target = + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBytesToArray( + 3, this->payload(), target); + } + + if (_internal_metadata_.have_unknown_fields()) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields(), target); + } + // @@protoc_insertion_point(serialize_to_array_end:iotextypes.Transfer) + return target; +} + +size_t Transfer::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:iotextypes.Transfer) + size_t total_size = 0; + + if (_internal_metadata_.have_unknown_fields()) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::ComputeUnknownFieldsSize( + _internal_metadata_.unknown_fields()); + } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string amount = 1; + if (this->amount().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->amount()); + } + + // string recipient = 2; + if (this->recipient().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->recipient()); + } + + // bytes payload = 3; + if (this->payload().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize( + this->payload()); + } + + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void Transfer::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:iotextypes.Transfer) + GOOGLE_DCHECK_NE(&from, this); + const Transfer* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:iotextypes.Transfer) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:iotextypes.Transfer) + MergeFrom(*source); + } +} + +void Transfer::MergeFrom(const Transfer& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:iotextypes.Transfer) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.amount().size() > 0) { + + amount_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.amount_); + } + if (from.recipient().size() > 0) { + + recipient_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.recipient_); + } + if (from.payload().size() > 0) { + + payload_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.payload_); + } +} + +void Transfer::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:iotextypes.Transfer) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void Transfer::CopyFrom(const Transfer& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:iotextypes.Transfer) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Transfer::IsInitialized() const { + return true; +} + +void Transfer::InternalSwap(Transfer* other) { + using std::swap; + _internal_metadata_.Swap(&other->_internal_metadata_); + amount_.Swap(&other->amount_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + GetArenaNoVirtual()); + recipient_.Swap(&other->recipient_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + GetArenaNoVirtual()); + payload_.Swap(&other->payload_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + GetArenaNoVirtual()); +} + +::PROTOBUF_NAMESPACE_ID::Metadata Transfer::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void Execution::InitAsDefaultInstance() { +} +class Execution::_Internal { + public: +}; + +Execution::Execution() + : ::PROTOBUF_NAMESPACE_ID::Message(), _internal_metadata_(nullptr) { + SharedCtor(); + // @@protoc_insertion_point(constructor:iotextypes.Execution) +} +Execution::Execution(const Execution& from) + : ::PROTOBUF_NAMESPACE_ID::Message(), + _internal_metadata_(nullptr) { + _internal_metadata_.MergeFrom(from._internal_metadata_); + amount_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from.amount().empty()) { + amount_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.amount_); + } + contract_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from.contract().empty()) { + contract_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.contract_); + } + data_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from.data().empty()) { + data_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.data_); + } + // @@protoc_insertion_point(copy_constructor:iotextypes.Execution) +} + +void Execution::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Execution_action_2eproto.base); + amount_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + contract_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + data_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +Execution::~Execution() { + // @@protoc_insertion_point(destructor:iotextypes.Execution) + SharedDtor(); +} + +void Execution::SharedDtor() { + amount_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + contract_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + data_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void Execution::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const Execution& Execution::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Execution_action_2eproto.base); + return *internal_default_instance(); +} + + +void Execution::Clear() { +// @@protoc_insertion_point(message_clear_start:iotextypes.Execution) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + amount_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + contract_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + data_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + _internal_metadata_.Clear(); +} + +#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER +const char* Execution::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // string amount = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(mutable_amount(), ptr, ctx, "iotextypes.Execution.amount"); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string contract = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(mutable_contract(), ptr, ctx, "iotextypes.Execution.contract"); + CHK_(ptr); + } else goto handle_unusual; + continue; + // bytes data = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(mutable_data(), ptr, ctx); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, &_internal_metadata_, ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} +#else // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER +bool Execution::MergePartialFromCodedStream( + ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + // @@protoc_insertion_point(parse_start:iotextypes.Execution) + for (;;) { + ::std::pair<::PROTOBUF_NAMESPACE_ID::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); + tag = p.first; + if (!p.second) goto handle_unusual; + switch (::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // string amount = 1; + case 1: { + if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (10 & 0xFF)) { + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString( + input, this->mutable_amount())); + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->amount().data(), static_cast(this->amount().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE, + "iotextypes.Execution.amount")); + } else { + goto handle_unusual; + } + break; + } + + // string contract = 2; + case 2: { + if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (18 & 0xFF)) { + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString( + input, this->mutable_contract())); + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->contract().data(), static_cast(this->contract().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE, + "iotextypes.Execution.contract")); + } else { + goto handle_unusual; + } + break; + } + + // bytes data = 3; + case 3: { + if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (26 & 0xFF)) { + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadBytes( + input, this->mutable_data())); + } else { + goto handle_unusual; + } + break; + } + + default: { + handle_unusual: + if (tag == 0) { + goto success; + } + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SkipField( + input, tag, _internal_metadata_.mutable_unknown_fields())); + break; + } + } + } +success: + // @@protoc_insertion_point(parse_success:iotextypes.Execution) + return true; +failure: + // @@protoc_insertion_point(parse_failure:iotextypes.Execution) + return false; +#undef DO_ +} +#endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER + +void Execution::SerializeWithCachedSizes( + ::PROTOBUF_NAMESPACE_ID::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:iotextypes.Execution) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // string amount = 1; + if (this->amount().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->amount().data(), static_cast(this->amount().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "iotextypes.Execution.amount"); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteStringMaybeAliased( + 1, this->amount(), output); + } + + // string contract = 2; + if (this->contract().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->contract().data(), static_cast(this->contract().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "iotextypes.Execution.contract"); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteStringMaybeAliased( + 2, this->contract(), output); + } + + // bytes data = 3; + if (this->data().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBytesMaybeAliased( + 3, this->data(), output); + } + + if (_internal_metadata_.have_unknown_fields()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SerializeUnknownFields( + _internal_metadata_.unknown_fields(), output); + } + // @@protoc_insertion_point(serialize_end:iotextypes.Execution) +} + +::PROTOBUF_NAMESPACE_ID::uint8* Execution::InternalSerializeWithCachedSizesToArray( + ::PROTOBUF_NAMESPACE_ID::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:iotextypes.Execution) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // string amount = 1; + if (this->amount().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->amount().data(), static_cast(this->amount().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "iotextypes.Execution.amount"); + target = + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteStringToArray( + 1, this->amount(), target); + } + + // string contract = 2; + if (this->contract().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->contract().data(), static_cast(this->contract().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "iotextypes.Execution.contract"); + target = + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteStringToArray( + 2, this->contract(), target); + } + + // bytes data = 3; + if (this->data().size() > 0) { + target = + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBytesToArray( + 3, this->data(), target); + } + + if (_internal_metadata_.have_unknown_fields()) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields(), target); + } + // @@protoc_insertion_point(serialize_to_array_end:iotextypes.Execution) + return target; +} + +size_t Execution::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:iotextypes.Execution) + size_t total_size = 0; + + if (_internal_metadata_.have_unknown_fields()) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::ComputeUnknownFieldsSize( + _internal_metadata_.unknown_fields()); + } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string amount = 1; + if (this->amount().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->amount()); + } + + // string contract = 2; + if (this->contract().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->contract()); + } + + // bytes data = 3; + if (this->data().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize( + this->data()); + } + + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void Execution::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:iotextypes.Execution) + GOOGLE_DCHECK_NE(&from, this); + const Execution* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:iotextypes.Execution) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:iotextypes.Execution) + MergeFrom(*source); + } +} + +void Execution::MergeFrom(const Execution& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:iotextypes.Execution) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.amount().size() > 0) { + + amount_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.amount_); + } + if (from.contract().size() > 0) { + + contract_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.contract_); + } + if (from.data().size() > 0) { + + data_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.data_); + } +} + +void Execution::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:iotextypes.Execution) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void Execution::CopyFrom(const Execution& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:iotextypes.Execution) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Execution::IsInitialized() const { + return true; +} + +void Execution::InternalSwap(Execution* other) { + using std::swap; + _internal_metadata_.Swap(&other->_internal_metadata_); + amount_.Swap(&other->amount_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + GetArenaNoVirtual()); + contract_.Swap(&other->contract_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + GetArenaNoVirtual()); + data_.Swap(&other->data_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + GetArenaNoVirtual()); +} + +::PROTOBUF_NAMESPACE_ID::Metadata Execution::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void ActionCore::InitAsDefaultInstance() { + ::iotextypes::_ActionCore_default_instance_.transfer_ = const_cast< ::iotextypes::Transfer*>( + ::iotextypes::Transfer::internal_default_instance()); + ::iotextypes::_ActionCore_default_instance_.execution_ = const_cast< ::iotextypes::Execution*>( + ::iotextypes::Execution::internal_default_instance()); +} +class ActionCore::_Internal { + public: + static const ::iotextypes::Transfer& transfer(const ActionCore* msg); + static const ::iotextypes::Execution& execution(const ActionCore* msg); +}; + +const ::iotextypes::Transfer& +ActionCore::_Internal::transfer(const ActionCore* msg) { + return *msg->action_.transfer_; +} +const ::iotextypes::Execution& +ActionCore::_Internal::execution(const ActionCore* msg) { + return *msg->action_.execution_; +} +void ActionCore::set_allocated_transfer(::iotextypes::Transfer* transfer) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaNoVirtual(); + clear_action(); + if (transfer) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = nullptr; + if (message_arena != submessage_arena) { + transfer = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, transfer, submessage_arena); + } + set_has_transfer(); + action_.transfer_ = transfer; + } + // @@protoc_insertion_point(field_set_allocated:iotextypes.ActionCore.transfer) +} +void ActionCore::set_allocated_execution(::iotextypes::Execution* execution) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaNoVirtual(); + clear_action(); + if (execution) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = nullptr; + if (message_arena != submessage_arena) { + execution = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, execution, submessage_arena); + } + set_has_execution(); + action_.execution_ = execution; + } + // @@protoc_insertion_point(field_set_allocated:iotextypes.ActionCore.execution) +} +ActionCore::ActionCore() + : ::PROTOBUF_NAMESPACE_ID::Message(), _internal_metadata_(nullptr) { + SharedCtor(); + // @@protoc_insertion_point(constructor:iotextypes.ActionCore) +} +ActionCore::ActionCore(const ActionCore& from) + : ::PROTOBUF_NAMESPACE_ID::Message(), + _internal_metadata_(nullptr) { + _internal_metadata_.MergeFrom(from._internal_metadata_); + gasprice_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from.gasprice().empty()) { + gasprice_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.gasprice_); + } + ::memcpy(&nonce_, &from.nonce_, + static_cast(reinterpret_cast(&version_) - + reinterpret_cast(&nonce_)) + sizeof(version_)); + clear_has_action(); + switch (from.action_case()) { + case kTransfer: { + mutable_transfer()->::iotextypes::Transfer::MergeFrom(from.transfer()); + break; + } + case kExecution: { + mutable_execution()->::iotextypes::Execution::MergeFrom(from.execution()); + break; + } + case ACTION_NOT_SET: { + break; + } + } + // @@protoc_insertion_point(copy_constructor:iotextypes.ActionCore) +} + +void ActionCore::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_ActionCore_action_2eproto.base); + gasprice_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + ::memset(&nonce_, 0, static_cast( + reinterpret_cast(&version_) - + reinterpret_cast(&nonce_)) + sizeof(version_)); + clear_has_action(); +} + +ActionCore::~ActionCore() { + // @@protoc_insertion_point(destructor:iotextypes.ActionCore) + SharedDtor(); +} + +void ActionCore::SharedDtor() { + gasprice_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (has_action()) { + clear_action(); + } +} + +void ActionCore::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const ActionCore& ActionCore::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_ActionCore_action_2eproto.base); + return *internal_default_instance(); +} + + +void ActionCore::clear_action() { +// @@protoc_insertion_point(one_of_clear_start:iotextypes.ActionCore) + switch (action_case()) { + case kTransfer: { + delete action_.transfer_; + break; + } + case kExecution: { + delete action_.execution_; + break; + } + case ACTION_NOT_SET: { + break; + } + } + _oneof_case_[0] = ACTION_NOT_SET; +} + + +void ActionCore::Clear() { +// @@protoc_insertion_point(message_clear_start:iotextypes.ActionCore) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + gasprice_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + ::memset(&nonce_, 0, static_cast( + reinterpret_cast(&version_) - + reinterpret_cast(&nonce_)) + sizeof(version_)); + clear_action(); + _internal_metadata_.Clear(); +} + +#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER +const char* ActionCore::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // uint32 version = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) { + version_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // uint64 nonce = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) { + nonce_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // uint64 gasLimit = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 24)) { + gaslimit_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint(&ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // string gasPrice = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParserUTF8(mutable_gasprice(), ptr, ctx, "iotextypes.ActionCore.gasPrice"); + CHK_(ptr); + } else goto handle_unusual; + continue; + // .iotextypes.Transfer transfer = 10; + case 10: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 82)) { + ptr = ctx->ParseMessage(mutable_transfer(), ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // .iotextypes.Execution execution = 12; + case 12: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 98)) { + ptr = ctx->ParseMessage(mutable_execution(), ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, &_internal_metadata_, ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} +#else // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER +bool ActionCore::MergePartialFromCodedStream( + ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + // @@protoc_insertion_point(parse_start:iotextypes.ActionCore) + for (;;) { + ::std::pair<::PROTOBUF_NAMESPACE_ID::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); + tag = p.first; + if (!p.second) goto handle_unusual; + switch (::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // uint32 version = 1; + case 1: { + if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (8 & 0xFF)) { + + DO_((::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadPrimitive< + ::PROTOBUF_NAMESPACE_ID::uint32, ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_UINT32>( + input, &version_))); + } else { + goto handle_unusual; + } + break; + } + + // uint64 nonce = 2; + case 2: { + if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (16 & 0xFF)) { + + DO_((::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadPrimitive< + ::PROTOBUF_NAMESPACE_ID::uint64, ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_UINT64>( + input, &nonce_))); + } else { + goto handle_unusual; + } + break; + } + + // uint64 gasLimit = 3; + case 3: { + if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (24 & 0xFF)) { + + DO_((::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadPrimitive< + ::PROTOBUF_NAMESPACE_ID::uint64, ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_UINT64>( + input, &gaslimit_))); + } else { + goto handle_unusual; + } + break; + } + + // string gasPrice = 4; + case 4: { + if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (34 & 0xFF)) { + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadString( + input, this->mutable_gasprice())); + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->gasprice().data(), static_cast(this->gasprice().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::PARSE, + "iotextypes.ActionCore.gasPrice")); + } else { + goto handle_unusual; + } + break; + } + + // .iotextypes.Transfer transfer = 10; + case 10: { + if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (82 & 0xFF)) { + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadMessage( + input, mutable_transfer())); + } else { + goto handle_unusual; + } + break; + } + + // .iotextypes.Execution execution = 12; + case 12: { + if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (98 & 0xFF)) { + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadMessage( + input, mutable_execution())); + } else { + goto handle_unusual; + } + break; + } + + default: { + handle_unusual: + if (tag == 0) { + goto success; + } + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SkipField( + input, tag, _internal_metadata_.mutable_unknown_fields())); + break; + } + } + } +success: + // @@protoc_insertion_point(parse_success:iotextypes.ActionCore) + return true; +failure: + // @@protoc_insertion_point(parse_failure:iotextypes.ActionCore) + return false; +#undef DO_ +} +#endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER + +void ActionCore::SerializeWithCachedSizes( + ::PROTOBUF_NAMESPACE_ID::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:iotextypes.ActionCore) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // uint32 version = 1; + if (this->version() != 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32(1, this->version(), output); + } + + // uint64 nonce = 2; + if (this->nonce() != 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt64(2, this->nonce(), output); + } + + // uint64 gasLimit = 3; + if (this->gaslimit() != 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt64(3, this->gaslimit(), output); + } + + // string gasPrice = 4; + if (this->gasprice().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->gasprice().data(), static_cast(this->gasprice().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "iotextypes.ActionCore.gasPrice"); + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteStringMaybeAliased( + 4, this->gasprice(), output); + } + + // .iotextypes.Transfer transfer = 10; + if (has_transfer()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteMessageMaybeToArray( + 10, _Internal::transfer(this), output); + } + + // .iotextypes.Execution execution = 12; + if (has_execution()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteMessageMaybeToArray( + 12, _Internal::execution(this), output); + } + + if (_internal_metadata_.have_unknown_fields()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SerializeUnknownFields( + _internal_metadata_.unknown_fields(), output); + } + // @@protoc_insertion_point(serialize_end:iotextypes.ActionCore) +} + +::PROTOBUF_NAMESPACE_ID::uint8* ActionCore::InternalSerializeWithCachedSizesToArray( + ::PROTOBUF_NAMESPACE_ID::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:iotextypes.ActionCore) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // uint32 version = 1; + if (this->version() != 0) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(1, this->version(), target); + } + + // uint64 nonce = 2; + if (this->nonce() != 0) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt64ToArray(2, this->nonce(), target); + } + + // uint64 gasLimit = 3; + if (this->gaslimit() != 0) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt64ToArray(3, this->gaslimit(), target); + } + + // string gasPrice = 4; + if (this->gasprice().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->gasprice().data(), static_cast(this->gasprice().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "iotextypes.ActionCore.gasPrice"); + target = + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteStringToArray( + 4, this->gasprice(), target); + } + + // .iotextypes.Transfer transfer = 10; + if (has_transfer()) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessageToArray( + 10, _Internal::transfer(this), target); + } + + // .iotextypes.Execution execution = 12; + if (has_execution()) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessageToArray( + 12, _Internal::execution(this), target); + } + + if (_internal_metadata_.have_unknown_fields()) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields(), target); + } + // @@protoc_insertion_point(serialize_to_array_end:iotextypes.ActionCore) + return target; +} + +size_t ActionCore::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:iotextypes.ActionCore) + size_t total_size = 0; + + if (_internal_metadata_.have_unknown_fields()) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::ComputeUnknownFieldsSize( + _internal_metadata_.unknown_fields()); + } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string gasPrice = 4; + if (this->gasprice().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->gasprice()); + } + + // uint64 nonce = 2; + if (this->nonce() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt64Size( + this->nonce()); + } + + // uint64 gasLimit = 3; + if (this->gaslimit() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt64Size( + this->gaslimit()); + } + + // uint32 version = 1; + if (this->version() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32Size( + this->version()); + } + + switch (action_case()) { + // .iotextypes.Transfer transfer = 10; + case kTransfer: { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *action_.transfer_); + break; + } + // .iotextypes.Execution execution = 12; + case kExecution: { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *action_.execution_); + break; + } + case ACTION_NOT_SET: { + break; + } + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void ActionCore::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:iotextypes.ActionCore) + GOOGLE_DCHECK_NE(&from, this); + const ActionCore* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:iotextypes.ActionCore) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:iotextypes.ActionCore) + MergeFrom(*source); + } +} + +void ActionCore::MergeFrom(const ActionCore& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:iotextypes.ActionCore) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.gasprice().size() > 0) { + + gasprice_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.gasprice_); + } + if (from.nonce() != 0) { + set_nonce(from.nonce()); + } + if (from.gaslimit() != 0) { + set_gaslimit(from.gaslimit()); + } + if (from.version() != 0) { + set_version(from.version()); + } + switch (from.action_case()) { + case kTransfer: { + mutable_transfer()->::iotextypes::Transfer::MergeFrom(from.transfer()); + break; + } + case kExecution: { + mutable_execution()->::iotextypes::Execution::MergeFrom(from.execution()); + break; + } + case ACTION_NOT_SET: { + break; + } + } +} + +void ActionCore::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:iotextypes.ActionCore) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ActionCore::CopyFrom(const ActionCore& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:iotextypes.ActionCore) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ActionCore::IsInitialized() const { + return true; +} + +void ActionCore::InternalSwap(ActionCore* other) { + using std::swap; + _internal_metadata_.Swap(&other->_internal_metadata_); + gasprice_.Swap(&other->gasprice_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + GetArenaNoVirtual()); + swap(nonce_, other->nonce_); + swap(gaslimit_, other->gaslimit_); + swap(version_, other->version_); + swap(action_, other->action_); + swap(_oneof_case_[0], other->_oneof_case_[0]); +} + +::PROTOBUF_NAMESPACE_ID::Metadata ActionCore::GetMetadata() const { + return GetMetadataStatic(); +} + + +// =================================================================== + +void Action::InitAsDefaultInstance() { + ::iotextypes::_Action_default_instance_._instance.get_mutable()->core_ = const_cast< ::iotextypes::ActionCore*>( + ::iotextypes::ActionCore::internal_default_instance()); +} +class Action::_Internal { + public: + static const ::iotextypes::ActionCore& core(const Action* msg); +}; + +const ::iotextypes::ActionCore& +Action::_Internal::core(const Action* msg) { + return *msg->core_; +} +Action::Action() + : ::PROTOBUF_NAMESPACE_ID::Message(), _internal_metadata_(nullptr) { + SharedCtor(); + // @@protoc_insertion_point(constructor:iotextypes.Action) +} +Action::Action(const Action& from) + : ::PROTOBUF_NAMESPACE_ID::Message(), + _internal_metadata_(nullptr) { + _internal_metadata_.MergeFrom(from._internal_metadata_); + senderpubkey_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from.senderpubkey().empty()) { + senderpubkey_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.senderpubkey_); + } + signature_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (!from.signature().empty()) { + signature_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.signature_); + } + if (from.has_core()) { + core_ = new ::iotextypes::ActionCore(*from.core_); + } else { + core_ = nullptr; + } + // @@protoc_insertion_point(copy_constructor:iotextypes.Action) +} + +void Action::SharedCtor() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Action_action_2eproto.base); + senderpubkey_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + signature_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + core_ = nullptr; +} + +Action::~Action() { + // @@protoc_insertion_point(destructor:iotextypes.Action) + SharedDtor(); +} + +void Action::SharedDtor() { + senderpubkey_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + signature_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (this != internal_default_instance()) delete core_; +} + +void Action::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const Action& Action::default_instance() { + ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Action_action_2eproto.base); + return *internal_default_instance(); +} + + +void Action::Clear() { +// @@protoc_insertion_point(message_clear_start:iotextypes.Action) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + senderpubkey_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + signature_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + if (GetArenaNoVirtual() == nullptr && core_ != nullptr) { + delete core_; + } + core_ = nullptr; + _internal_metadata_.Clear(); +} + +#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER +const char* Action::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + CHK_(ptr); + switch (tag >> 3) { + // .iotextypes.ActionCore core = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) { + ptr = ctx->ParseMessage(mutable_core(), ptr); + CHK_(ptr); + } else goto handle_unusual; + continue; + // bytes senderPubKey = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(mutable_senderpubkey(), ptr, ctx); + CHK_(ptr); + } else goto handle_unusual; + continue; + // bytes signature = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(mutable_signature(), ptr, ctx); + CHK_(ptr); + } else goto handle_unusual; + continue; + default: { + handle_unusual: + if ((tag & 7) == 4 || tag == 0) { + ctx->SetLastTag(tag); + goto success; + } + ptr = UnknownFieldParse(tag, &_internal_metadata_, ptr, ctx); + CHK_(ptr != nullptr); + continue; + } + } // switch + } // while +success: + return ptr; +failure: + ptr = nullptr; + goto success; +#undef CHK_ +} +#else // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER +bool Action::MergePartialFromCodedStream( + ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure + ::PROTOBUF_NAMESPACE_ID::uint32 tag; + // @@protoc_insertion_point(parse_start:iotextypes.Action) + for (;;) { + ::std::pair<::PROTOBUF_NAMESPACE_ID::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); + tag = p.first; + if (!p.second) goto handle_unusual; + switch (::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // .iotextypes.ActionCore core = 1; + case 1: { + if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (10 & 0xFF)) { + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadMessage( + input, mutable_core())); + } else { + goto handle_unusual; + } + break; + } + + // bytes senderPubKey = 2; + case 2: { + if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (18 & 0xFF)) { + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadBytes( + input, this->mutable_senderpubkey())); + } else { + goto handle_unusual; + } + break; + } + + // bytes signature = 3; + case 3: { + if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (26 & 0xFF)) { + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadBytes( + input, this->mutable_signature())); + } else { + goto handle_unusual; + } + break; + } + + default: { + handle_unusual: + if (tag == 0) { + goto success; + } + DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SkipField( + input, tag, _internal_metadata_.mutable_unknown_fields())); + break; + } + } + } +success: + // @@protoc_insertion_point(parse_success:iotextypes.Action) + return true; +failure: + // @@protoc_insertion_point(parse_failure:iotextypes.Action) + return false; +#undef DO_ +} +#endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER + +void Action::SerializeWithCachedSizes( + ::PROTOBUF_NAMESPACE_ID::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:iotextypes.Action) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // .iotextypes.ActionCore core = 1; + if (this->has_core()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, _Internal::core(this), output); + } + + // bytes senderPubKey = 2; + if (this->senderpubkey().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBytesMaybeAliased( + 2, this->senderpubkey(), output); + } + + // bytes signature = 3; + if (this->signature().size() > 0) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBytesMaybeAliased( + 3, this->signature(), output); + } + + if (_internal_metadata_.have_unknown_fields()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SerializeUnknownFields( + _internal_metadata_.unknown_fields(), output); + } + // @@protoc_insertion_point(serialize_end:iotextypes.Action) +} + +::PROTOBUF_NAMESPACE_ID::uint8* Action::InternalSerializeWithCachedSizesToArray( + ::PROTOBUF_NAMESPACE_ID::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:iotextypes.Action) + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // .iotextypes.ActionCore core = 1; + if (this->has_core()) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessageToArray( + 1, _Internal::core(this), target); + } + + // bytes senderPubKey = 2; + if (this->senderpubkey().size() > 0) { + target = + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBytesToArray( + 2, this->senderpubkey(), target); + } + + // bytes signature = 3; + if (this->signature().size() > 0) { + target = + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBytesToArray( + 3, this->signature(), target); + } + + if (_internal_metadata_.have_unknown_fields()) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields(), target); + } + // @@protoc_insertion_point(serialize_to_array_end:iotextypes.Action) + return target; +} + +size_t Action::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:iotextypes.Action) + size_t total_size = 0; + + if (_internal_metadata_.have_unknown_fields()) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::ComputeUnknownFieldsSize( + _internal_metadata_.unknown_fields()); + } + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // bytes senderPubKey = 2; + if (this->senderpubkey().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize( + this->senderpubkey()); + } + + // bytes signature = 3; + if (this->signature().size() > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::BytesSize( + this->signature()); + } + + // .iotextypes.ActionCore core = 1; + if (this->has_core()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *core_); + } + + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void Action::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:iotextypes.Action) + GOOGLE_DCHECK_NE(&from, this); + const Action* source = + ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated( + &from); + if (source == nullptr) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:iotextypes.Action) + ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:iotextypes.Action) + MergeFrom(*source); + } +} + +void Action::MergeFrom(const Action& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:iotextypes.Action) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom(from._internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.senderpubkey().size() > 0) { + + senderpubkey_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.senderpubkey_); + } + if (from.signature().size() > 0) { + + signature_.AssignWithDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), from.signature_); + } + if (from.has_core()) { + mutable_core()->::iotextypes::ActionCore::MergeFrom(from.core()); + } +} + +void Action::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:iotextypes.Action) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void Action::CopyFrom(const Action& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:iotextypes.Action) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Action::IsInitialized() const { + return true; +} + +void Action::InternalSwap(Action* other) { + using std::swap; + _internal_metadata_.Swap(&other->_internal_metadata_); + senderpubkey_.Swap(&other->senderpubkey_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + GetArenaNoVirtual()); + signature_.Swap(&other->signature_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + GetArenaNoVirtual()); + swap(core_, other->core_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata Action::GetMetadata() const { + return GetMetadataStatic(); +} + + +// @@protoc_insertion_point(namespace_scope) +} // namespace iotextypes +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE ::iotextypes::Transfer* Arena::CreateMaybeMessage< ::iotextypes::Transfer >(Arena* arena) { + return Arena::CreateInternal< ::iotextypes::Transfer >(arena); +} +template<> PROTOBUF_NOINLINE ::iotextypes::Execution* Arena::CreateMaybeMessage< ::iotextypes::Execution >(Arena* arena) { + return Arena::CreateInternal< ::iotextypes::Execution >(arena); +} +template<> PROTOBUF_NOINLINE ::iotextypes::ActionCore* Arena::CreateMaybeMessage< ::iotextypes::ActionCore >(Arena* arena) { + return Arena::CreateInternal< ::iotextypes::ActionCore >(arena); +} +template<> PROTOBUF_NOINLINE ::iotextypes::Action* Arena::CreateMaybeMessage< ::iotextypes::Action >(Arena* arena) { + return Arena::CreateInternal< ::iotextypes::Action >(arena); +} +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#include diff --git a/src/IoTeX/Protobuf/action.pb.h b/src/IoTeX/Protobuf/action.pb.h new file mode 100644 index 00000000000..10ddfbe15b9 --- /dev/null +++ b/src/IoTeX/Protobuf/action.pb.h @@ -0,0 +1,1444 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: action.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_action_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_action_2eproto + +#include +#include + +#include +#if PROTOBUF_VERSION < 3009000 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 3009000 < PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // IWYU pragma: export +#include // IWYU pragma: export +#include +// @@protoc_insertion_point(includes) +#include +#define PROTOBUF_INTERNAL_EXPORT_action_2eproto +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct TableStruct_action_2eproto { + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::AuxillaryParseTableField aux[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[4] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; + static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; + static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[]; +}; +extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_action_2eproto; +namespace iotextypes { +class Action; +class ActionDefaultTypeInternal; +extern ActionDefaultTypeInternal _Action_default_instance_; +class ActionCore; +class ActionCoreDefaultTypeInternal; +extern ActionCoreDefaultTypeInternal _ActionCore_default_instance_; +class Execution; +class ExecutionDefaultTypeInternal; +extern ExecutionDefaultTypeInternal _Execution_default_instance_; +class Transfer; +class TransferDefaultTypeInternal; +extern TransferDefaultTypeInternal _Transfer_default_instance_; +} // namespace iotextypes +PROTOBUF_NAMESPACE_OPEN +template<> ::iotextypes::Action* Arena::CreateMaybeMessage<::iotextypes::Action>(Arena*); +template<> ::iotextypes::ActionCore* Arena::CreateMaybeMessage<::iotextypes::ActionCore>(Arena*); +template<> ::iotextypes::Execution* Arena::CreateMaybeMessage<::iotextypes::Execution>(Arena*); +template<> ::iotextypes::Transfer* Arena::CreateMaybeMessage<::iotextypes::Transfer>(Arena*); +PROTOBUF_NAMESPACE_CLOSE +namespace iotextypes { + +// =================================================================== + +class Transfer : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:iotextypes.Transfer) */ { + public: + Transfer(); + virtual ~Transfer(); + + Transfer(const Transfer& from); + Transfer(Transfer&& from) noexcept + : Transfer() { + *this = ::std::move(from); + } + + inline Transfer& operator=(const Transfer& from) { + CopyFrom(from); + return *this; + } + inline Transfer& operator=(Transfer&& from) noexcept { + if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const Transfer& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const Transfer* internal_default_instance() { + return reinterpret_cast( + &_Transfer_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(Transfer& a, Transfer& b) { + a.Swap(&b); + } + inline void Swap(Transfer* other) { + if (other == this) return; + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline Transfer* New() const final { + return CreateMaybeMessage(nullptr); + } + + Transfer* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const Transfer& from); + void MergeFrom(const Transfer& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + #else + bool MergePartialFromCodedStream( + ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) final; + #endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER + void SerializeWithCachedSizes( + ::PROTOBUF_NAMESPACE_ID::io::CodedOutputStream* output) const final; + ::PROTOBUF_NAMESPACE_ID::uint8* InternalSerializeWithCachedSizesToArray( + ::PROTOBUF_NAMESPACE_ID::uint8* target) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Transfer* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "iotextypes.Transfer"; + } + private: + inline ::PROTOBUF_NAMESPACE_ID::Arena* GetArenaNoVirtual() const { + return nullptr; + } + inline void* MaybeArenaPtr() const { + return nullptr; + } + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_action_2eproto); + return ::descriptor_table_action_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kAmountFieldNumber = 1, + kRecipientFieldNumber = 2, + kPayloadFieldNumber = 3, + }; + // string amount = 1; + void clear_amount(); + const std::string& amount() const; + void set_amount(const std::string& value); + void set_amount(std::string&& value); + void set_amount(const char* value); + void set_amount(const char* value, size_t size); + std::string* mutable_amount(); + std::string* release_amount(); + void set_allocated_amount(std::string* amount); + + // string recipient = 2; + void clear_recipient(); + const std::string& recipient() const; + void set_recipient(const std::string& value); + void set_recipient(std::string&& value); + void set_recipient(const char* value); + void set_recipient(const char* value, size_t size); + std::string* mutable_recipient(); + std::string* release_recipient(); + void set_allocated_recipient(std::string* recipient); + + // bytes payload = 3; + void clear_payload(); + const std::string& payload() const; + void set_payload(const std::string& value); + void set_payload(std::string&& value); + void set_payload(const char* value); + void set_payload(const void* value, size_t size); + std::string* mutable_payload(); + std::string* release_payload(); + void set_allocated_payload(std::string* payload); + + // @@protoc_insertion_point(class_scope:iotextypes.Transfer) + private: + class _Internal; + + ::PROTOBUF_NAMESPACE_ID::internal::InternalMetadataWithArena _internal_metadata_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr amount_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr recipient_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr payload_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_action_2eproto; +}; +// ------------------------------------------------------------------- + +class Execution : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:iotextypes.Execution) */ { + public: + Execution(); + virtual ~Execution(); + + Execution(const Execution& from); + Execution(Execution&& from) noexcept + : Execution() { + *this = ::std::move(from); + } + + inline Execution& operator=(const Execution& from) { + CopyFrom(from); + return *this; + } + inline Execution& operator=(Execution&& from) noexcept { + if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const Execution& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const Execution* internal_default_instance() { + return reinterpret_cast( + &_Execution_default_instance_); + } + static constexpr int kIndexInFileMessages = + 1; + + friend void swap(Execution& a, Execution& b) { + a.Swap(&b); + } + inline void Swap(Execution* other) { + if (other == this) return; + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline Execution* New() const final { + return CreateMaybeMessage(nullptr); + } + + Execution* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const Execution& from); + void MergeFrom(const Execution& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + #else + bool MergePartialFromCodedStream( + ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) final; + #endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER + void SerializeWithCachedSizes( + ::PROTOBUF_NAMESPACE_ID::io::CodedOutputStream* output) const final; + ::PROTOBUF_NAMESPACE_ID::uint8* InternalSerializeWithCachedSizesToArray( + ::PROTOBUF_NAMESPACE_ID::uint8* target) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Execution* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "iotextypes.Execution"; + } + private: + inline ::PROTOBUF_NAMESPACE_ID::Arena* GetArenaNoVirtual() const { + return nullptr; + } + inline void* MaybeArenaPtr() const { + return nullptr; + } + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_action_2eproto); + return ::descriptor_table_action_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kAmountFieldNumber = 1, + kContractFieldNumber = 2, + kDataFieldNumber = 3, + }; + // string amount = 1; + void clear_amount(); + const std::string& amount() const; + void set_amount(const std::string& value); + void set_amount(std::string&& value); + void set_amount(const char* value); + void set_amount(const char* value, size_t size); + std::string* mutable_amount(); + std::string* release_amount(); + void set_allocated_amount(std::string* amount); + + // string contract = 2; + void clear_contract(); + const std::string& contract() const; + void set_contract(const std::string& value); + void set_contract(std::string&& value); + void set_contract(const char* value); + void set_contract(const char* value, size_t size); + std::string* mutable_contract(); + std::string* release_contract(); + void set_allocated_contract(std::string* contract); + + // bytes data = 3; + void clear_data(); + const std::string& data() const; + void set_data(const std::string& value); + void set_data(std::string&& value); + void set_data(const char* value); + void set_data(const void* value, size_t size); + std::string* mutable_data(); + std::string* release_data(); + void set_allocated_data(std::string* data); + + // @@protoc_insertion_point(class_scope:iotextypes.Execution) + private: + class _Internal; + + ::PROTOBUF_NAMESPACE_ID::internal::InternalMetadataWithArena _internal_metadata_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr amount_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr contract_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr data_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_action_2eproto; +}; +// ------------------------------------------------------------------- + +class ActionCore : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:iotextypes.ActionCore) */ { + public: + ActionCore(); + virtual ~ActionCore(); + + ActionCore(const ActionCore& from); + ActionCore(ActionCore&& from) noexcept + : ActionCore() { + *this = ::std::move(from); + } + + inline ActionCore& operator=(const ActionCore& from) { + CopyFrom(from); + return *this; + } + inline ActionCore& operator=(ActionCore&& from) noexcept { + if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const ActionCore& default_instance(); + + enum ActionCase { + kTransfer = 10, + kExecution = 12, + ACTION_NOT_SET = 0, + }; + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const ActionCore* internal_default_instance() { + return reinterpret_cast( + &_ActionCore_default_instance_); + } + static constexpr int kIndexInFileMessages = + 2; + + friend void swap(ActionCore& a, ActionCore& b) { + a.Swap(&b); + } + inline void Swap(ActionCore* other) { + if (other == this) return; + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline ActionCore* New() const final { + return CreateMaybeMessage(nullptr); + } + + ActionCore* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const ActionCore& from); + void MergeFrom(const ActionCore& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + #else + bool MergePartialFromCodedStream( + ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) final; + #endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER + void SerializeWithCachedSizes( + ::PROTOBUF_NAMESPACE_ID::io::CodedOutputStream* output) const final; + ::PROTOBUF_NAMESPACE_ID::uint8* InternalSerializeWithCachedSizesToArray( + ::PROTOBUF_NAMESPACE_ID::uint8* target) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(ActionCore* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "iotextypes.ActionCore"; + } + private: + inline ::PROTOBUF_NAMESPACE_ID::Arena* GetArenaNoVirtual() const { + return nullptr; + } + inline void* MaybeArenaPtr() const { + return nullptr; + } + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_action_2eproto); + return ::descriptor_table_action_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kGasPriceFieldNumber = 4, + kNonceFieldNumber = 2, + kGasLimitFieldNumber = 3, + kVersionFieldNumber = 1, + kTransferFieldNumber = 10, + kExecutionFieldNumber = 12, + }; + // string gasPrice = 4; + void clear_gasprice(); + const std::string& gasprice() const; + void set_gasprice(const std::string& value); + void set_gasprice(std::string&& value); + void set_gasprice(const char* value); + void set_gasprice(const char* value, size_t size); + std::string* mutable_gasprice(); + std::string* release_gasprice(); + void set_allocated_gasprice(std::string* gasprice); + + // uint64 nonce = 2; + void clear_nonce(); + ::PROTOBUF_NAMESPACE_ID::uint64 nonce() const; + void set_nonce(::PROTOBUF_NAMESPACE_ID::uint64 value); + + // uint64 gasLimit = 3; + void clear_gaslimit(); + ::PROTOBUF_NAMESPACE_ID::uint64 gaslimit() const; + void set_gaslimit(::PROTOBUF_NAMESPACE_ID::uint64 value); + + // uint32 version = 1; + void clear_version(); + ::PROTOBUF_NAMESPACE_ID::uint32 version() const; + void set_version(::PROTOBUF_NAMESPACE_ID::uint32 value); + + // .iotextypes.Transfer transfer = 10; + bool has_transfer() const; + void clear_transfer(); + const ::iotextypes::Transfer& transfer() const; + ::iotextypes::Transfer* release_transfer(); + ::iotextypes::Transfer* mutable_transfer(); + void set_allocated_transfer(::iotextypes::Transfer* transfer); + + // .iotextypes.Execution execution = 12; + bool has_execution() const; + void clear_execution(); + const ::iotextypes::Execution& execution() const; + ::iotextypes::Execution* release_execution(); + ::iotextypes::Execution* mutable_execution(); + void set_allocated_execution(::iotextypes::Execution* execution); + + void clear_action(); + ActionCase action_case() const; + // @@protoc_insertion_point(class_scope:iotextypes.ActionCore) + private: + class _Internal; + void set_has_transfer(); + void set_has_execution(); + + inline bool has_action() const; + inline void clear_has_action(); + + ::PROTOBUF_NAMESPACE_ID::internal::InternalMetadataWithArena _internal_metadata_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr gasprice_; + ::PROTOBUF_NAMESPACE_ID::uint64 nonce_; + ::PROTOBUF_NAMESPACE_ID::uint64 gaslimit_; + ::PROTOBUF_NAMESPACE_ID::uint32 version_; + union ActionUnion { + ActionUnion() {} + ::iotextypes::Transfer* transfer_; + ::iotextypes::Execution* execution_; + } action_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + ::PROTOBUF_NAMESPACE_ID::uint32 _oneof_case_[1]; + + friend struct ::TableStruct_action_2eproto; +}; +// ------------------------------------------------------------------- + +class Action : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:iotextypes.Action) */ { + public: + Action(); + virtual ~Action(); + + Action(const Action& from); + Action(Action&& from) noexcept + : Action() { + *this = ::std::move(from); + } + + inline Action& operator=(const Action& from) { + CopyFrom(from); + return *this; + } + inline Action& operator=(Action&& from) noexcept { + if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return GetMetadataStatic().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return GetMetadataStatic().reflection; + } + static const Action& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const Action* internal_default_instance() { + return reinterpret_cast( + &_Action_default_instance_); + } + static constexpr int kIndexInFileMessages = + 3; + + friend void swap(Action& a, Action& b) { + a.Swap(&b); + } + inline void Swap(Action* other) { + if (other == this) return; + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + inline Action* New() const final { + return CreateMaybeMessage(nullptr); + } + + Action* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final; + void CopyFrom(const Action& from); + void MergeFrom(const Action& from); + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + #else + bool MergePartialFromCodedStream( + ::PROTOBUF_NAMESPACE_ID::io::CodedInputStream* input) final; + #endif // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER + void SerializeWithCachedSizes( + ::PROTOBUF_NAMESPACE_ID::io::CodedOutputStream* output) const final; + ::PROTOBUF_NAMESPACE_ID::uint8* InternalSerializeWithCachedSizesToArray( + ::PROTOBUF_NAMESPACE_ID::uint8* target) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + inline void SharedCtor(); + inline void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Action* other); + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "iotextypes.Action"; + } + private: + inline ::PROTOBUF_NAMESPACE_ID::Arena* GetArenaNoVirtual() const { + return nullptr; + } + inline void* MaybeArenaPtr() const { + return nullptr; + } + public: + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + private: + static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_action_2eproto); + return ::descriptor_table_action_2eproto.file_level_metadata[kIndexInFileMessages]; + } + + public: + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kSenderPubKeyFieldNumber = 2, + kSignatureFieldNumber = 3, + kCoreFieldNumber = 1, + }; + // bytes senderPubKey = 2; + void clear_senderpubkey(); + const std::string& senderpubkey() const; + void set_senderpubkey(const std::string& value); + void set_senderpubkey(std::string&& value); + void set_senderpubkey(const char* value); + void set_senderpubkey(const void* value, size_t size); + std::string* mutable_senderpubkey(); + std::string* release_senderpubkey(); + void set_allocated_senderpubkey(std::string* senderpubkey); + + // bytes signature = 3; + void clear_signature(); + const std::string& signature() const; + void set_signature(const std::string& value); + void set_signature(std::string&& value); + void set_signature(const char* value); + void set_signature(const void* value, size_t size); + std::string* mutable_signature(); + std::string* release_signature(); + void set_allocated_signature(std::string* signature); + + // .iotextypes.ActionCore core = 1; + bool has_core() const; + void clear_core(); + const ::iotextypes::ActionCore& core() const; + ::iotextypes::ActionCore* release_core(); + ::iotextypes::ActionCore* mutable_core(); + void set_allocated_core(::iotextypes::ActionCore* core); + + // @@protoc_insertion_point(class_scope:iotextypes.Action) + private: + class _Internal; + + ::PROTOBUF_NAMESPACE_ID::internal::InternalMetadataWithArena _internal_metadata_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr senderpubkey_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr signature_; + ::iotextypes::ActionCore* core_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_action_2eproto; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// Transfer + +// string amount = 1; +inline void Transfer::clear_amount() { + amount_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline const std::string& Transfer::amount() const { + // @@protoc_insertion_point(field_get:iotextypes.Transfer.amount) + return amount_.GetNoArena(); +} +inline void Transfer::set_amount(const std::string& value) { + + amount_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:iotextypes.Transfer.amount) +} +inline void Transfer::set_amount(std::string&& value) { + + amount_.SetNoArena( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + // @@protoc_insertion_point(field_set_rvalue:iotextypes.Transfer.amount) +} +inline void Transfer::set_amount(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + amount_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:iotextypes.Transfer.amount) +} +inline void Transfer::set_amount(const char* value, size_t size) { + + amount_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:iotextypes.Transfer.amount) +} +inline std::string* Transfer::mutable_amount() { + + // @@protoc_insertion_point(field_mutable:iotextypes.Transfer.amount) + return amount_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline std::string* Transfer::release_amount() { + // @@protoc_insertion_point(field_release:iotextypes.Transfer.amount) + + return amount_.ReleaseNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline void Transfer::set_allocated_amount(std::string* amount) { + if (amount != nullptr) { + + } else { + + } + amount_.SetAllocatedNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), amount); + // @@protoc_insertion_point(field_set_allocated:iotextypes.Transfer.amount) +} + +// string recipient = 2; +inline void Transfer::clear_recipient() { + recipient_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline const std::string& Transfer::recipient() const { + // @@protoc_insertion_point(field_get:iotextypes.Transfer.recipient) + return recipient_.GetNoArena(); +} +inline void Transfer::set_recipient(const std::string& value) { + + recipient_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:iotextypes.Transfer.recipient) +} +inline void Transfer::set_recipient(std::string&& value) { + + recipient_.SetNoArena( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + // @@protoc_insertion_point(field_set_rvalue:iotextypes.Transfer.recipient) +} +inline void Transfer::set_recipient(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + recipient_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:iotextypes.Transfer.recipient) +} +inline void Transfer::set_recipient(const char* value, size_t size) { + + recipient_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:iotextypes.Transfer.recipient) +} +inline std::string* Transfer::mutable_recipient() { + + // @@protoc_insertion_point(field_mutable:iotextypes.Transfer.recipient) + return recipient_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline std::string* Transfer::release_recipient() { + // @@protoc_insertion_point(field_release:iotextypes.Transfer.recipient) + + return recipient_.ReleaseNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline void Transfer::set_allocated_recipient(std::string* recipient) { + if (recipient != nullptr) { + + } else { + + } + recipient_.SetAllocatedNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), recipient); + // @@protoc_insertion_point(field_set_allocated:iotextypes.Transfer.recipient) +} + +// bytes payload = 3; +inline void Transfer::clear_payload() { + payload_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline const std::string& Transfer::payload() const { + // @@protoc_insertion_point(field_get:iotextypes.Transfer.payload) + return payload_.GetNoArena(); +} +inline void Transfer::set_payload(const std::string& value) { + + payload_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:iotextypes.Transfer.payload) +} +inline void Transfer::set_payload(std::string&& value) { + + payload_.SetNoArena( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + // @@protoc_insertion_point(field_set_rvalue:iotextypes.Transfer.payload) +} +inline void Transfer::set_payload(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + payload_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:iotextypes.Transfer.payload) +} +inline void Transfer::set_payload(const void* value, size_t size) { + + payload_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:iotextypes.Transfer.payload) +} +inline std::string* Transfer::mutable_payload() { + + // @@protoc_insertion_point(field_mutable:iotextypes.Transfer.payload) + return payload_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline std::string* Transfer::release_payload() { + // @@protoc_insertion_point(field_release:iotextypes.Transfer.payload) + + return payload_.ReleaseNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline void Transfer::set_allocated_payload(std::string* payload) { + if (payload != nullptr) { + + } else { + + } + payload_.SetAllocatedNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), payload); + // @@protoc_insertion_point(field_set_allocated:iotextypes.Transfer.payload) +} + +// ------------------------------------------------------------------- + +// Execution + +// string amount = 1; +inline void Execution::clear_amount() { + amount_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline const std::string& Execution::amount() const { + // @@protoc_insertion_point(field_get:iotextypes.Execution.amount) + return amount_.GetNoArena(); +} +inline void Execution::set_amount(const std::string& value) { + + amount_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:iotextypes.Execution.amount) +} +inline void Execution::set_amount(std::string&& value) { + + amount_.SetNoArena( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + // @@protoc_insertion_point(field_set_rvalue:iotextypes.Execution.amount) +} +inline void Execution::set_amount(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + amount_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:iotextypes.Execution.amount) +} +inline void Execution::set_amount(const char* value, size_t size) { + + amount_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:iotextypes.Execution.amount) +} +inline std::string* Execution::mutable_amount() { + + // @@protoc_insertion_point(field_mutable:iotextypes.Execution.amount) + return amount_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline std::string* Execution::release_amount() { + // @@protoc_insertion_point(field_release:iotextypes.Execution.amount) + + return amount_.ReleaseNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline void Execution::set_allocated_amount(std::string* amount) { + if (amount != nullptr) { + + } else { + + } + amount_.SetAllocatedNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), amount); + // @@protoc_insertion_point(field_set_allocated:iotextypes.Execution.amount) +} + +// string contract = 2; +inline void Execution::clear_contract() { + contract_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline const std::string& Execution::contract() const { + // @@protoc_insertion_point(field_get:iotextypes.Execution.contract) + return contract_.GetNoArena(); +} +inline void Execution::set_contract(const std::string& value) { + + contract_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:iotextypes.Execution.contract) +} +inline void Execution::set_contract(std::string&& value) { + + contract_.SetNoArena( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + // @@protoc_insertion_point(field_set_rvalue:iotextypes.Execution.contract) +} +inline void Execution::set_contract(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + contract_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:iotextypes.Execution.contract) +} +inline void Execution::set_contract(const char* value, size_t size) { + + contract_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:iotextypes.Execution.contract) +} +inline std::string* Execution::mutable_contract() { + + // @@protoc_insertion_point(field_mutable:iotextypes.Execution.contract) + return contract_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline std::string* Execution::release_contract() { + // @@protoc_insertion_point(field_release:iotextypes.Execution.contract) + + return contract_.ReleaseNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline void Execution::set_allocated_contract(std::string* contract) { + if (contract != nullptr) { + + } else { + + } + contract_.SetAllocatedNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), contract); + // @@protoc_insertion_point(field_set_allocated:iotextypes.Execution.contract) +} + +// bytes data = 3; +inline void Execution::clear_data() { + data_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline const std::string& Execution::data() const { + // @@protoc_insertion_point(field_get:iotextypes.Execution.data) + return data_.GetNoArena(); +} +inline void Execution::set_data(const std::string& value) { + + data_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:iotextypes.Execution.data) +} +inline void Execution::set_data(std::string&& value) { + + data_.SetNoArena( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + // @@protoc_insertion_point(field_set_rvalue:iotextypes.Execution.data) +} +inline void Execution::set_data(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + data_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:iotextypes.Execution.data) +} +inline void Execution::set_data(const void* value, size_t size) { + + data_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:iotextypes.Execution.data) +} +inline std::string* Execution::mutable_data() { + + // @@protoc_insertion_point(field_mutable:iotextypes.Execution.data) + return data_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline std::string* Execution::release_data() { + // @@protoc_insertion_point(field_release:iotextypes.Execution.data) + + return data_.ReleaseNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline void Execution::set_allocated_data(std::string* data) { + if (data != nullptr) { + + } else { + + } + data_.SetAllocatedNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), data); + // @@protoc_insertion_point(field_set_allocated:iotextypes.Execution.data) +} + +// ------------------------------------------------------------------- + +// ActionCore + +// uint32 version = 1; +inline void ActionCore::clear_version() { + version_ = 0u; +} +inline ::PROTOBUF_NAMESPACE_ID::uint32 ActionCore::version() const { + // @@protoc_insertion_point(field_get:iotextypes.ActionCore.version) + return version_; +} +inline void ActionCore::set_version(::PROTOBUF_NAMESPACE_ID::uint32 value) { + + version_ = value; + // @@protoc_insertion_point(field_set:iotextypes.ActionCore.version) +} + +// uint64 nonce = 2; +inline void ActionCore::clear_nonce() { + nonce_ = PROTOBUF_ULONGLONG(0); +} +inline ::PROTOBUF_NAMESPACE_ID::uint64 ActionCore::nonce() const { + // @@protoc_insertion_point(field_get:iotextypes.ActionCore.nonce) + return nonce_; +} +inline void ActionCore::set_nonce(::PROTOBUF_NAMESPACE_ID::uint64 value) { + + nonce_ = value; + // @@protoc_insertion_point(field_set:iotextypes.ActionCore.nonce) +} + +// uint64 gasLimit = 3; +inline void ActionCore::clear_gaslimit() { + gaslimit_ = PROTOBUF_ULONGLONG(0); +} +inline ::PROTOBUF_NAMESPACE_ID::uint64 ActionCore::gaslimit() const { + // @@protoc_insertion_point(field_get:iotextypes.ActionCore.gasLimit) + return gaslimit_; +} +inline void ActionCore::set_gaslimit(::PROTOBUF_NAMESPACE_ID::uint64 value) { + + gaslimit_ = value; + // @@protoc_insertion_point(field_set:iotextypes.ActionCore.gasLimit) +} + +// string gasPrice = 4; +inline void ActionCore::clear_gasprice() { + gasprice_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline const std::string& ActionCore::gasprice() const { + // @@protoc_insertion_point(field_get:iotextypes.ActionCore.gasPrice) + return gasprice_.GetNoArena(); +} +inline void ActionCore::set_gasprice(const std::string& value) { + + gasprice_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:iotextypes.ActionCore.gasPrice) +} +inline void ActionCore::set_gasprice(std::string&& value) { + + gasprice_.SetNoArena( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + // @@protoc_insertion_point(field_set_rvalue:iotextypes.ActionCore.gasPrice) +} +inline void ActionCore::set_gasprice(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + gasprice_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:iotextypes.ActionCore.gasPrice) +} +inline void ActionCore::set_gasprice(const char* value, size_t size) { + + gasprice_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:iotextypes.ActionCore.gasPrice) +} +inline std::string* ActionCore::mutable_gasprice() { + + // @@protoc_insertion_point(field_mutable:iotextypes.ActionCore.gasPrice) + return gasprice_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline std::string* ActionCore::release_gasprice() { + // @@protoc_insertion_point(field_release:iotextypes.ActionCore.gasPrice) + + return gasprice_.ReleaseNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline void ActionCore::set_allocated_gasprice(std::string* gasprice) { + if (gasprice != nullptr) { + + } else { + + } + gasprice_.SetAllocatedNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), gasprice); + // @@protoc_insertion_point(field_set_allocated:iotextypes.ActionCore.gasPrice) +} + +// .iotextypes.Transfer transfer = 10; +inline bool ActionCore::has_transfer() const { + return action_case() == kTransfer; +} +inline void ActionCore::set_has_transfer() { + _oneof_case_[0] = kTransfer; +} +inline void ActionCore::clear_transfer() { + if (has_transfer()) { + delete action_.transfer_; + clear_has_action(); + } +} +inline ::iotextypes::Transfer* ActionCore::release_transfer() { + // @@protoc_insertion_point(field_release:iotextypes.ActionCore.transfer) + if (has_transfer()) { + clear_has_action(); + ::iotextypes::Transfer* temp = action_.transfer_; + action_.transfer_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::iotextypes::Transfer& ActionCore::transfer() const { + // @@protoc_insertion_point(field_get:iotextypes.ActionCore.transfer) + return has_transfer() + ? *action_.transfer_ + : *reinterpret_cast< ::iotextypes::Transfer*>(&::iotextypes::_Transfer_default_instance_); +} +inline ::iotextypes::Transfer* ActionCore::mutable_transfer() { + if (!has_transfer()) { + clear_action(); + set_has_transfer(); + action_.transfer_ = CreateMaybeMessage< ::iotextypes::Transfer >( + GetArenaNoVirtual()); + } + // @@protoc_insertion_point(field_mutable:iotextypes.ActionCore.transfer) + return action_.transfer_; +} + +// .iotextypes.Execution execution = 12; +inline bool ActionCore::has_execution() const { + return action_case() == kExecution; +} +inline void ActionCore::set_has_execution() { + _oneof_case_[0] = kExecution; +} +inline void ActionCore::clear_execution() { + if (has_execution()) { + delete action_.execution_; + clear_has_action(); + } +} +inline ::iotextypes::Execution* ActionCore::release_execution() { + // @@protoc_insertion_point(field_release:iotextypes.ActionCore.execution) + if (has_execution()) { + clear_has_action(); + ::iotextypes::Execution* temp = action_.execution_; + action_.execution_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::iotextypes::Execution& ActionCore::execution() const { + // @@protoc_insertion_point(field_get:iotextypes.ActionCore.execution) + return has_execution() + ? *action_.execution_ + : *reinterpret_cast< ::iotextypes::Execution*>(&::iotextypes::_Execution_default_instance_); +} +inline ::iotextypes::Execution* ActionCore::mutable_execution() { + if (!has_execution()) { + clear_action(); + set_has_execution(); + action_.execution_ = CreateMaybeMessage< ::iotextypes::Execution >( + GetArenaNoVirtual()); + } + // @@protoc_insertion_point(field_mutable:iotextypes.ActionCore.execution) + return action_.execution_; +} + +inline bool ActionCore::has_action() const { + return action_case() != ACTION_NOT_SET; +} +inline void ActionCore::clear_has_action() { + _oneof_case_[0] = ACTION_NOT_SET; +} +inline ActionCore::ActionCase ActionCore::action_case() const { + return ActionCore::ActionCase(_oneof_case_[0]); +} +// ------------------------------------------------------------------- + +// Action + +// .iotextypes.ActionCore core = 1; +inline bool Action::has_core() const { + return this != internal_default_instance() && core_ != nullptr; +} +inline void Action::clear_core() { + if (GetArenaNoVirtual() == nullptr && core_ != nullptr) { + delete core_; + } + core_ = nullptr; +} +inline const ::iotextypes::ActionCore& Action::core() const { + const ::iotextypes::ActionCore* p = core_; + // @@protoc_insertion_point(field_get:iotextypes.Action.core) + return p != nullptr ? *p : *reinterpret_cast( + &::iotextypes::_ActionCore_default_instance_); +} +inline ::iotextypes::ActionCore* Action::release_core() { + // @@protoc_insertion_point(field_release:iotextypes.Action.core) + + ::iotextypes::ActionCore* temp = core_; + core_ = nullptr; + return temp; +} +inline ::iotextypes::ActionCore* Action::mutable_core() { + + if (core_ == nullptr) { + auto* p = CreateMaybeMessage<::iotextypes::ActionCore>(GetArenaNoVirtual()); + core_ = p; + } + // @@protoc_insertion_point(field_mutable:iotextypes.Action.core) + return core_; +} +inline void Action::set_allocated_core(::iotextypes::ActionCore* core) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaNoVirtual(); + if (message_arena == nullptr) { + delete core_; + } + if (core) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = nullptr; + if (message_arena != submessage_arena) { + core = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, core, submessage_arena); + } + + } else { + + } + core_ = core; + // @@protoc_insertion_point(field_set_allocated:iotextypes.Action.core) +} + +// bytes senderPubKey = 2; +inline void Action::clear_senderpubkey() { + senderpubkey_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline const std::string& Action::senderpubkey() const { + // @@protoc_insertion_point(field_get:iotextypes.Action.senderPubKey) + return senderpubkey_.GetNoArena(); +} +inline void Action::set_senderpubkey(const std::string& value) { + + senderpubkey_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:iotextypes.Action.senderPubKey) +} +inline void Action::set_senderpubkey(std::string&& value) { + + senderpubkey_.SetNoArena( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + // @@protoc_insertion_point(field_set_rvalue:iotextypes.Action.senderPubKey) +} +inline void Action::set_senderpubkey(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + senderpubkey_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:iotextypes.Action.senderPubKey) +} +inline void Action::set_senderpubkey(const void* value, size_t size) { + + senderpubkey_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:iotextypes.Action.senderPubKey) +} +inline std::string* Action::mutable_senderpubkey() { + + // @@protoc_insertion_point(field_mutable:iotextypes.Action.senderPubKey) + return senderpubkey_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline std::string* Action::release_senderpubkey() { + // @@protoc_insertion_point(field_release:iotextypes.Action.senderPubKey) + + return senderpubkey_.ReleaseNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline void Action::set_allocated_senderpubkey(std::string* senderpubkey) { + if (senderpubkey != nullptr) { + + } else { + + } + senderpubkey_.SetAllocatedNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), senderpubkey); + // @@protoc_insertion_point(field_set_allocated:iotextypes.Action.senderPubKey) +} + +// bytes signature = 3; +inline void Action::clear_signature() { + signature_.ClearToEmptyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline const std::string& Action::signature() const { + // @@protoc_insertion_point(field_get:iotextypes.Action.signature) + return signature_.GetNoArena(); +} +inline void Action::set_signature(const std::string& value) { + + signature_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:iotextypes.Action.signature) +} +inline void Action::set_signature(std::string&& value) { + + signature_.SetNoArena( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + // @@protoc_insertion_point(field_set_rvalue:iotextypes.Action.signature) +} +inline void Action::set_signature(const char* value) { + GOOGLE_DCHECK(value != nullptr); + + signature_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:iotextypes.Action.signature) +} +inline void Action::set_signature(const void* value, size_t size) { + + signature_.SetNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:iotextypes.Action.signature) +} +inline std::string* Action::mutable_signature() { + + // @@protoc_insertion_point(field_mutable:iotextypes.Action.signature) + return signature_.MutableNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline std::string* Action::release_signature() { + // @@protoc_insertion_point(field_release:iotextypes.Action.signature) + + return signature_.ReleaseNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} +inline void Action::set_allocated_signature(std::string* signature) { + if (signature != nullptr) { + + } else { + + } + signature_.SetAllocatedNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), signature); + // @@protoc_insertion_point(field_set_allocated:iotextypes.Action.signature) +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace iotextypes + +// @@protoc_insertion_point(global_scope) + +#include +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_action_2eproto diff --git a/src/IoTeX/Protobuf/action.proto b/src/IoTeX/Protobuf/action.proto deleted file mode 100644 index 921d8c38807..00000000000 --- a/src/IoTeX/Protobuf/action.proto +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) 2018 IoTeX -// This is an alpha (internal) release and is not suitable for production. This -// source code is provided 'as is' and no warranties are given as to title or -// non-infringement, merchantability or fitness for purpose and, to the extent -// permitted by law, all liability for your use of the code is disclaimed. This -// source code is governed by Apache License 2.0 that can be found in the -// LICENSE file. - -syntax = "proto3"; -package iotextypes; - -message Transfer { - // used by state-based model - string amount = 1; - string recipient = 2; - bytes payload = 3; -} - -message Execution { - string amount = 1; - string contract = 2; - bytes data = 3; -} - -message ActionCore { - uint32 version = 1; - uint64 nonce = 2; - uint64 gasLimit = 3; - string gasPrice = 4; - oneof action { - Transfer transfer = 10; - Execution execution = 12; - } -} - -message Action { - ActionCore core = 1; - bytes senderPubKey = 2; - bytes signature = 3; -} diff --git a/src/IoTeX/Signer.cpp b/src/IoTeX/Signer.cpp index e7fb547d025..6b0e6d6ec1a 100644 --- a/src/IoTeX/Signer.cpp +++ b/src/IoTeX/Signer.cpp @@ -24,7 +24,7 @@ Data Signer::sign() const { } Proto::SigningOutput Signer::build() const { - auto signedAction = iotextypes::Action(); + auto signedAction = Proto::Action(); signedAction.mutable_core()->MergeFrom(action); auto key = PrivateKey(input.privatekey()); auto pk = key.getPublicKey(TWPublicKeyTypeSECP256k1Extended).bytes; @@ -32,7 +32,7 @@ Proto::SigningOutput Signer::build() const { auto sig = key.sign(hash(), TWCurveSECP256k1); signedAction.set_signature(sig.data(), sig.size()); - auto output = IoTeX::Proto::SigningOutput(); + auto output = Proto::SigningOutput(); auto serialized = signedAction.SerializeAsString(); output.set_encoded(serialized); auto h = Hash::keccak256(serialized); @@ -44,41 +44,7 @@ Data Signer::hash() const { return Hash::keccak256(action.SerializeAsString()); } -static Data encodeStaking(const Proto::Staking& staking) { - Data encoded; - if (staking.has_stake()) { - auto& stake = staking.stake(); - stakingStake(TW::data(stake.candidate()), stake.duration(), stake.nondecay(), TW::data(stake.data()), encoded); - } else if (staking.has_unstake()) { - auto& unstake = staking.unstake(); - stakingUnstake(unstake.piggy_index(), TW::data(unstake.data()), encoded); - } else if (staking.has_withdraw()) { - auto& withdraw = staking.withdraw(); - stakingWithdraw(withdraw.piggy_index(), TW::data(withdraw.data()), encoded); - } else if (staking.has_movestake()) { - auto& move = staking.movestake(); - stakingMoveStake(move.piggy_index(), TW::data(move.candidate()), TW::data(move.data()), encoded); - } else if (staking.has_addstake()) { - auto& add = staking.addstake(); - stakingAddStake(add.piggy_index(), TW::data(add.data()), encoded); - } - return encoded; -} void Signer::toActionCore() { - if (input.has_staking()) { - action.set_version(input.version()); - action.set_nonce(input.nonce()); - action.set_gaslimit(input.gaslimit()); - action.set_gasprice(input.gasprice()); - auto& staking = input.staking(); - auto encoded = encodeStaking(staking); - auto& execution = *action.mutable_execution(); - execution.set_amount(staking.amount()); - execution.set_contract(staking.contract()); - execution.set_data(encoded.data(), encoded.size()); - } else { - // ActionCore is almost same as SigningInput, missing field privateKey = 5; - action.ParseFromString(input.SerializeAsString()); - action.DiscardUnknownFields(); - } + action.ParseFromString(input.SerializeAsString()); + action.DiscardUnknownFields(); } diff --git a/src/IoTeX/Signer.h b/src/IoTeX/Signer.h index d1e5d8caf33..31fc2c8a15f 100644 --- a/src/IoTeX/Signer.h +++ b/src/IoTeX/Signer.h @@ -9,7 +9,6 @@ #include "Data.h" #include "proto/IoTeX.pb.h" -#include "Protobuf/action.pb.h" namespace TW::IoTeX { @@ -20,7 +19,7 @@ class Signer { static Proto::SigningOutput sign(const Proto::SigningInput& input) noexcept; public: Proto::SigningInput input; - iotextypes::ActionCore action; + Proto::ActionCore action; /// Initializes a transaction signer Signer(const Proto::SigningInput& input) : input(input) { toActionCore(); } diff --git a/src/IoTeX/Staking.cpp b/src/IoTeX/Staking.cpp index 938be61ed9d..493b3a86013 100644 --- a/src/IoTeX/Staking.cpp +++ b/src/IoTeX/Staking.cpp @@ -5,56 +5,106 @@ // file LICENSE at the root of the source code distribution tree. #include "Staking.h" - -#include "Ethereum/ABI/Function.h" #include "Data.h" -#include "uint256.h" +#include "HexCoding.h" +using namespace TW; namespace TW::IoTeX { -using namespace TW::Ethereum::ABI; +const char* FromData(const Data& data) { + auto s = new std::string(data.begin(), data.end()); + s->append(data.size(), '\0'); + auto ss = reinterpret_cast(s); + return ss->data(); +} -void stakingStake(const Data& candidate, uint64_t stakeDuration, bool nonDecay, const Data& dataIn, Data& dataOut) { - Function func("createPygg"); - func.addInParam(std::make_shared(12, candidate)); - func.addInParam(std::make_shared(uint256_t(stakeDuration))); - func.addInParam(std::make_shared(nonDecay)); - func.addInParam(std::make_shared(dataIn)); +Data dataFromString(const std::string& d) { + Data data; + std::copy(d.c_str(), d.c_str() + d.length(), back_inserter(data)); + return data; +} - func.encode(dataOut); +Data stakingCreate(const Data& candidate, const Data& amount, uint32_t duration, bool autoStake, + const Data& payload) { + auto action = IoTeX::Proto::Staking_Create(); + action.set_candidatename(FromData(candidate)); + action.set_stakedamount(FromData(amount)); + action.set_stakedduration(duration); + action.set_autostake(autoStake); + action.set_payload(FromData(payload)); + return dataFromString(action.SerializeAsString()); } -void stakingUnstake(uint64_t pyggIndex, const Data& dataIn, Data& dataOut) { - Function func("unstake"); - func.addInParam(std::make_shared(uint256_t(pyggIndex))); - func.addInParam(std::make_shared(dataIn)); +Data stakingAddDeposit(uint64_t index, const Data& amount, const Data& payload) { + auto action = IoTeX::Proto::Staking_AddDeposit(); + action.set_bucketindex(index); + action.set_amount(FromData(amount)); + action.set_payload(FromData(payload)); + return dataFromString(action.SerializeAsString()); +} - func.encode(dataOut); +Data stakingUnstake(uint64_t index, const Data& payload) { + auto action = IoTeX::Proto::Staking_Reclaim(); + action.set_bucketindex(index); + action.set_payload(FromData(payload)); + return dataFromString(action.SerializeAsString()); } -void stakingWithdraw(uint64_t pyggIndex, const Data& dataIn, Data& dataOut) { - Function func("withdraw"); - func.addInParam(std::make_shared(uint256_t(pyggIndex))); - func.addInParam(std::make_shared(dataIn)); +Data stakingWithdraw(uint64_t index, const Data& payload) { + auto action = IoTeX::Proto::Staking_Reclaim(); + action.set_bucketindex(index); + action.set_payload(FromData(payload)); + return dataFromString(action.SerializeAsString()); +} - func.encode(dataOut); +Data stakingRestake(uint64_t index, uint32_t duration, bool autoStake, const Data& payload) { + auto action = IoTeX::Proto::Staking_Restake(); + action.set_bucketindex(index); + action.set_stakedduration(duration); + action.set_autostake(autoStake); + action.set_payload(FromData(payload)); + return dataFromString(action.SerializeAsString()); } -void stakingAddStake(uint64_t pyggIndex, const Data& dataIn, Data& dataOut) { - Function func("storeToPygg"); - func.addInParam(std::make_shared(uint256_t(pyggIndex))); - func.addInParam(std::make_shared(dataIn)); +Data stakingChangeCandidate(uint64_t index, const Data& candidate, const Data& payload) { + auto action = IoTeX::Proto::Staking_ChangeCandidate(); + action.set_bucketindex(index); + action.set_candidatename(FromData(candidate)); + action.set_payload(FromData(payload)); + return dataFromString(action.SerializeAsString()); +} - func.encode(dataOut); +Data stakingTransfer(uint64_t index, const Data& voterAddress, const Data& payload) { + auto action = IoTeX::Proto::Staking_TransferOwnership(); + action.set_bucketindex(index); + action.set_voteraddress(FromData(voterAddress)); + action.set_payload(FromData(payload)); + return dataFromString(action.SerializeAsString()); } -void stakingMoveStake(uint64_t pyggIndex, const Data& candidate, const Data& dataIn, Data& dataOut) { - Function func("revote"); - func.addInParam(std::make_shared(uint256_t(pyggIndex))); - func.addInParam(std::make_shared(12, candidate)); - func.addInParam(std::make_shared(dataIn)); +Data candidateRegister(const Data& name, const Data& operatorAddress, const Data& rewardAddress, + const Data& amount, uint32_t duration, bool autoStake, + const Data& ownerAddress, const Data& payload) { + auto cbi = new IoTeX::Proto::Staking_CandidateBasicInfo(); + cbi->set_name(FromData(name)); + cbi->set_operatoraddress(FromData(operatorAddress)); + cbi->set_rewardaddress(FromData(rewardAddress)); - func.encode(dataOut); + auto action = IoTeX::Proto::Staking_CandidateRegister(); + action.set_allocated_candidate(cbi); + action.set_stakedamount(FromData(amount)); + action.set_stakedduration(duration); + action.set_autostake(autoStake); + action.set_owneraddress(FromData(ownerAddress)); + action.set_payload(FromData(payload)); + return dataFromString(action.SerializeAsString()); } +Data candidateUpdate(const Data& name, const Data& operatorAddress, const Data& rewardAddress) { + auto action = IoTeX::Proto::Staking_CandidateBasicInfo(); + action.set_name(FromData(name)); + action.set_operatoraddress(FromData(operatorAddress)); + action.set_rewardaddress(FromData(rewardAddress)); + return dataFromString(action.SerializeAsString()); +} } // namespace TW::IoTeX diff --git a/src/IoTeX/Staking.h b/src/IoTeX/Staking.h index 9d5a6846be1..73a5e737473 100644 --- a/src/IoTeX/Staking.h +++ b/src/IoTeX/Staking.h @@ -7,22 +7,37 @@ #pragma once #include "Data.h" - +#include "proto/IoTeX.pb.h" namespace TW::IoTeX { -/// Function to generate Stake message -void stakingStake(const Data& candidate, uint64_t stakeDuration, bool nonDecay, const Data& dataIn, Data& dataOut); +/// Function to generate Create message +Data stakingCreate(const Data& candidate, const Data& amount, uint32_t duration, bool autoStake, + const Data& payload); + +/// Function to generate AddDeposit message +Data stakingAddDeposit(uint64_t index, const Data& amount, const Data& payload); /// Function to generate Unstake message -void stakingUnstake(uint64_t pyggIndex, const Data& dataIn, Data& dataOut); +Data stakingUnstake(uint64_t index, const Data& payload); /// Function to generate Withdraw message -void stakingWithdraw(uint64_t pyggIndex, const Data& dataIn, Data& dataOut); +Data stakingWithdraw(uint64_t index, const Data& payload); + +/// Function to generate Restake message +Data stakingRestake(uint64_t index, uint32_t duration, bool autoStake, const Data& payload); + +/// Function to generate ChangeCandidate message +Data stakingChangeCandidate(uint64_t index, const Data& candidate, const Data& payload); + +/// Function to generate Transfer message +Data stakingTransfer(uint64_t index, const Data& voterAddress, const Data& payload); -/// Function to generate AddStake message -void stakingAddStake(uint64_t pyggIndex, const Data& dataIn, Data& dataOut); +/// Function to generate candidate register message +Data candidateRegister(const Data& name, const Data& operatorAddress, const Data& rewardAddress, + const Data& amount, uint32_t duration, bool autoStake, + const Data& ownerAddress, const Data& payload); -/// Function to generate MoveStake message -void stakingMoveStake(uint64_t pyggIndex, const Data& candidate, const Data& dataIn, Data& dataOut); +/// Function to generate candidate update message +Data candidateUpdate(const Data& name, const Data& operatorAddress, const Data& rewardAddress); } // namespace TW::IoTeX diff --git a/src/Keystore/EncryptionParameters.cpp b/src/Keystore/EncryptionParameters.cpp index 44f4af3f921..279cc76761c 100644 --- a/src/Keystore/EncryptionParameters.cpp +++ b/src/Keystore/EncryptionParameters.cpp @@ -20,7 +20,7 @@ using namespace TW; using namespace TW::Keystore; template -static Data computeMAC(Iter begin, Iter end, Data key) { +static Data computeMAC(Iter begin, Iter end, const Data& key) { auto data = Data(); data.reserve((end - begin) + key.size()); data.insert(data.end(), begin, end); @@ -28,7 +28,7 @@ static Data computeMAC(Iter begin, Iter end, Data key) { return Hash::keccak256(data); } -EncryptionParameters::EncryptionParameters(const std::string& password, Data data) : mac() { +EncryptionParameters::EncryptionParameters(const Data& password, const Data& data) : mac() { auto scryptParams = boost::get(kdfParams); auto derivedKey = Data(scryptParams.desiredKeyLength); scrypt(reinterpret_cast(password.data()), password.size(), scryptParams.salt.data(), @@ -50,21 +50,21 @@ EncryptionParameters::~EncryptionParameters() { std::fill(encrypted.begin(), encrypted.end(), 0); } -Data EncryptionParameters::decrypt(const std::string& password) const { +Data EncryptionParameters::decrypt(const Data& password) const { auto derivedKey = Data(); auto mac = Data(); if (kdfParams.which() == 0) { auto scryptParams = boost::get(kdfParams); derivedKey.resize(scryptParams.defaultDesiredKeyLength); - scrypt(reinterpret_cast(password.data()), password.size(), scryptParams.salt.data(), + scrypt(password.data(), password.size(), scryptParams.salt.data(), scryptParams.salt.size(), scryptParams.n, scryptParams.r, scryptParams.p, derivedKey.data(), scryptParams.defaultDesiredKeyLength); mac = computeMAC(derivedKey.end() - 16, derivedKey.end(), encrypted); } else if (kdfParams.which() == 1) { auto pbkdf2Params = boost::get(kdfParams); derivedKey.resize(pbkdf2Params.defaultDesiredKeyLength); - pbkdf2_hmac_sha256(reinterpret_cast(password.data()), password.size(), pbkdf2Params.salt.data(), + pbkdf2_hmac_sha256(password.data(), password.size(), pbkdf2Params.salt.data(), pbkdf2Params.salt.size(), pbkdf2Params.iterations, derivedKey.data(), pbkdf2Params.defaultDesiredKeyLength); mac = computeMAC(derivedKey.end() - 16, derivedKey.end(), encrypted); diff --git a/src/Keystore/EncryptionParameters.h b/src/Keystore/EncryptionParameters.h index db2e49cc1ba..e1e68933977 100644 --- a/src/Keystore/EncryptionParameters.h +++ b/src/Keystore/EncryptionParameters.h @@ -46,7 +46,7 @@ struct EncryptionParameters { EncryptionParameters() = default; /// Initializes `EncryptionParameters` with standard values. - EncryptionParameters(Data encrypted, AESParameters cipherParams, boost::variant kdfParams, Data mac) + EncryptionParameters(const Data& encrypted, AESParameters cipherParams, boost::variant kdfParams, const Data& mac) : encrypted(std::move(encrypted)) , cipherParams(std::move(cipherParams)) , kdfParams(std::move(kdfParams)) @@ -54,13 +54,13 @@ struct EncryptionParameters { /// Initializes `EncryptionParameters` by encrypting data with a password /// using standard values. - EncryptionParameters(const std::string& password, Data data); + EncryptionParameters(const Data& password, const Data& data); /// Initializes `EncryptionParameters` with a JSON object. EncryptionParameters(const nlohmann::json& json); /// Decrypts the payload with the given password. - Data decrypt(const std::string& password) const; + Data decrypt(const Data& password) const; /// Saves `this` as a JSON object. nlohmann::json json() const; diff --git a/src/Keystore/PBKDF2Parameters.h b/src/Keystore/PBKDF2Parameters.h index b99ab79d786..0d473b5615b 100644 --- a/src/Keystore/PBKDF2Parameters.h +++ b/src/Keystore/PBKDF2Parameters.h @@ -35,7 +35,7 @@ struct PBKDF2Parameters { PBKDF2Parameters(); /// Initializes `PBKDF2Parameters` with all values. - PBKDF2Parameters(Data salt, uint32_t iterations, std::size_t desiredKeyLength) + PBKDF2Parameters(const Data& salt, uint32_t iterations, std::size_t desiredKeyLength) : salt(std::move(salt)), desiredKeyLength(desiredKeyLength), iterations(iterations) {} /// Initializes `PBKDF2Parameters` with a JSON object. diff --git a/src/Keystore/ScryptParameters.h b/src/Keystore/ScryptParameters.h index 460dc4b8e64..10e7c019bd6 100644 --- a/src/Keystore/ScryptParameters.h +++ b/src/Keystore/ScryptParameters.h @@ -66,7 +66,7 @@ struct ScryptParameters { /// Initializes `ScryptParameters` with all values. /// /// @throws ScryptValidationError if the parameters are invalid. - ScryptParameters(Data salt, uint32_t n, uint32_t r, uint32_t p, std::size_t desiredKeyLength) + ScryptParameters(const Data& salt, uint32_t n, uint32_t r, uint32_t p, std::size_t desiredKeyLength) : salt(std::move(salt)), desiredKeyLength(desiredKeyLength), n(n), p(p), r(r) { auto error = validate(); if (error) { diff --git a/src/Keystore/StoredKey.cpp b/src/Keystore/StoredKey.cpp index 476fa336d7e..bba73ee4907 100644 --- a/src/Keystore/StoredKey.cpp +++ b/src/Keystore/StoredKey.cpp @@ -27,7 +27,7 @@ using namespace TW; using namespace TW::Keystore; -StoredKey StoredKey::createWithMnemonic(const std::string& name, const std::string& password, const std::string& mnemonic) { +StoredKey StoredKey::createWithMnemonic(const std::string& name, const Data& password, const std::string& mnemonic) { if (!HDWallet::isValid(mnemonic)) { throw std::invalid_argument("Invalid mnemonic"); } @@ -37,7 +37,7 @@ StoredKey StoredKey::createWithMnemonic(const std::string& name, const std::stri return key; } -StoredKey StoredKey::createWithMnemonicRandom(const std::string& name, const std::string& password) { +StoredKey StoredKey::createWithMnemonicRandom(const std::string& name, const Data& password) { const auto wallet = TW::HDWallet(128, ""); const auto& mnemonic = wallet.mnemonic; assert(HDWallet::isValid(mnemonic)); @@ -46,7 +46,7 @@ StoredKey StoredKey::createWithMnemonicRandom(const std::string& name, const std return key; } -StoredKey StoredKey::createWithMnemonicAddDefaultAddress(const std::string& name, const std::string& password, const std::string& mnemonic, TWCoinType coin) { +StoredKey StoredKey::createWithMnemonicAddDefaultAddress(const std::string& name, const Data& password, const std::string& mnemonic, TWCoinType coin) { StoredKey key = createWithMnemonic(name, password, mnemonic); const auto wallet = HDWallet(mnemonic, ""); @@ -58,12 +58,12 @@ StoredKey StoredKey::createWithMnemonicAddDefaultAddress(const std::string& name return key; } -StoredKey StoredKey::createWithPrivateKey(const std::string& name, const std::string& password, const Data& privateKeyData) { +StoredKey StoredKey::createWithPrivateKey(const std::string& name, const Data& password, const Data& privateKeyData) { StoredKey key = StoredKey(StoredKeyType::privateKey, name, password, privateKeyData); return key; } -StoredKey StoredKey::createWithPrivateKeyAddDefaultAddress(const std::string& name, const std::string& password, TWCoinType coin, const Data& privateKeyData) { +StoredKey StoredKey::createWithPrivateKeyAddDefaultAddress(const std::string& name, const Data& password, TWCoinType coin, const Data& privateKeyData) { const auto curve = TW::curve(coin); if (!PrivateKey::isValid(privateKeyData, curve)) { throw std::invalid_argument("Invalid private key data"); @@ -78,13 +78,13 @@ StoredKey StoredKey::createWithPrivateKeyAddDefaultAddress(const std::string& na return key; } -StoredKey::StoredKey(StoredKeyType type, std::string name, const std::string& password, Data data) +StoredKey::StoredKey(StoredKeyType type, std::string name, const Data& password, const Data& data) : type(type), id(), name(std::move(name)), payload(password, data), accounts() { boost::uuids::random_generator gen; id = boost::lexical_cast(gen()); } -const HDWallet StoredKey::wallet(const std::string& password) const { +const HDWallet StoredKey::wallet(const Data& password) const { if (type != StoredKeyType::mnemonicPhrase) { throw std::invalid_argument("Invalid account requested."); } @@ -139,7 +139,7 @@ void StoredKey::removeAccount(TWCoinType coin) { } -const PrivateKey StoredKey::privateKey(TWCoinType coin, const std::string& password) { +const PrivateKey StoredKey::privateKey(TWCoinType coin, const Data& password) { switch (type) { case StoredKeyType::mnemonicPhrase: { const auto wallet = this->wallet(password); @@ -151,7 +151,7 @@ const PrivateKey StoredKey::privateKey(TWCoinType coin, const std::string& passw } } -void StoredKey::fixAddresses(const std::string& password) { +void StoredKey::fixAddresses(const Data& password) { switch (type) { case StoredKeyType::mnemonicPhrase: { const auto wallet = this->wallet(password); diff --git a/src/Keystore/StoredKey.h b/src/Keystore/StoredKey.h index c742ba5423a..475271e9283 100644 --- a/src/Keystore/StoredKey.h +++ b/src/Keystore/StoredKey.h @@ -43,23 +43,23 @@ class StoredKey { /// Create a new StoredKey, with the given name, mnemonic and password. /// @throws std::invalid_argument if mnemonic is invalid - static StoredKey createWithMnemonic(const std::string& name, const std::string& password, const std::string& mnemonic); + static StoredKey createWithMnemonic(const std::string& name, const Data& password, const std::string& mnemonic); /// Create a new StoredKey, with the given name, mnemonic and password. /// @throws std::invalid_argument if mnemonic is invalid - static StoredKey createWithMnemonicRandom(const std::string& name, const std::string& password); + static StoredKey createWithMnemonicRandom(const std::string& name, const Data& password); /// Create a new StoredKey, with the given name, mnemonic and password, and also add the default address for the given coin.. /// @throws std::invalid_argument if mnemonic is invalid - static StoredKey createWithMnemonicAddDefaultAddress(const std::string& name, const std::string& password, const std::string& mnemonic, TWCoinType coin); + static StoredKey createWithMnemonicAddDefaultAddress(const std::string& name, const Data& password, const std::string& mnemonic, TWCoinType coin); /// Create a new StoredKey, with the given name and private key. /// @throws std::invalid_argument if privateKeyData is not a vald private key - static StoredKey createWithPrivateKey(const std::string& name, const std::string& password, const Data& privateKeyData); + static StoredKey createWithPrivateKey(const std::string& name, const Data& password, const Data& privateKeyData); /// Create a new StoredKey, with the given name and private key, and also add the default address for the given coin.. /// @throws std::invalid_argument if privateKeyData is not a vald private key - static StoredKey createWithPrivateKeyAddDefaultAddress(const std::string& name, const std::string& password, TWCoinType coin, const Data& privateKeyData); + static StoredKey createWithPrivateKeyAddDefaultAddress(const std::string& name, const Data& password, TWCoinType coin, const Data& privateKeyData); /// Create a StoredKey from a JSON object. static StoredKey createWithJson(const nlohmann::json& json); @@ -67,7 +67,7 @@ class StoredKey { /// Returns the HDWallet for this key. /// /// @throws std::invalid_argument if this key is of a type other than `mnemonicPhrase`. - const HDWallet wallet(const std::string& password) const; + const HDWallet wallet(const Data& password) const; /// Returns the account for a specific coin, creating it if necessary and /// the provided wallet is not `nullptr`. @@ -86,7 +86,7 @@ class StoredKey { /// /// @throws std::invalid_argument if this key is of a type other than /// `mnemonicPhrase` and a coin other than the default is requested. - const PrivateKey privateKey(TWCoinType coin, const std::string& password); + const PrivateKey privateKey(TWCoinType coin, const Data& password); /// Loads and decrypts a stored key from a file. /// @@ -110,7 +110,7 @@ class StoredKey { /// /// Use to fix legacy wallets with invalid address data. This method needs /// the encryption password to re-derive addresses from private keys. - void fixAddresses(const std::string& password); + void fixAddresses(const Data& password); private: /// Default constructor, private @@ -119,7 +119,7 @@ class StoredKey { /// Initializes a `StoredKey` with a type, an encryption password, and unencrypted data. /// This contstructor will encrypt the provided data with default encryption /// parameters. - StoredKey(StoredKeyType type, std::string name, const std::string& password, Data data); + StoredKey(StoredKeyType type, std::string name, const Data& password, const Data& data); }; } // namespace TW::Keystore diff --git a/src/NEAR/Serialization.cpp b/src/NEAR/Serialization.cpp index 9e69a1951cf..4b6e24826de 100644 --- a/src/NEAR/Serialization.cpp +++ b/src/NEAR/Serialization.cpp @@ -30,7 +30,7 @@ static void writeU128(Data& data, const std::string& numberData) { data.insert(std::end(data), std::begin(numberData), std::end(numberData)); } -template static void writeRawBuffer(Data &data, const T& buf) { +template static void writeRawBuffer(Data& data, const T& buf) { data.insert(std::end(data), std::begin(buf), std::end(buf)); } diff --git a/src/NEO/Address.h b/src/NEO/Address.h index bd2afc2a44a..d3d78ab7088 100644 --- a/src/NEO/Address.h +++ b/src/NEO/Address.h @@ -23,13 +23,13 @@ class Address : public TW::Base58Address { static const byte version = 0x17; /// Determines whether a string makes a valid NEO address. - static bool isValid(const std::string &string); + static bool isValid(const std::string& string); /// Initializes a NEO address with a string representation. - explicit Address(const std::string &string) : TW::Base58Address(string) {} + explicit Address(const std::string& string) : TW::Base58Address(string) {} /// Initializes a NEO address with a collection of bytes. - explicit Address(const Data &data) : TW::Base58Address(data) {} + explicit Address(const Data& data) : TW::Base58Address(data) {} /// Initializes an address with a collection of public key. explicit Address(uint8_t m, const std::vector& publicKeys); @@ -40,7 +40,7 @@ class Address : public TW::Base58Address { /// Initializes a NEO address without a public key. explicit Address(); - Data toScriptHash(const Data &data) const; + Data toScriptHash(const Data& data) const; Data toScriptHash() const; }; diff --git a/src/NEO/CoinReference.h b/src/NEO/CoinReference.h index 2b040923ede..d21b8865630 100644 --- a/src/NEO/CoinReference.h +++ b/src/NEO/CoinReference.h @@ -29,7 +29,7 @@ class CoinReference : public Serializable { return Hash::sha256Size + prevIndexSize; } - void deserialize(const Data &data, int initial_pos = 0) override { + void deserialize(const Data& data, int initial_pos = 0) override { prevHash = load(readBytes(data, Hash::sha256Size, initial_pos)); prevIndex = decode16LE(data.data() + initial_pos + Hash::sha256Size); } diff --git a/src/NEO/ISerializable.h b/src/NEO/ISerializable.h index 3106328cdc3..64e30ee0754 100644 --- a/src/NEO/ISerializable.h +++ b/src/NEO/ISerializable.h @@ -17,7 +17,7 @@ class ISerializable { virtual ~ISerializable() {} virtual int64_t size() const = 0; virtual Data serialize() const = 0; - virtual void deserialize(const Data &data, int initial_pos = 0) = 0; + virtual void deserialize(const Data& data, int initial_pos = 0) = 0; }; } // namespace TW::NEO diff --git a/src/NEO/MinerTransaction.h b/src/NEO/MinerTransaction.h index 01e3235fb06..ca73b306958 100644 --- a/src/NEO/MinerTransaction.h +++ b/src/NEO/MinerTransaction.h @@ -15,7 +15,7 @@ class MinerTransaction : public Transaction { public: uint32_t nonce; - virtual int deserializeExclusiveData(const Data &data, int initial_pos = 0) { + virtual int deserializeExclusiveData(const Data& data, int initial_pos = 0) { nonce = decode32LE(data.data() + initial_pos); return initial_pos + 4; } diff --git a/src/NEO/ReadData.cpp b/src/NEO/ReadData.cpp index e419f944319..459044589de 100644 --- a/src/NEO/ReadData.cpp +++ b/src/NEO/ReadData.cpp @@ -7,15 +7,14 @@ #include "../Data.h" #include "ReadData.h" - -TW::Data TW::readBytes(const TW::Data &from, int max, int initial_pos) { +TW::Data TW::readBytes(const TW::Data& from, int max, int initial_pos) { if (from.size() - initial_pos < max) { throw std::invalid_argument("Data::Cannot read enough bytes!"); } return TW::Data(from.begin() + initial_pos, from.begin() + initial_pos + max); } -TW::Data TW::readVarBytes(const Data &from, int initial_pos, uint32_t* dataRead) { +TW::Data TW::readVarBytes(const Data& from, int initial_pos, uint32_t* dataRead) { uint64_t size = readVar(from, initial_pos); auto shift = varIntSize(size); if (dataRead) { @@ -24,7 +23,7 @@ TW::Data TW::readVarBytes(const Data &from, int initial_pos, uint32_t* dataRead) return readBytes(from, int(size), initial_pos + int(shift)); } -template<> uint64_t TW::readVar(const TW::Data &from, int initial_pos, const uint64_t &max) { +template<> uint64_t TW::readVar(const TW::Data& from, int initial_pos, const uint64_t &max) { byte fb = from[initial_pos]; uint64_t value; if (fb == 0xFD) { @@ -43,11 +42,11 @@ template<> uint64_t TW::readVar(const TW::Data &from, int initial_pos, const uin return value; } -template<> int64_t TW::readVar(const TW::Data &from, int initial_pos, const int64_t &max) { +template<> int64_t TW::readVar(const TW::Data& from, int initial_pos, const int64_t &max) { return (int64_t) readVar(from, initial_pos, uint64_t(max)); } -TW::Data TW::writeVarBytes(const Data &from, int initial_pos) { +TW::Data TW::writeVarBytes(const Data& from, int initial_pos) { Data resp; encodeVarInt(uint64_t(from.size() - initial_pos), resp); resp.insert(resp.end(), from.begin() + initial_pos, from.end()); diff --git a/src/NEO/ReadData.h b/src/NEO/ReadData.h index 80b86693f02..624a1265120 100644 --- a/src/NEO/ReadData.h +++ b/src/NEO/ReadData.h @@ -7,20 +7,21 @@ #pragma once #include +#include #include "../Data.h" #include "../BinaryCoding.h" namespace TW { -Data readBytes(const Data &from, int max, int initial_pos = 0); -Data readVarBytes(const Data &from, int initial_pos = 0, uint32_t* dataRead = nullptr); +Data readBytes(const Data& from, int max, int initial_pos = 0); +Data readVarBytes(const Data& from, int initial_pos = 0, uint32_t* dataRead = nullptr); -template T readVar(const TW::Data &from, int initial_pos = 0, const T &max = INT_MAX); -template<> int64_t readVar(const TW::Data &from, int initial_pos, const int64_t &max); -template<> uint64_t readVar(const TW::Data &from, int initial_pos, const uint64_t &max); +template T readVar(const TW::Data& from, int initial_pos = 0, const T &max = INT_MAX); +template<> int64_t readVar(const TW::Data& from, int initial_pos, const int64_t &max); +template<> uint64_t readVar(const TW::Data& from, int initial_pos, const uint64_t &max); -Data writeVarBytes(const Data &from, int initial_pos = 0); +Data writeVarBytes(const Data& from, int initial_pos = 0); template static std::vector concat(const std::vector& v1, const std::vector& v2) { diff --git a/src/NEO/Script.cpp b/src/NEO/Script.cpp index 6e89610335b..a168dfe74bb 100644 --- a/src/NEO/Script.cpp +++ b/src/NEO/Script.cpp @@ -8,7 +8,7 @@ namespace TW::NEO { -Data Script::CreateSignatureRedeemScript(Data publicKey) { +Data Script::CreateSignatureRedeemScript(const Data& publicKey) { Data result; result.push_back((byte)PUSHBYTES21); result.insert(result.end(), publicKey.begin(), publicKey.end()); @@ -16,7 +16,7 @@ Data Script::CreateSignatureRedeemScript(Data publicKey) { return result; } -Data Script::CreateInvocationScript(Data signature) { +Data Script::CreateInvocationScript(const Data& signature) { Data result; result.push_back((byte)PUSHBYTES40); result.insert(result.end(), signature.begin(), signature.end()); diff --git a/src/NEO/Script.h b/src/NEO/Script.h index 5cbd4a59d82..64d47982754 100644 --- a/src/NEO/Script.h +++ b/src/NEO/Script.h @@ -11,8 +11,8 @@ namespace TW::NEO { class Script { public: - static Data CreateSignatureRedeemScript(Data publicKey); - static Data CreateInvocationScript(Data signature); + static Data CreateSignatureRedeemScript(const Data& publicKey); + static Data CreateInvocationScript(const Data& signature); }; } // namespace TW::NEO diff --git a/src/NEO/Serializable.h b/src/NEO/Serializable.h index 423253b861b..51ec20edf73 100644 --- a/src/NEO/Serializable.h +++ b/src/NEO/Serializable.h @@ -44,12 +44,9 @@ class Serializable : public ISerializable { } template - static inline int deserialize(std::vector &resp, const Data &data, int initial_pos = 0) { + static inline int deserialize(std::vector &resp, const Data& data, int initial_pos = 0) { uint64_t size = readVar(data, initial_pos, INT_MAX); - if (size < 0) { - throw std::invalid_argument("Serializable::deserialize ArgumentOutOfRangeException"); - } - + // assert(size >= 0); initial_pos += varIntSize(size); for (uint64_t i = 0; i < size; ++i) { T value; diff --git a/src/NEO/Transaction.cpp b/src/NEO/Transaction.cpp index 897ec967714..6c352b36894 100644 --- a/src/NEO/Transaction.cpp +++ b/src/NEO/Transaction.cpp @@ -21,7 +21,7 @@ int64_t Transaction::size() const { return serialize().size(); } -void Transaction::deserialize(const Data &data, int initial_pos) { +void Transaction::deserialize(const Data& data, int initial_pos) { type = (TransactionType) data[initial_pos++]; version = data[initial_pos++]; initial_pos = deserializeExclusiveData(data, initial_pos); @@ -33,7 +33,7 @@ void Transaction::deserialize(const Data &data, int initial_pos) { Serializable::deserialize(outputs, data, initial_pos); } -Transaction * Transaction::deserializeFrom(const Data &data, int initial_pos) { +Transaction * Transaction::deserializeFrom(const Data& data, int initial_pos) { Transaction * resp = nullptr; switch ((TransactionType) data[initial_pos]) { case TransactionType::TT_MinerTransaction: diff --git a/src/NEO/Transaction.h b/src/NEO/Transaction.h index 5fb387f5f47..50a311e3d9a 100644 --- a/src/NEO/Transaction.h +++ b/src/NEO/Transaction.h @@ -28,18 +28,18 @@ class Transaction : public Serializable { virtual ~Transaction() {} int64_t size() const override; - void deserialize(const Data &data, int initial_pos = 0) override; + void deserialize(const Data& data, int initial_pos = 0) override; Data serialize() const override; bool operator==(const Transaction &other) const; - virtual int deserializeExclusiveData(const Data &data, int initial_pos = 0) { return initial_pos; } + virtual int deserializeExclusiveData(const Data& data, int initial_pos = 0) { return initial_pos; } virtual Data serializeExclusiveData() const { return Data(); } Data getHash() const; uint256_t getHashUInt256() const; - static Transaction * deserializeFrom(const Data &data, int initial_pos = 0); + static Transaction * deserializeFrom(const Data& data, int initial_pos = 0); }; } // namespace TW::NEO diff --git a/src/NEO/TransactionAttribute.h b/src/NEO/TransactionAttribute.h index 3978484a614..7a5187e65c0 100644 --- a/src/NEO/TransactionAttribute.h +++ b/src/NEO/TransactionAttribute.h @@ -24,7 +24,7 @@ class TransactionAttribute : public Serializable { return 1 + data.size(); } - void deserialize(const Data &data, int initial_pos = 0) override { + void deserialize(const Data& data, int initial_pos = 0) override { if (data.size() < initial_pos + 1) { throw std::invalid_argument("Invalid data for deserialization"); } diff --git a/src/NEO/TransactionOutput.h b/src/NEO/TransactionOutput.h index 85d05d7d297..1c27d3f3781 100644 --- a/src/NEO/TransactionOutput.h +++ b/src/NEO/TransactionOutput.h @@ -31,7 +31,7 @@ class TransactionOutput : public Serializable { return store(assetId).size() + valueSize + store(scriptHash).size(); } - void deserialize(const Data &data, int initial_pos = 0) override { + void deserialize(const Data& data, int initial_pos = 0) override { assetId = load(readBytes(data, assetIdSize, initial_pos)); value = decode64LE(data.data() + initial_pos + assetIdSize); scriptHash = load(readBytes(data, scriptHashSize, initial_pos + assetIdSize + valueSize)); diff --git a/src/NEO/Witness.h b/src/NEO/Witness.h index 808037b7dcf..6f0e7c9d139 100644 --- a/src/NEO/Witness.h +++ b/src/NEO/Witness.h @@ -23,7 +23,7 @@ class Witness : public Serializable { return invocationScript.size() + verificationScript.size(); } - void deserialize(const Data &data, int initial_pos = 0) override { + void deserialize(const Data& data, int initial_pos = 0) override { uint32_t size; invocationScript = readVarBytes(data, initial_pos, &size); verificationScript = readVarBytes(data, initial_pos + size); diff --git a/src/Nebulas/Address.cpp b/src/Nebulas/Address.cpp index acdc595d17d..46f210636f7 100644 --- a/src/Nebulas/Address.cpp +++ b/src/Nebulas/Address.cpp @@ -8,10 +8,11 @@ #include "../Base58.h" #include "../Hash.h" #include "../HexCoding.h" +#include using namespace TW::Nebulas; -bool Address::isValid(const std::string &string) { +bool Address::isValid(const std::string& string) { auto data = Base58::bitcoin.decode(string); if (data.size() != (size_t)Address::size) { return false; @@ -30,7 +31,7 @@ bool Address::isValid(const std::string &string) { return ::memcmp(dataSha3.data(), checksum.data(), 4) == 0; } -Address::Address(const std::string &string) { +Address::Address(const std::string& string) { if (!isValid(string)) { throw std::invalid_argument("Invalid address string"); } @@ -39,7 +40,7 @@ Address::Address(const std::string &string) { std::copy(data.begin(), data.end(), bytes.begin()); } -Address::Address(const Data &data) { +Address::Address(const Data& data) { if (!Base58Address::isValid(data)) { throw std::invalid_argument("Invalid address data"); } diff --git a/src/Solana/Address.cpp b/src/Solana/Address.cpp index a45bcc3ba94..93460cdf9ea 100644 --- a/src/Solana/Address.cpp +++ b/src/Solana/Address.cpp @@ -41,8 +41,8 @@ Data Address::vector() const { return vec; } -Address addressFromValidatorSeed(Address& fromAddress, Address& validatorAddress, - Address& programId) { +Address addressFromValidatorSeed(const Address& fromAddress, const Address& validatorAddress, + const Address& programId) { Data extended = fromAddress.vector(); std::string seed = validatorAddress.string(); Data vecSeed(seed.begin(), seed.end()); diff --git a/src/Solana/Address.h b/src/Solana/Address.h index fda8c909415..8bdc71ec85e 100644 --- a/src/Solana/Address.h +++ b/src/Solana/Address.h @@ -40,6 +40,6 @@ class Address : public Base58Address<32> { } // namespace TW::Solana -TW::Solana::Address addressFromValidatorSeed(TW::Solana::Address& fromAddress, - TW::Solana::Address& validatorAddress, - TW::Solana::Address& programId); +TW::Solana::Address addressFromValidatorSeed(const TW::Solana::Address& fromAddress, + const TW::Solana::Address& validatorAddress, + const TW::Solana::Address& programId); diff --git a/src/Solana/Transaction.h b/src/Solana/Transaction.h index 12ffdbe9c6f..b64cce5335d 100644 --- a/src/Solana/Transaction.h +++ b/src/Solana/Transaction.h @@ -54,7 +54,7 @@ struct CompiledInstruction { // The program input data Data data; - CompiledInstruction(uint8_t programIdIndex, Data accounts, Data data) + CompiledInstruction(uint8_t programIdIndex, const Data& accounts, const Data& data) : programIdIndex(programIdIndex), accounts(accounts), data(data) {} // This constructor creates a default System Transfer instruction diff --git a/src/TON/Cell.cpp b/src/TON/Cell.cpp index af70dbfb3c2..be52dc56130 100644 --- a/src/TON/Cell.cpp +++ b/src/TON/Cell.cpp @@ -41,7 +41,7 @@ Slice Slice::createFromHex(std::string const& dataStr) { } Slice Slice::createFromBits(const Data& data, size_t sizeBits) { - if (sizeBits <= 0) { + if (sizeBits == 0) { throw std::runtime_error("empty data"); } Slice s; diff --git a/src/Tezos/Signer.cpp b/src/Tezos/Signer.cpp index 0c4aae8ba1f..b0732fd78c9 100644 --- a/src/Tezos/Signer.cpp +++ b/src/Tezos/Signer.cpp @@ -45,7 +45,7 @@ Data Signer::signOperationList(const PrivateKey& privateKey, const OperationList return signData(privateKey, forged); } -Data Signer::signData(const PrivateKey& privateKey, Data data) { +Data Signer::signData(const PrivateKey& privateKey, const Data& data) { Data watermarkedData = Data(); watermarkedData.push_back(0x03); append(watermarkedData, data); diff --git a/src/Tezos/Signer.h b/src/Tezos/Signer.h index d6b88fcc6b5..798d703ab21 100644 --- a/src/Tezos/Signer.h +++ b/src/Tezos/Signer.h @@ -25,7 +25,7 @@ class Signer { public: /// Signs the given transaction. Data signOperationList(const PrivateKey& privateKey, const OperationList& operationList); - Data signData(const PrivateKey& privateKey, Data data); + Data signData(const PrivateKey& privateKey, const Data& data); }; } // namespace TW::Tezos diff --git a/src/Theta/Transaction.h b/src/Theta/Transaction.h index fccc7e5439d..735c21ab1a8 100644 --- a/src/Theta/Transaction.h +++ b/src/Theta/Transaction.h @@ -24,7 +24,7 @@ class TxInput { TxInput(Ethereum::Address address, Coins coins, uint64_t sequence) : address(std::move(address)), coins(std::move(coins)), sequence(sequence) {} - TxInput(Ethereum::Address address, Coins coins, uint64_t sequence, Data signature) + TxInput(Ethereum::Address address, Coins coins, uint64_t sequence, const Data& signature) : address(std::move(address)), coins(std::move(coins)), sequence(sequence), signature(std::move(signature)) {} }; diff --git a/src/VeChain/Clause.h b/src/VeChain/Clause.h index eb8d1e5dd06..9bbb1bc6435 100644 --- a/src/VeChain/Clause.h +++ b/src/VeChain/Clause.h @@ -19,7 +19,7 @@ class Clause { uint256_t value; Data data; - Clause(Ethereum::Address to, uint256_t value, Data data = {}) + Clause(Ethereum::Address to, uint256_t value, const Data& data = {}) : to(std::move(to)), value(std::move(value)), data(std::move(data)) {} /// Decodes from a proto representation. diff --git a/src/Waves/Address.cpp b/src/Waves/Address.cpp index 7b42ff51dc0..672d0310595 100644 --- a/src/Waves/Address.cpp +++ b/src/Waves/Address.cpp @@ -13,6 +13,7 @@ #include #include #include +#include using namespace TW; using namespace TW::Waves; @@ -22,7 +23,7 @@ Data Address::secureHash(const T &data) { return Hash::keccak256(Hash::blake2b(data, 32)); } -bool Address::isValid(const Data &decoded) { +bool Address::isValid(const Data& decoded) { if (decoded.size() != Address::size) { return false; } @@ -44,12 +45,12 @@ bool Address::isValid(const Data &decoded) { return std::memcmp(data_checksum.data(), calculated_checksum.data(), 4) == 0; } -bool Address::isValid(const std::string &string) { +bool Address::isValid(const std::string& string) { const auto decoded = Base58::bitcoin.decode(string); return isValid(decoded); } -Address::Address(const std::string &string) { +Address::Address(const std::string& string) { const auto decoded = Base58::bitcoin.decode(string); if (!isValid(string)) { throw std::invalid_argument("Invalid address key data"); @@ -57,7 +58,7 @@ Address::Address(const std::string &string) { std::copy(decoded.begin(), decoded.end(), bytes.begin()); } -Address::Address(const Data &data) { +Address::Address(const Data& data) { if (!isValid(data)) { throw std::invalid_argument("Invalid address data"); } diff --git a/src/Waves/Address.h b/src/Waves/Address.h index 81950ee6b93..df518415334 100644 --- a/src/Waves/Address.h +++ b/src/Waves/Address.h @@ -17,9 +17,6 @@ namespace TW::Waves { class Address : public Base58Address<26> { public: - /// Number of bytes in an address. - static const size_t size = 26; - /// Address version. static const signed char v1 = 0x01; @@ -29,20 +26,16 @@ class Address : public Base58Address<26> { template static Data secureHash(const T &data); - /// Address data consisting of a version and network bytes followed by the public key - /// hash and the checksum. - std::array bytes; - /// Determines whether a string makes a valid address. - static bool isValid(const std::string &string); + static bool isValid(const std::string& string); - static bool isValid(const Data &data); + static bool isValid(const Data& data); /// Initializes a address with a string representation. - explicit Address(const std::string &string); + explicit Address(const std::string& string); /// Initializes a address with a collection of bytes. - explicit Address(const Data &data); + explicit Address(const Data& data); /// Initializes a address with a public key and a prefix. explicit Address(const PublicKey &publicKey); diff --git a/src/Waves/Transaction.cpp b/src/Waves/Transaction.cpp index 277c1540bc3..ee9d2a5af44 100644 --- a/src/Waves/Transaction.cpp +++ b/src/Waves/Transaction.cpp @@ -17,7 +17,7 @@ using json = nlohmann::json; const std::string Transaction::WAVES = "WAVES"; -Data serializeTransfer(int64_t amount, std::string asset, int64_t fee, std::string fee_asset, Address to, Data attachment, int64_t timestamp, Data pub_key) { +Data serializeTransfer(int64_t amount, std::string asset, int64_t fee, std::string fee_asset, Address to, const Data& attachment, int64_t timestamp, const Data& pub_key) { auto data = Data(); if (asset.empty()) { asset = Transaction::WAVES; @@ -50,7 +50,7 @@ Data serializeTransfer(int64_t amount, std::string asset, int64_t fee, std::stri return data; } -Data serializeLease(int64_t amount, int64_t fee, Address to, int64_t timestamp, Data pub_key) { +Data serializeLease(int64_t amount, int64_t fee, Address to, int64_t timestamp, const Data& pub_key) { auto data = Data(); data.resize(2); data[0] = static_cast(TransactionType::lease); @@ -65,7 +65,7 @@ Data serializeLease(int64_t amount, int64_t fee, Address to, int64_t timestamp, return data; } -Data serializeCancelLease(Data leaseId, int64_t fee, int64_t timestamp, Data pub_key) { +Data serializeCancelLease(const Data& leaseId, int64_t fee, int64_t timestamp, const Data& pub_key) { auto data = Data(); data.resize(2); data[0] = static_cast(TransactionType::cancelLease); @@ -79,7 +79,7 @@ Data serializeCancelLease(Data leaseId, int64_t fee, int64_t timestamp, Data pub return data; } -json jsonTransfer(Data signature, int64_t amount, const std::string &asset, int64_t fee, const std::string &fee_asset, Address to, Data attachment, int64_t timestamp, Data pub_key) { +json jsonTransfer(const Data& signature, int64_t amount, const std::string& asset, int64_t fee, const std::string& fee_asset, Address to, const Data& attachment, int64_t timestamp, const Data& pub_key) { json jsonTx; jsonTx["type"] = TransactionType::transfer; @@ -101,7 +101,7 @@ json jsonTransfer(Data signature, int64_t amount, const std::string &asset, int6 return jsonTx; } -json jsonLease(Data signature, int64_t amount, int64_t fee, Address to, int64_t timestamp, Data pub_key) { +json jsonLease(const Data& signature, int64_t amount, int64_t fee, Address to, int64_t timestamp, const Data& pub_key) { json jsonTx; jsonTx["type"] = TransactionType::lease; @@ -116,7 +116,7 @@ json jsonLease(Data signature, int64_t amount, int64_t fee, Address to, int64_t return jsonTx; } -json jsonCancelLease(Data signature, Data leaseId, int64_t fee, int64_t timestamp, Data pub_key) { +json jsonCancelLease(const Data& signature, const Data& leaseId, int64_t fee, int64_t timestamp, const Data& pub_key) { json jsonTx; jsonTx["type"] = TransactionType::cancelLease; @@ -162,7 +162,7 @@ Data Transaction::serializeToSign() const { -json Transaction::buildJson(Data signature) const { +json Transaction::buildJson(const Data& signature) const { if (input.has_transfer_message()) { auto message = input.transfer_message(); auto attachment = Data(message.attachment().begin(), message.attachment().end()); diff --git a/src/Waves/Transaction.h b/src/Waves/Transaction.h index 130f44ba095..b22fd54a030 100644 --- a/src/Waves/Transaction.h +++ b/src/Waves/Transaction.h @@ -29,7 +29,7 @@ class Transaction { public: Data serializeToSign() const; - nlohmann::json buildJson(Data signature) const; + nlohmann::json buildJson(const Data& signature) const; }; } // namespace TW::Waves diff --git a/src/XXHash64.h b/src/XXHash64.h index 34122ebc85e..6147ff42759 100644 --- a/src/XXHash64.h +++ b/src/XXHash64.h @@ -33,6 +33,7 @@ class XXHash64 state[1] = seed + Prime2; state[2] = seed; state[3] = seed - Prime1; + buffer[0] = 0; bufferSize = 0; totalLength = 0; } diff --git a/src/Zilliqa/Address.h b/src/Zilliqa/Address.h index 9aa09804f59..be7a7ef234f 100644 --- a/src/Zilliqa/Address.h +++ b/src/Zilliqa/Address.h @@ -18,12 +18,12 @@ class Address : public Bech32Address { public: static const std::string hrp; // HRP_ZILLIQA - static bool isValid(const std::string addr) { return Bech32Address::isValid(addr, hrp); } + static bool isValid(const std::string& addr) { return Bech32Address::isValid(addr, hrp); } Address() : Bech32Address(hrp) {} /// Initializes an address with a key hash. - Address(Data keyHash) : Bech32Address(hrp, keyHash) {} + Address(const Data& keyHash) : Bech32Address(hrp, keyHash) {} /// Initializes an address with a public key. Address(const PublicKey& publicKey) : Bech32Address(hrp, HASHER_SHA2, publicKey) {} diff --git a/src/interface/TWAnyAddress.cpp b/src/interface/TWAnyAddress.cpp index fcd2587ddf2..dd6ee615f4c 100644 --- a/src/interface/TWAnyAddress.cpp +++ b/src/interface/TWAnyAddress.cpp @@ -20,6 +20,7 @@ #include "../Cardano/AddressV3.h" #include "../NEO/Address.h" #include "../Nano/Address.h" +#include "../Elrond/Address.h" #include "../Coin.h" #include "../HexCoding.h" @@ -36,13 +37,13 @@ bool TWAnyAddressEqual(struct TWAnyAddress* _Nonnull lhs, struct TWAnyAddress* _ } bool TWAnyAddressIsValid(TWString* _Nonnull string, enum TWCoinType coin) { - auto& address = *reinterpret_cast(string); + const auto& address = *reinterpret_cast(string); return TW::validateAddress(coin, address); } struct TWAnyAddress* _Nullable TWAnyAddressCreateWithString(TWString* _Nonnull string, enum TWCoinType coin) { - auto& address = *reinterpret_cast(string); + const auto& address = *reinterpret_cast(string); auto normalized = TW::normalizeAddress(coin, address); if (normalized.empty()) { return nullptr; } return new TWAnyAddress{TWStringCreateWithUTF8Bytes(normalized.c_str()), coin}; @@ -184,6 +185,16 @@ TWData* _Nonnull TWAnyAddressData(struct TWAnyAddress* _Nonnull address) { data = Data(addr.bytes.begin(), addr.bytes.end()); break; } + + case TWCoinTypeElrond: { + Elrond::Address addr; + if (Elrond::Address::decode(string, addr)) { + data = addr.getKeyHash(); + } + + break; + } + default: break; } return TWDataCreateWithBytes(data.data(), data.size()); diff --git a/src/interface/TWBase58.cpp b/src/interface/TWBase58.cpp index ee38331260e..923b8a33bf0 100644 --- a/src/interface/TWBase58.cpp +++ b/src/interface/TWBase58.cpp @@ -13,7 +13,7 @@ using namespace TW; TWString *_Nonnull TWBase58Encode(TWData *_Nonnull data) { - auto& d = *reinterpret_cast(data); + const auto& d = *reinterpret_cast(data); const auto str = Base58::bitcoin.encodeCheck(d); return TWStringCreateWithUTF8Bytes(str.c_str()); } diff --git a/src/interface/TWBitcoinAddress.cpp b/src/interface/TWBitcoinAddress.cpp index b18e840364d..8df8de2a37f 100644 --- a/src/interface/TWBitcoinAddress.cpp +++ b/src/interface/TWBitcoinAddress.cpp @@ -38,7 +38,7 @@ struct TWBitcoinAddress *_Nullable TWBitcoinAddressCreateWithString(TWString *_N } struct TWBitcoinAddress *_Nullable TWBitcoinAddressCreateWithData(TWData *_Nonnull data) { - auto& d = *reinterpret_cast(data); + const auto& d = *reinterpret_cast(data); try { return new TWBitcoinAddress{ Address(d) }; } catch (...) { diff --git a/src/interface/TWBitcoinScript.cpp b/src/interface/TWBitcoinScript.cpp index 1fa6575c560..b316b1d0fe6 100644 --- a/src/interface/TWBitcoinScript.cpp +++ b/src/interface/TWBitcoinScript.cpp @@ -59,6 +59,10 @@ bool TWBitcoinScriptIsPayToWitnessScriptHash(const struct TWBitcoinScript *scrip return script->impl.isPayToWitnessScriptHash(); } +bool TWBitcoinScriptIsPayToWitnessPublicKeyHash(const struct TWBitcoinScript *script) { + return script->impl.isPayToWitnessPublicKeyHash(); +} + bool TWBitcoinScriptIsWitnessProgram(const struct TWBitcoinScript *script) { return script->impl.isWitnessProgram(); } @@ -69,7 +73,7 @@ bool TWBitcoinScriptEqual(const struct TWBitcoinScript *_Nonnull lhs, const stru TWData *TWBitcoinScriptMatchPayToPubkey(const struct TWBitcoinScript *script) { std::vector data; - if (script->impl.matchPayToPubkey(data)) { + if (script->impl.matchPayToPublicKey(data)) { return TWDataCreateWithBytes(data.data(), data.size()); } return nullptr; @@ -77,7 +81,7 @@ TWData *TWBitcoinScriptMatchPayToPubkey(const struct TWBitcoinScript *script) { TWData *TWBitcoinScriptMatchPayToPubkeyHash(const struct TWBitcoinScript *script) { std::vector data; - if (script->impl.matchPayToPubkeyHash(data)) { + if (script->impl.matchPayToPublicKeyHash(data)) { return TWDataCreateWithBytes(data.data(), data.size()); } return nullptr; @@ -127,7 +131,7 @@ struct TWBitcoinScript *TWBitcoinScriptBuildPayToScriptHash(TWData *scriptHash) struct TWBitcoinScript *TWBitcoinScriptBuildPayToWitnessPubkeyHash(TWData *hash) { auto v = reinterpret_cast*>(hash); - auto script = Script::buildPayToWitnessPubkeyHash(*v); + auto script = Script::buildPayToWitnessPublicKeyHash(*v); return new TWBitcoinScript{ .impl = script }; } diff --git a/src/interface/TWData.cpp b/src/interface/TWData.cpp index 5a0ae87d6b2..ed290bfccf2 100644 --- a/src/interface/TWData.cpp +++ b/src/interface/TWData.cpp @@ -70,8 +70,7 @@ void TWDataAppendByte(TWData *_Nonnull data, uint8_t byte) { void TWDataAppendData(TWData *_Nonnull data, TWData *_Nonnull append) { auto v = const_cast*>(reinterpret_cast*>(data)); auto av = reinterpret_cast*>(append); - for (auto& b : *av) - v->push_back(b); + std::copy(av->begin(), av->end(), std::back_inserter(*v)); } void TWDataReverse(TWData *_Nonnull data) { diff --git a/src/interface/TWPrivateKey.cpp b/src/interface/TWPrivateKey.cpp index 9ae603f8ffd..ab6b2b27ccb 100644 --- a/src/interface/TWPrivateKey.cpp +++ b/src/interface/TWPrivateKey.cpp @@ -90,7 +90,7 @@ struct TWPublicKey *_Nonnull TWPrivateKeyGetPublicKeyCurve25519(struct TWPrivate } TWData *TWPrivateKeySign(struct TWPrivateKey *_Nonnull pk, TWData *_Nonnull digest, enum TWCurve curve) { - auto& d = *reinterpret_cast(digest); + const auto& d = *reinterpret_cast(digest); auto result = pk->impl.sign(d, curve); if (result.empty()) { return nullptr; @@ -110,7 +110,7 @@ TWData *TWPrivateKeySignAsDER(struct TWPrivateKey *_Nonnull pk, TWData *_Nonnull } TWData *TWPrivateKeySignSchnorr(struct TWPrivateKey *_Nonnull pk, TWData *_Nonnull message, enum TWCurve curve) { - auto& msg = *reinterpret_cast(message); + const auto& msg = *reinterpret_cast(message); auto result = pk->impl.signSchnorr(msg, curve); if (result.empty()) { diff --git a/src/interface/TWPublicKey.cpp b/src/interface/TWPublicKey.cpp index 9ada3d666d0..83f2c9c4789 100644 --- a/src/interface/TWPublicKey.cpp +++ b/src/interface/TWPublicKey.cpp @@ -49,14 +49,14 @@ struct TWPublicKey *_Nonnull TWPublicKeyUncompressed(struct TWPublicKey *_Nonnul } bool TWPublicKeyVerify(struct TWPublicKey *_Nonnull pk, TWData *signature, TWData *message) { - auto& s = *reinterpret_cast(signature); - auto& m = *reinterpret_cast(message); + const auto& s = *reinterpret_cast(signature); + const auto& m = *reinterpret_cast(message); return pk->impl.verify(s, m); } bool TWPublicKeyVerifySchnorr(struct TWPublicKey *_Nonnull pk, TWData *_Nonnull signature, TWData *_Nonnull message) { - auto& s = *reinterpret_cast(signature); - auto& m = *reinterpret_cast(message); + const auto& s = *reinterpret_cast(signature); + const auto& m = *reinterpret_cast(message); return pk->impl.verifySchnorr(s, m); } diff --git a/src/interface/TWStoredKey.cpp b/src/interface/TWStoredKey.cpp index 795cfa38ce9..3fbfa5f1214 100644 --- a/src/interface/TWStoredKey.cpp +++ b/src/interface/TWStoredKey.cpp @@ -14,6 +14,7 @@ #include #include + using namespace TW::Keystore; struct TWStoredKey* _Nullable TWStoredKeyLoad(TWString* _Nonnull path) { @@ -25,29 +26,29 @@ struct TWStoredKey* _Nullable TWStoredKeyLoad(TWString* _Nonnull path) { } } -struct TWStoredKey* _Nonnull TWStoredKeyCreate(TWString* _Nonnull name, TWString* _Nonnull password) { +struct TWStoredKey* _Nonnull TWStoredKeyCreate(TWString* _Nonnull name, TWData* _Nonnull password) { const auto& nameString = *reinterpret_cast(name); - const auto& passwordString = *reinterpret_cast(password); - return new TWStoredKey{ StoredKey::createWithMnemonicRandom(nameString, passwordString) }; + const auto passwordData = TW::data(TWDataBytes(password), TWDataSize(password)); + return new TWStoredKey{ StoredKey::createWithMnemonicRandom(nameString, passwordData) }; } -struct TWStoredKey* _Nullable TWStoredKeyImportPrivateKey(TWData* _Nonnull privateKey, TWString* _Nonnull name, TWString* _Nonnull password, enum TWCoinType coin) { +struct TWStoredKey* _Nullable TWStoredKeyImportPrivateKey(TWData* _Nonnull privateKey, TWString* _Nonnull name, TWData* _Nonnull password, enum TWCoinType coin) { try { const auto& privateKeyData = *reinterpret_cast(privateKey); const auto& nameString = *reinterpret_cast(name); - const auto& passwordString = *reinterpret_cast(password); - return new TWStoredKey{ StoredKey::createWithPrivateKeyAddDefaultAddress(nameString, passwordString, coin, privateKeyData) }; + const auto passwordData = TW::data(TWDataBytes(password), TWDataSize(password)); + return new TWStoredKey{ StoredKey::createWithPrivateKeyAddDefaultAddress(nameString, passwordData, coin, privateKeyData) }; } catch (...) { return nullptr; } } -struct TWStoredKey* _Nullable TWStoredKeyImportHDWallet(TWString* _Nonnull mnemonic, TWString* _Nonnull name, TWString* _Nonnull password, enum TWCoinType coin) { +struct TWStoredKey* _Nullable TWStoredKeyImportHDWallet(TWString* _Nonnull mnemonic, TWString* _Nonnull name, TWData* _Nonnull password, enum TWCoinType coin) { try { const auto& mnemonicString = *reinterpret_cast(mnemonic); const auto& nameString = *reinterpret_cast(name); - const auto& passwordString = *reinterpret_cast(password); - return new TWStoredKey{ StoredKey::createWithMnemonicAddDefaultAddress(nameString, passwordString, mnemonicString, coin) }; + const auto passwordData = TW::data(TWDataBytes(password), TWDataSize(password)); + return new TWStoredKey{ StoredKey::createWithMnemonicAddDefaultAddress(nameString, passwordData, mnemonicString, coin) }; } catch (...) { return nullptr; } @@ -124,20 +125,20 @@ bool TWStoredKeyStore(struct TWStoredKey* _Nonnull key, TWString* _Nonnull path) } } -TWData* _Nullable TWStoredKeyDecryptPrivateKey(struct TWStoredKey* _Nonnull key, TWString* _Nonnull password) { +TWData* _Nullable TWStoredKeyDecryptPrivateKey(struct TWStoredKey* _Nonnull key, TWData* _Nonnull password) { try { - const auto& passwordString = *reinterpret_cast(password); - const auto data = key->impl.payload.decrypt(passwordString); + const auto passwordData = TW::data(TWDataBytes(password), TWDataSize(password)); + const auto data = key->impl.payload.decrypt(passwordData); return TWDataCreateWithBytes(data.data(), data.size()); } catch (...) { return nullptr; } } -TWString* _Nullable TWStoredKeyDecryptMnemonic(struct TWStoredKey* _Nonnull key, TWString* _Nonnull password) { +TWString* _Nullable TWStoredKeyDecryptMnemonic(struct TWStoredKey* _Nonnull key, TWData* _Nonnull password) { try { - const auto& passwordString = *reinterpret_cast(password); - const auto data = key->impl.payload.decrypt(passwordString); + const auto passwordData = TW::data(TWDataBytes(password), TWDataSize(password)); + const auto data = key->impl.payload.decrypt(passwordData); const auto string = std::string(data.begin(), data.end()); return TWStringCreateWithUTF8Bytes(string.c_str()); } catch (...) { @@ -145,19 +146,19 @@ TWString* _Nullable TWStoredKeyDecryptMnemonic(struct TWStoredKey* _Nonnull key, } } -struct TWPrivateKey* _Nullable TWStoredKeyPrivateKey(struct TWStoredKey* _Nonnull key, enum TWCoinType coin, TWString* _Nonnull password) { +struct TWPrivateKey* _Nullable TWStoredKeyPrivateKey(struct TWStoredKey* _Nonnull key, enum TWCoinType coin, TWData* _Nonnull password) { try { - const auto& passwordString = *reinterpret_cast(password); - return new TWPrivateKey{ key->impl.privateKey(coin, passwordString) }; + const auto passwordData = TW::data(TWDataBytes(password), TWDataSize(password)); + return new TWPrivateKey{ key->impl.privateKey(coin, passwordData) }; } catch (...) { return nullptr; } } -struct TWHDWallet* _Nullable TWStoredKeyWallet(struct TWStoredKey* _Nonnull key, TWString* _Nonnull password) { +struct TWHDWallet* _Nullable TWStoredKeyWallet(struct TWStoredKey* _Nonnull key, TWData* _Nonnull password) { try { - const auto& passwordString = *reinterpret_cast(password); - return new TWHDWallet{ key->impl.wallet(passwordString) }; + const auto passwordData = TW::data(TWDataBytes(password), TWDataSize(password)); + return new TWHDWallet{ key->impl.wallet(passwordData) }; } catch (...) { return nullptr; } @@ -168,10 +169,10 @@ TWData* _Nullable TWStoredKeyExportJSON(struct TWStoredKey* _Nonnull key) { return TWDataCreateWithBytes(reinterpret_cast(json.data()), json.size()); } -bool TWStoredKeyFixAddresses(struct TWStoredKey* _Nonnull key, TWString* _Nonnull password) { +bool TWStoredKeyFixAddresses(struct TWStoredKey* _Nonnull key, TWData* _Nonnull password) { try { - const auto& passwordString = *reinterpret_cast(password); - key->impl.fixAddresses(passwordString); + const auto passwordData = TW::data(TWDataBytes(password), TWDataSize(password)); + key->impl.fixAddresses(passwordData); return true; } catch (...) { return false; diff --git a/src/proto/Elrond.proto b/src/proto/Elrond.proto new file mode 100644 index 00000000000..41b4a0efc06 --- /dev/null +++ b/src/proto/Elrond.proto @@ -0,0 +1,36 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +syntax = "proto3"; + +package TW.Elrond.Proto; +option java_package = "wallet.core.jni.proto"; + +// A transaction, typical balance transfer +message TransactionMessage { + uint64 nonce = 1; + string value = 2; + string receiver = 3; + string sender = 4; + uint64 gas_price = 5; + uint64 gas_limit = 6; + string data = 7; +} + +// Input data necessary to create a signed transaction. +message SigningInput { + bytes private_key = 1; + + oneof message_oneof { + TransactionMessage transaction = 2; + } +} + +// Transaction signing output. +message SigningOutput { + string encoded = 1; + string signature = 2; +} diff --git a/src/proto/IoTeX.proto b/src/proto/IoTeX.proto index 669b049ecb3..1df337cf627 100644 --- a/src/proto/IoTeX.proto +++ b/src/proto/IoTeX.proto @@ -10,43 +10,73 @@ message Transfer { } message Staking { - message Stake { - string candidate = 1; - uint64 duration = 2; - bool nonDecay= 3; - bytes data = 4; - } - - message Unstake { - uint64 piggy_index = 1; - bytes data = 2; - } - - message Withdraw { - uint64 piggy_index = 1; - bytes data = 2; - } - - message AddStake { - uint64 piggy_index = 1; - bytes data = 2; - } - - message MoveStake { - uint64 piggy_index = 1; - string candidate = 2; - bytes data = 3; - } + // create stake + message Create { + string candidateName = 1; + string stakedAmount = 2; + uint32 stakedDuration = 3; + bool autoStake = 4; + bytes payload = 5; + } - string amount = 1; - string contract = 2; + // unstake or withdraw + message Reclaim { + uint64 bucketIndex = 1; + bytes payload = 2; + } + + // add the amount of bucket + message AddDeposit { + uint64 bucketIndex = 1; + string amount = 2; + bytes payload = 3; + } + + // restake the duration and autoStake flag of bucket + message Restake { + uint64 bucketIndex = 1; + uint32 stakedDuration = 2; + bool autoStake = 3; + bytes payload = 4; + } + + // move the bucket to vote for another candidate or transfer the ownership of bucket to another voters + message ChangeCandidate { + uint64 bucketIndex = 1; + string candidateName = 2; + bytes payload = 3; + } - oneof message { - Stake stake = 3; - Unstake unstake = 4; - Withdraw withdraw = 5; - AddStake addStake = 6; - MoveStake moveStake = 7; + message TransferOwnership { + uint64 bucketIndex = 1; + string voterAddress = 2; + bytes payload = 3; + } + + message CandidateBasicInfo { + string name = 1; + string operatorAddress = 2; + string rewardAddress = 3; + } + + message CandidateRegister { + CandidateBasicInfo candidate = 1; + string stakedAmount = 2; + uint32 stakedDuration = 3; + bool autoStake = 4; + string ownerAddress = 5; // if ownerAddress is absent, owner of candidate is the sender + bytes payload = 6; + } + oneof message { + Create stakeCreate = 1; + Reclaim stakeUnstake = 2; + Reclaim stakeWithdraw = 3; + AddDeposit stakeAddDeposit = 4; + Restake stakeRestake = 5; + ChangeCandidate stakeChangeCandidate = 6; + TransferOwnership stakeTransferOwnership = 7; + CandidateRegister candidateRegister = 8; + CandidateBasicInfo candidateUpdate = 9; } } @@ -65,8 +95,17 @@ message SigningInput { bytes privateKey = 5; oneof action { Transfer transfer = 10; - Staking staking = 11; ContractCall call = 12; + // Native staking + Staking.Create stakeCreate = 40; + Staking.Reclaim stakeUnstake = 41; + Staking.Reclaim stakeWithdraw = 42; + Staking.AddDeposit stakeAddDeposit = 43; + Staking.Restake stakeRestake = 44; + Staking.ChangeCandidate stakeChangeCandidate = 45; + Staking.TransferOwnership stakeTransferOwnership = 46; + Staking.CandidateRegister candidateRegister = 47; + Staking.CandidateBasicInfo candidateUpdate = 48; } } @@ -78,3 +117,30 @@ message SigningOutput { // Signed Action hash bytes hash = 2; } + +message ActionCore { + uint32 version = 1; + uint64 nonce = 2; + uint64 gasLimit = 3; + string gasPrice = 4; + oneof action { + Transfer transfer = 10; + ContractCall execution = 12; + // Native staking + Staking.Create stakeCreate = 40; + Staking.Reclaim stakeUnstake = 41; + Staking.Reclaim stakeWithdraw = 42; + Staking.AddDeposit stakeAddDeposit = 43; + Staking.Restake stakeRestake = 44; + Staking.ChangeCandidate stakeChangeCandidate = 45; + Staking.TransferOwnership stakeTransferOwnership = 46; + Staking.CandidateRegister candidateRegister = 47; + Staking.CandidateBasicInfo candidateUpdate = 48; + } +} + +message Action { + ActionCore core = 1; + bytes senderPubKey = 2; + bytes signature = 3; +} \ No newline at end of file diff --git a/swift/Podfile.lock b/swift/Podfile.lock index 9250a5e40a0..46f957ed3b2 100644 --- a/swift/Podfile.lock +++ b/swift/Podfile.lock @@ -17,4 +17,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 9af33e2495c8b16bfcea0f7779a0fcfe29e3ab60 -COCOAPODS: 1.9.0 +COCOAPODS: 1.9.1 diff --git a/swift/Sources/KeyStore.swift b/swift/Sources/KeyStore.swift index 35e46d9ab0d..d86ce0014c2 100755 --- a/swift/Sources/KeyStore.swift +++ b/swift/Sources/KeyStore.swift @@ -75,7 +75,7 @@ public final class KeyStore { /// Creates a new wallet. HD default by default public func createWallet(name: String, password: String, coins: [CoinType]) throws -> Wallet { - let key = StoredKey(name: name, password: password) + let key = StoredKey(name: name, password: Data(password.utf8)) return try saveCreatedWallet(for: key, password: password, coins: coins) } @@ -101,7 +101,7 @@ public final class KeyStore { /// Remove accounts from a wallet. public func removeAccounts(wallet: Wallet, coins: [CoinType], password: String) throws -> Wallet { - guard wallet.key.decryptPrivateKey(password: password) != nil else { + guard wallet.key.decryptPrivateKey(password: Data(password.utf8)) != nil else { throw Error.invalidPassword } @@ -130,7 +130,7 @@ public final class KeyStore { guard let key = StoredKey.importJSON(json: json) else { throw Error.invalidKey } - guard let data = key.decryptPrivateKey(password: password) else { + guard let data = key.decryptPrivateKey(password: Data(password.utf8)) else { throw Error.invalidPassword } @@ -159,7 +159,7 @@ public final class KeyStore { /// - coin: coin to use for this wallet /// - Returns: new wallet public func `import`(privateKey: PrivateKey, name: String, password: String, coin: CoinType) throws -> Wallet { - guard let newKey = StoredKey.importPrivateKey(privateKey: privateKey.data, name: name, password: password, coin: coin) else { + guard let newKey = StoredKey.importPrivateKey(privateKey: privateKey.data, name: name, password: Data(password.utf8), coin: coin) else { throw Error.invalidKey } let url = makeAccountURL() @@ -180,7 +180,7 @@ public final class KeyStore { /// - coins: coins to add /// - Returns: new account public func `import`(mnemonic: String, name: String, encryptPassword: String, coins: [CoinType]) throws -> Wallet { - guard let key = StoredKey.importHDWallet(mnemonic: mnemonic, name: name, password: encryptPassword, coin: coins.first ?? .ethereum) else { + guard let key = StoredKey.importHDWallet(mnemonic: mnemonic, name: name, password: Data(encryptPassword.utf8), coin: coins.first ?? .ethereum) else { throw Error.invalidMnemonic } let url = makeAccountURL() @@ -211,12 +211,12 @@ public final class KeyStore { throw Error.accountNotFound } - if let mnemonic = checkMnemonic(privateKeyData), let newKey = StoredKey.importHDWallet(mnemonic: mnemonic, name: "", password: newPassword, coin: coin) { + if let mnemonic = checkMnemonic(privateKeyData), let newKey = StoredKey.importHDWallet(mnemonic: mnemonic, name: "", password: Data(newPassword.utf8), coin: coin) { guard let json = newKey.exportJSON() else { throw Error.invalidKey } return json - } else if let newKey = StoredKey.importPrivateKey(privateKey: privateKeyData, name: "", password: newPassword, coin: coin) { + } else if let newKey = StoredKey.importPrivateKey(privateKey: privateKeyData, name: "", password: Data(newPassword.utf8), coin: coin) { guard let json = newKey.exportJSON() else { throw Error.invalidKey } @@ -233,7 +233,7 @@ public final class KeyStore { /// - password: account password /// - Returns: private key data for encrypted keys or menmonic phrase for HD wallets public func exportPrivateKey(wallet: Wallet, password: String) throws -> Data { - guard let key = wallet.key.decryptPrivateKey(password: password) else { + guard let key = wallet.key.decryptPrivateKey(password: Data(password.utf8)) else { throw Error.invalidPassword } return key @@ -247,7 +247,7 @@ public final class KeyStore { /// - Returns: mnemonic phrase /// - Throws: `EncryptError.invalidMnemonic` if the account is not an HD wallet. public func exportMnemonic(wallet: Wallet, password: String) throws -> String { - guard let mnemonic = wallet.key.decryptMnemonic(password: password) else { + guard let mnemonic = wallet.key.decryptMnemonic(password: Data(password.utf8)) else { throw Error.invalidPassword } return mnemonic @@ -278,7 +278,7 @@ public final class KeyStore { fatalError("Missing wallet") } - guard var privateKeyData = wallet.key.decryptPrivateKey(password: password) else { + guard var privateKeyData = wallet.key.decryptPrivateKey(password: Data(password.utf8)) else { throw Error.invalidPassword } defer { @@ -291,10 +291,10 @@ public final class KeyStore { } if let mnemonic = checkMnemonic(privateKeyData), - let key = StoredKey.importHDWallet(mnemonic: mnemonic, name: newName, password: newPassword, coin: coins[0]) { + let key = StoredKey.importHDWallet(mnemonic: mnemonic, name: newName, password: Data(newPassword.utf8), coin: coins[0]) { wallets[index].key = key } else if let key = StoredKey.importPrivateKey( - privateKey: privateKeyData, name: newName, password: newPassword, coin: coins[0]) { + privateKey: privateKeyData, name: newName, password: Data(newPassword.utf8), coin: coins[0]) { wallets[index].key = key } else { throw Error.invalidKey @@ -310,7 +310,7 @@ public final class KeyStore { fatalError("Missing wallet") } - guard var privateKey = wallet.key.decryptPrivateKey(password: password) else { + guard var privateKey = wallet.key.decryptPrivateKey(password: Data(password.utf8)) else { throw KeyStore.Error.invalidKey } defer { diff --git a/swift/Sources/Wallet.swift b/swift/Sources/Wallet.swift index e702ea105cf..036d2a22d7e 100755 --- a/swift/Sources/Wallet.swift +++ b/swift/Sources/Wallet.swift @@ -36,7 +36,7 @@ public final class Wallet: Hashable, Equatable { /// - Returns: the account /// - Throws: `KeyStore.Error.invalidPassword` if the password is incorrect. public func getAccount(password: String, coin: CoinType) throws -> Account { - let wallet = key.wallet(password: password) + let wallet = key.wallet(password: Data(password.utf8)) guard let account = key.accountForCoin(coin: coin, wallet: wallet) else { throw KeyStore.Error.invalidPassword } @@ -51,7 +51,7 @@ public final class Wallet: Hashable, Equatable { /// - Returns: the added accounts /// - Throws: `KeyStore.Error.invalidPassword` if the password is incorrect. public func getAccounts(password: String, coins: [CoinType]) throws -> [Account] { - guard let wallet = key.wallet(password: password) else { + guard let wallet = key.wallet(password: Data(password.utf8)) else { throw KeyStore.Error.invalidPassword } return coins.compactMap({ key.accountForCoin(coin: $0, wallet: wallet) }) @@ -65,7 +65,7 @@ public final class Wallet: Hashable, Equatable { /// - Returns: the private key /// - Throws: `KeyStore.Error.invalidPassword` if the password is incorrect. public func privateKey(password: String, coin: CoinType) throws -> PrivateKey { - guard let pk = key.privateKey(coin: coin, password: password) else { + guard let pk = key.privateKey(coin: coin, password: Data(password.utf8)) else { throw KeyStore.Error.invalidPassword } return pk diff --git a/swift/Tests/Blockchains/DigitalGoldTests.swift b/swift/Tests/Blockchains/DigitalGoldTests.swift new file mode 100644 index 00000000000..afa62c10593 --- /dev/null +++ b/swift/Tests/Blockchains/DigitalGoldTests.swift @@ -0,0 +1,28 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +import TrustWalletCore +import XCTest + +class DigitalGoldTests: XCTestCase { + // TODO: Check and finalize implementation + + func testAddress() { + // TODO: Check and finalize implementation + + let key = PrivateKey(data: Data(hexString: "__PRIVATE_KEY_DATA__")!)! + let pubkey = key.getPublicKeyEd25519() + let address = AnyAddress(publicKey: pubkey, coin: .digitalgold) + let addressFromString = AnyAddress(string: "__ADDRESS_DATA__", coin: .digitalgold)! + + XCTAssertEqual(pubkey.data.hexString, "__EXPECTED_PUBKEY_DATA__") + XCTAssertEqual(address.description, addressFromString.description) + } + + func testSign() { + // TODO: Create implementation + } +} diff --git a/swift/Tests/Blockchains/ElrondTests.swift b/swift/Tests/Blockchains/ElrondTests.swift new file mode 100644 index 00000000000..c3e3e5b4b8c --- /dev/null +++ b/swift/Tests/Blockchains/ElrondTests.swift @@ -0,0 +1,51 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +import TrustWalletCore +import XCTest + +class ElrondTests: XCTestCase { + + let aliceBech32 = "erd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2fsmsgldz" + let aliceSeedHex = "1a927e2af5306a9bb2ea777f73e06ecc0ac9aaa72fb4ea3fecf659451394cccf" + let alicePubKeyHex = "fd691bb5e85d102687d81079dffce842d4dc328276d2d4c60d8fd1c3433c3293" + let bobBech32 = "erd1cux02zersde0l7hhklzhywcxk4u9n4py5tdxyx7vrvhnza2r4gmq4vw35r" + + func testAddress() { + let key = PrivateKey(data: Data(hexString: aliceSeedHex)!)! + let pubkey = key.getPublicKeyEd25519() + let address = AnyAddress(publicKey: pubkey, coin: .elrond) + let addressFromString = AnyAddress(string: aliceBech32, coin: .elrond)! + + XCTAssertEqual(pubkey.data.hexString, alicePubKeyHex) + XCTAssertEqual(address.description, addressFromString.description) + } + + func testSign() { + let privateKey = PrivateKey(data: Data(hexString: aliceSeedHex)!)! + + let input = ElrondSigningInput.with { + $0.transaction = ElrondTransactionMessage.with { + $0.nonce = 0 + $0.value = "0" + $0.sender = aliceBech32 + $0.receiver = bobBech32 + $0.gasPrice = 200000000000000 + $0.gasLimit = 500000000 + $0.data = "foo" + } + + $0.privateKey = privateKey.data + } + + let output: ElrondSigningOutput = AnySigner.sign(input: input, coin: .elrond) + let expectedSignature = "b88ad2fe98a7316ea432a0a76c18cd87200fe75f27a8f053ea6532b40317dbec5136c5463aef132ae951b7e60d45d921caaa5903e70821dcda98f237d4ec4308" + let expectedEncoded = #"{"nonce":0,"value":"0","receiver":"\#(bobBech32)","sender":"\#(aliceBech32)","gasPrice":200000000000000,"gasLimit":500000000,"data":"foo","signature":"\#(expectedSignature)"}"# + + XCTAssertEqual(output.signature, expectedSignature) + XCTAssertEqual(output.encoded, expectedEncoded) + } +} diff --git a/swift/Tests/Blockchains/IoTeXTests.swift b/swift/Tests/Blockchains/IoTeXTests.swift index 1209db8d4e1..0e68e5ab83f 100644 --- a/swift/Tests/Blockchains/IoTeXTests.swift +++ b/swift/Tests/Blockchains/IoTeXTests.swift @@ -8,7 +8,6 @@ import XCTest import TrustWalletCore class IoTeXTests: XCTestCase { - func testSign() { let privateKey = PrivateKey(data: Data(hexString: "0x68ffa8ec149ce50da647166036555f73d57f662eb420e154621e5f24f6cf9748")!)! @@ -29,81 +28,182 @@ class IoTeXTests: XCTestCase { XCTAssertEqual(output.encoded.hexString, "0a39080110011801220131522e0a01311229696f3165326e7173797437666b707a733578377a6632756b306a6a3732746575356e36616b75337472124104fb30b196ce3e976593ecc2da220dca9cdea8c84d2373770042a930b892ac0f5cf762f20459c9100eb9d4d7597f5817bf21e10b53a0120b9ec1ba5cddfdcb669b1a41ec9757ae6c9009315830faaab250b6db0e9535b00843277f596ae0b2b9efc0bd4e14138c056fc4cdfa285d13dd618052b3d1cb7a3f554722005a2941bfede96601") } - func stakingInput() -> IoTeXSigningInput { - let input = IoTeXSigningInput.with { + func testSignStakingCreate() { + var input = IoTeXSigningInput.with { $0.version = 1 - $0.nonce = 123 - $0.gasLimit = 888 - $0.gasPrice = "999" - $0.staking = IoTeXStaking.with { - $0.amount = "456" - $0.contract = "io1xpq62aw85uqzrccg9y5hnryv8ld2nkpycc3gza" - } - $0.privateKey = Data(hexString: "0806c458b262edd333a191e92f561aff338211ee3e18ab315a074a2d82aa343f")! + $0.nonce = 0 + $0.gasLimit = 1000000 + $0.gasPrice = "10" + $0.privateKey = Data(hexString: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1")! } - return input + input.stakeCreate = IoTeXStaking.Create.with { + $0.candidateName = "io19d0p3ah4g8ww9d7kcxfq87yxe7fnr8rpth5shj" + $0.stakedAmount = "100" + $0.stakedDuration = 10000 + $0.autoStake = true + $0.payload = "payload".data(using: .utf8)! + } + let output: IoTeXSigningOutput = AnySigner.sign(input: input, coin: .ioTeX) + + XCTAssertEqual(output.encoded.hexString, "0a4b080118c0843d22023130c2023e0a29696f313964307033616834673877773964376b63786671383779786537666e7238727074683573686a120331303018904e20012a077061796c6f6164124104755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf331a412e8bac421bab88dcd99c26ac8ffbf27f11ee57a41e7d2537891bfed5aed8e2e026d46e55d1b856787bc1cd7c1216a6e2534c5b5d1097c3afe8e657aa27cbbb0801") + XCTAssertEqual(output.hash.hexString, "f1785e47b4200c752bb6518bd18097a41e075438b8c18c9cb00e1ae2f38ce767") } - func testStake() { - // candidate name is a string - let candidate = "\u{01}\u{02}\u{03}\u{04}\u{05}\u{06}\u{07}\u{08}\t\n\u{0B}\u{0C}" - var input = stakingInput() - input.staking.stake = IoTeXStaking.Stake.with { - $0.candidate = candidate - $0.duration = 1001 - $0.nonDecay = true - $0.data = "this is a test".data(using: .utf8)! + func testSignStakingAddDeposit() { + var input = IoTeXSigningInput.with { + $0.version = 1 + $0.nonce = 0 + $0.gasLimit = 1000000 + $0.gasPrice = "10" + $0.privateKey = Data(hexString: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1")! + } + input.stakeAddDeposit = IoTeXStaking.AddDeposit.with { + $0.bucketIndex = 10 + $0.amount = "10" + $0.payload = "payload".data(using: .utf8)! } let output: IoTeXSigningOutput = AnySigner.sign(input: input, coin: .ioTeX) - XCTAssertEqual(output.encoded.hexString, "0a86020801107b18f806220339393962f7010a033435361229696f3178707136326177383575717a72636367397935686e727976386c64326e6b7079636333677a611ac40107c35fc00102030405060708090a0b0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000e74686973206973206120746573740000000000000000000000000000000000001241044e18306ae9ef4ec9d07bf6e705442d4d1a75e6cdf750330ca2d880f2cc54607c9c33deb9eae9c06e06e04fe9ce3d43962cc67d5aa34fbeb71270d4bad3d648d91a41a558bc9a4bfba920242ccd4d5c5da363ec534d4dd5eb67f88e9db7aaad5c50ad62dfe298c0e54e311ebba045f48cea1136e42a123a8e6b03d3e6ed82d4ec2b9401") - XCTAssertEqual(output.hash.hexString, "41b1f8be5f6b884c06556fba2611716e8e514b507f5a653fc02ac50ba13fbd6c") + XCTAssertEqual(output.encoded.hexString, "0a1c080118c0843d22023130da020f080a120231301a077061796c6f6164124104755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf331a41a48ab1feba8181d760de946aefed7d815a89fd9b1ab503d2392bb55e1bb75eec42dddc8bd642f89accc3a37b3cf15a103a95d66695fdf0647b202869fdd66bcb01") + XCTAssertEqual(output.hash.hexString, "ca8937d6f224a4e4bf93cb5605581de2d26fb0481e1dfc1eef384ee7ccf94b73") } + + func testSignStakingUnstake() { + var input = IoTeXSigningInput.with { + $0.version = 1 + $0.nonce = 0 + $0.gasLimit = 1000000 + $0.gasPrice = "10" + $0.privateKey = Data(hexString: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1")! + } + input.stakeUnstake = IoTeXStaking.Reclaim.with { + $0.bucketIndex = 10 + $0.payload = "payload".data(using: .utf8)! + } + let output: IoTeXSigningOutput = AnySigner.sign(input: input, coin: .ioTeX) - func testUnstake() { - var input = stakingInput() - input.staking.unstake = IoTeXStaking.Unstake.with { - $0.piggyIndex = 1001 + XCTAssertEqual(output.encoded.hexString, "0a18080118c0843d22023130ca020b080a12077061796c6f6164124104755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf331a4100adee39b48e1d3dbbd65298a57c7889709fc4df39987130da306f6997374a184b7e7c232a42f21e89b06e6e7ceab81303c6b7483152d08d19ac829b22eb81e601") + XCTAssertEqual(output.hash.hexString, "bed58b64a6c4e959eca60a86f0b2149ce0e1dd527ac5fd26aef725ebf7c22a7d") + } + + func testSignStakingWithdraw() { + var input = IoTeXSigningInput.with { + $0.version = 1 + $0.nonce = 0 + $0.gasLimit = 1000000 + $0.gasPrice = "10" + $0.privateKey = Data(hexString: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1")! + } + input.stakeWithdraw = IoTeXStaking.Reclaim.with { + $0.bucketIndex = 10 + $0.payload = "payload".data(using: .utf8)! } let output: IoTeXSigningOutput = AnySigner.sign(input: input, coin: .ioTeX) - XCTAssertEqual(output.encoded.hexString, "0aa5010801107b18f80622033939396296010a033435361229696f3178707136326177383575717a72636367397935686e727976386c64326e6b7079636333677a611a64c8fd6ed000000000000000000000000000000000000000000000000000000000000003e9000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000001241044e18306ae9ef4ec9d07bf6e705442d4d1a75e6cdf750330ca2d880f2cc54607c9c33deb9eae9c06e06e04fe9ce3d43962cc67d5aa34fbeb71270d4bad3d648d91a41eeb7cb3fa7ec22a61156753d569b3f4da3c74c3c7e2f148b1a43e11d220cac5d164663ff6c785439679b088de9d7f2437545f007ca9cda4b2f5327d2c6eda5aa01") - XCTAssertEqual(output.hash.hexString, "b93a2874a72ce4eb8a41a20c209cf3fd188671ed8be8239a57960cbed887e962") + XCTAssertEqual(output.encoded.hexString, "0a18080118c0843d22023130d2020b080a12077061796c6f6164124104755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf331a4152644d102186be6640d46b517331f3402e24424b0d85129595421d28503d75340b2922f5a0d4f667bbd6f576d9816770286b2ce032ba22eaec3952e24da4756b00") + XCTAssertEqual(output.hash.hexString, "28049348cf34f1aa927caa250e7a1b08778c44efaf73b565b6fa9abe843871b4") } - func testWithdraw() { - var input = stakingInput() - input.staking.withdraw = IoTeXStaking.Withdraw.with { - $0.piggyIndex = 1001 + func testSignStakingRestake() { + var input = IoTeXSigningInput.with { + $0.version = 1 + $0.nonce = 0 + $0.gasLimit = 1000000 + $0.gasPrice = "10" + $0.privateKey = Data(hexString: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1")! + } + input.stakeRestake = IoTeXStaking.Restake.with { + $0.bucketIndex = 10 + $0.stakedDuration = 1000 + $0.autoStake = true + $0.payload = "payload".data(using: .utf8)! } let output: IoTeXSigningOutput = AnySigner.sign(input: input, coin: .ioTeX) - XCTAssertEqual(output.encoded.hexString, "0aa5010801107b18f80622033939396296010a033435361229696f3178707136326177383575717a72636367397935686e727976386c64326e6b7079636333677a611a64030ba25d00000000000000000000000000000000000000000000000000000000000003e9000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000001241044e18306ae9ef4ec9d07bf6e705442d4d1a75e6cdf750330ca2d880f2cc54607c9c33deb9eae9c06e06e04fe9ce3d43962cc67d5aa34fbeb71270d4bad3d648d91a41903c79d042f6b1c05446ececb3d760ca154c539b5787e66135cd3db77638294d18dbbbbcb0de8b9a393cc7c0448cf246898e4343a2a51666e21e738ee6d8a6f700") - XCTAssertEqual(output.hash.hexString, "2b2657247a72cb262de214b4e793c7a01fa2139fd5d12a46d43c24f87f9e2396") + XCTAssertEqual(output.encoded.hexString, "0a1d080118c0843d22023130e20210080a10e807180122077061796c6f6164124104755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf331a41e2e763aed5b1fd1a8601de0f0ae34eb05162e34b0389ae3418eedbf762f64959634a968313a6516dba3a97b34efba4753bbed3a33d409ecbd45ac75007cd8e9101") + XCTAssertEqual(output.hash.hexString, "8816e8f784a1fce40b54d1cd172bb6976fd9552f1570c73d1d9fcdc5635424a9") } - func testAddStake() { - var input = stakingInput() - input.staking.addStake = IoTeXStaking.AddStake.with { - $0.piggyIndex = 1001 + func testSignStakingChangeCandidate() { + var input = IoTeXSigningInput.with { + $0.version = 1 + $0.nonce = 0 + $0.gasLimit = 1000000 + $0.gasPrice = "10" + $0.privateKey = Data(hexString: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1")! + } + input.stakeChangeCandidate = IoTeXStaking.ChangeCandidate.with { + $0.bucketIndex = 10 + $0.candidateName = "io1xpq62aw85uqzrccg9y5hnryv8ld2nkpycc3gza" + $0.payload = "payload".data(using: .utf8)! + } + let output: IoTeXSigningOutput = AnySigner.sign(input: input, coin: .ioTeX) + + XCTAssertEqual(output.encoded.hexString, "0a43080118c0843d22023130ea0236080a1229696f3178707136326177383575717a72636367397935686e727976386c64326e6b7079636333677a611a077061796c6f6164124104755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf331a41d519eb3747163b945b862989b7e82a7f8468001e9683757cb88d5ddd95f81895047429e858bd48f7d59a88bfec92de231d216293aeba1e4fbe11461d9c9fc99801") + XCTAssertEqual(output.hash.hexString, "186526b5b9fe74e25beb52c83c41780a69108160bef2ddaf3bffb9f1f1e5e73a") + } + + func testSignStakingTransfer() { + var input = IoTeXSigningInput.with { + $0.version = 1 + $0.nonce = 0 + $0.gasLimit = 1000000 + $0.gasPrice = "10" + $0.privateKey = Data(hexString: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1")! + } + input.stakeTransferOwnership = IoTeXStaking.TransferOwnership.with { + $0.bucketIndex = 10 + $0.voterAddress = "io1xpq62aw85uqzrccg9y5hnryv8ld2nkpycc3gza" + $0.payload = "payload".data(using: .utf8)! + } + let output: IoTeXSigningOutput = AnySigner.sign(input: input, coin: .ioTeX) + + XCTAssertEqual(output.encoded.hexString, "0a43080118c0843d22023130f20236080a1229696f3178707136326177383575717a72636367397935686e727976386c64326e6b7079636333677a611a077061796c6f6164124104755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf331a41fa26db427ab87a56a129196c1604f2e22c4dd2a1f99b2217bc916260757d00093d9e6dccdf53e3b0b64e41a69d71c238fbf9281625164694a74dfbeba075d0ce01") + XCTAssertEqual(output.hash.hexString, "74b2e1d6a09ba5d1298fa422d5850991ae516865077282196295a38f93c78b85") + } + + func testSignCandidateRegister() { + var input = IoTeXSigningInput.with { + $0.version = 1 + $0.nonce = 0 + $0.gasLimit = 1000000 + $0.gasPrice = "1000" + $0.privateKey = Data(hexString: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1")! + } + input.candidateRegister = IoTeXStaking.CandidateRegister.with { + $0.candidate = IoTeXStaking.CandidateBasicInfo.with { + $0.name = "test" + $0.operatorAddress = "io10a298zmzvrt4guq79a9f4x7qedj59y7ery84he" + $0.rewardAddress = "io13sj9mzpewn25ymheukte4v39hvjdtrfp00mlyv" + } + $0.stakedAmount = "100" + $0.stakedDuration = 10000 + $0.autoStake = false + $0.ownerAddress = "io19d0p3ah4g8ww9d7kcxfq87yxe7fnr8rpth5shj" + $0.payload = "payload".data(using: .utf8)! } let output: IoTeXSigningOutput = AnySigner.sign(input: input, coin: .ioTeX) - XCTAssertEqual(output.encoded.hexString, "0aa5010801107b18f80622033939396296010a033435361229696f3178707136326177383575717a72636367397935686e727976386c64326e6b7079636333677a611a646e7b301700000000000000000000000000000000000000000000000000000000000003e9000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000001241044e18306ae9ef4ec9d07bf6e705442d4d1a75e6cdf750330ca2d880f2cc54607c9c33deb9eae9c06e06e04fe9ce3d43962cc67d5aa34fbeb71270d4bad3d648d91a410f0832bb7a48c9e468c0bcb2c4a35a202f9519a63c4d6474b48087ab9dc33aea18127940d5cda43710cd874cbdf7a7b26efc9c04236e14dfb4d9b6f7095b0b6c01") - XCTAssertEqual(output.hash.hexString, "c71058812a5febe5cdcdaf9499ba0b2c895f88d1acd3203e5097b307c2a5f1d1") + XCTAssertEqual(output.encoded.hexString, "0aaa01080118c0843d220431303030fa029a010a5c0a04746573741229696f3130613239387a6d7a7672743467757137396139663478377165646a35397937657279383468651a29696f3133736a396d7a7065776e3235796d6865756b74653476333968766a647472667030306d6c7976120331303018904e2a29696f313964307033616834673877773964376b63786671383779786537666e7238727074683573686a32077061796c6f6164124104755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf331a417819b5bcb635e3577acc8ca757f2c3d6afa451c2b6ff8a9179b141ac68e2c50305679e5d09d288da6f0fb52876a86c74deab6a5247edc6d371de5c2f121e159400") + XCTAssertEqual(output.hash.hexString, "35f53a536e014b32b85df50483ef04849b80ad60635b3b1979c5ba1096b65237") } - func testMoveStake() { - // candidate name is a string - let candidate = "\u{01}\u{02}\u{03}\u{04}\u{05}\u{06}\u{07}\u{08}\t\n\u{0B}\u{0C}" - var input = stakingInput() - input.staking.moveStake = IoTeXStaking.MoveStake.with { - $0.piggyIndex = 1001 - $0.candidate = candidate + func testSignCandidateUpdate() { + var input = IoTeXSigningInput.with { + $0.version = 1 + $0.nonce = 0 + $0.gasLimit = 1000000 + $0.gasPrice = "10" + $0.privateKey = Data(hexString: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1")! + } + input.candidateUpdate = IoTeXStaking.CandidateBasicInfo.with { + $0.name = "test" + $0.operatorAddress = "io1cl6rl2ev5dfa988qmgzg2x4hfazmp9vn2g66ng" + $0.rewardAddress = "io1juvx5g063eu4ts832nukp4vgcwk2gnc5cu9ayd" } let output: IoTeXSigningOutput = AnySigner.sign(input: input, coin: .ioTeX) - XCTAssertEqual(output.encoded.hexString, "0ac6010801107b18f806220339393962b7010a033435361229696f3178707136326177383575717a72636367397935686e727976386c64326e6b7079636333677a611a8401d3e41fd200000000000000000000000000000000000000000000000000000000000003e90102030405060708090a0b0c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000001241044e18306ae9ef4ec9d07bf6e705442d4d1a75e6cdf750330ca2d880f2cc54607c9c33deb9eae9c06e06e04fe9ce3d43962cc67d5aa34fbeb71270d4bad3d648d91a4118b71944993d1cd5362379ff64e892024a75ce697b2755cc9bbfcac24482a19b1ec2951bec7461ef9eb0723f803987cb87e3c3afb340006cd5b413c1fac10d7c01") - XCTAssertEqual(output.hash.hexString, "33290ded342efaebf795855be73d34cbac149a2415ff9558de10303e6126f30d") + XCTAssertEqual(output.encoded.hexString, "0a69080118c0843d2202313082035c0a04746573741229696f31636c36726c32657635646661393838716d677a673278346866617a6d7039766e326736366e671a29696f316a757678356730363365753474733833326e756b7034766763776b32676e6335637539617964124104755ce6d8903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a1038ed9da8daf331a4101885c9c6684a4a8f2f5bf11f8326f27be48658f292e8f55ec8a11a604bb0c563a11ebf12d995ca1c152e00f8e0f0edf288db711aa10dbdfd5b7d73b4a28e1f701") + XCTAssertEqual(output.hash.hexString, "ca1a28f0e9a58ffc67037cc75066dbdd8e024aa2b2e416e4d6ce16c3d86282e5") } -} +} \ No newline at end of file diff --git a/swift/Tests/CoinAddressDerivationTests.swift b/swift/Tests/CoinAddressDerivationTests.swift index 81b55b548ed..2a09ac50169 100644 --- a/swift/Tests/CoinAddressDerivationTests.swift +++ b/swift/Tests/CoinAddressDerivationTests.swift @@ -190,6 +190,9 @@ class CoinAddressDerivationTests: XCTestCase { case .filecoin: let expectedResult = "f1zzykebxldfcakj5wdb5n3n7priul522fnmjzori" AssetCoinDerivation(coin, expectedResult, derivedAddress, address) + case .elrond: + let expectedResult = "erd1jfcy8aeru6vlx4fe6h3pc3vlpe2cnnur5zetxdhp879yagq7vqvs8na4f8" + AssetCoinDerivation(coin, expectedResult, derivedAddress, address) @unknown default: fatalError() } diff --git a/swift/Tests/Keystore/AccountTests.swift b/swift/Tests/Keystore/AccountTests.swift index 7d1d184173f..8fa934e9e11 100755 --- a/swift/Tests/Keystore/AccountTests.swift +++ b/swift/Tests/Keystore/AccountTests.swift @@ -9,7 +9,7 @@ import XCTest class AccountTests: XCTestCase { let words = "ripple scissors kick mammal hire column oak again sun offer wealth tomorrow wagon turn fatal" - let password = "password" + let password = Data("password".utf8) func testSignHash() throws { let privateKeyData = Data(hexString: "D30519BCAE8D180DBFCC94FE0B8383DC310185B0BE97B4365083EBCECCD75759")! @@ -42,9 +42,10 @@ class AccountTests: XCTestCase { func testExtendedPubkey() throws { let key = StoredKey.importHDWallet(mnemonic: words, name: "name", password: password, coin: .ethereum)! let wallet = Wallet(keyURL: URL(fileURLWithPath: "/"), key: key) - _ = try wallet.getAccount(password: password, coin: .bitcoin) - _ = try wallet.getAccount(password: password, coin: .bitcoinCash) - _ = try wallet.getAccount(password: password, coin: .ethereumClassic) + let stringPass = String(data: password, encoding: .utf8)! + _ = try wallet.getAccount(password: stringPass, coin: .bitcoin) + _ = try wallet.getAccount(password: stringPass, coin: .bitcoinCash) + _ = try wallet.getAccount(password: stringPass, coin: .ethereumClassic) XCTAssertEqual(wallet.accounts[0].extendedPublicKey, "") XCTAssertEqual(wallet.accounts[1].extendedPublicKey, "zpub6rNUNtxSa9Gxvm4Bdxf1MPMwrvkzwDx6vP96Hkzw3jiQKdg3fhXBStxjn12YixQB8h88B3RMSRscRstf9AEVaYr3MAqVBEWBDuEJU4PGaT9") diff --git a/swift/Tests/Keystore/KeyStoreTests.swift b/swift/Tests/Keystore/KeyStoreTests.swift index 928f5194345..f4e56822dd6 100755 --- a/swift/Tests/Keystore/KeyStoreTests.swift +++ b/swift/Tests/Keystore/KeyStoreTests.swift @@ -90,7 +90,7 @@ class KeyStoreTests: XCTestCase { let savedKeyStore = try KeyStore(keyDirectory: keyDirectory) let savedWallet = savedKeyStore.wallets.first(where: { $0 == wallet })! - let data = savedWallet.key.decryptPrivateKey(password: "testpassword") + let data = savedWallet.key.decryptPrivateKey(password: Data("testpassword".utf8)) let mnemonic = String(data: data!, encoding: .ascii) XCTAssertEqual(savedWallet.accounts.count, coins.count) @@ -110,7 +110,7 @@ class KeyStoreTests: XCTestCase { let savedKeyStore = try KeyStore(keyDirectory: keyDirectory) let savedWallet = savedKeyStore.wallets.first(where: { $0 == wallet })! - let data = savedWallet.key.decryptPrivateKey(password: "password") + let data = savedWallet.key.decryptPrivateKey(password: Data("password".utf8)) let mnemonic = String(data: data!, encoding: .ascii) XCTAssertEqual(savedWallet.accounts.count, coins.count) @@ -160,11 +160,11 @@ class KeyStoreTests: XCTestCase { func testImportKey() throws { let keyStore = try KeyStore(keyDirectory: keyDirectory) let privateKeyData = Data(hexString: "9cdb5cab19aec3bd0fcd614c5f185e7a1d97634d4225730eba22497dc89a716c")! - let key = StoredKey.importPrivateKey(privateKey: privateKeyData, name: "name", password: "password", coin: .ethereum)! + let key = StoredKey.importPrivateKey(privateKey: privateKeyData, name: "name", password: Data("password".utf8), coin: .ethereum)! let json = key.exportJSON()! let wallet = try keyStore.import(json: json, name: "name", password: "password", newPassword: "newPassword", coins: [.ethereum]) - let storedData = wallet.key.decryptPrivateKey(password: "newPassword") + let storedData = wallet.key.decryptPrivateKey(password: Data("newPassword".utf8)) XCTAssertNotNil(keyStore.keyWallet) XCTAssertNotNil(storedData) @@ -176,7 +176,7 @@ class KeyStoreTests: XCTestCase { let privateKey = PrivateKey(data: Data(hexString: "9cdb5cab19aec3bd0fcd614c5f185e7a1d97634d4225730eba22497dc89a716c")!)! let wallet = try keyStore.import(privateKey: privateKey, name: "name", password: "password", coin: .ethereum) - let storedData = wallet.key.decryptPrivateKey(password: "password") + let storedData = wallet.key.decryptPrivateKey(password: Data("password".utf8)) XCTAssertNotNil(storedData) XCTAssertNotNil(PrivateKey(data: storedData!)) @@ -189,7 +189,7 @@ class KeyStoreTests: XCTestCase { func testImportWallet() throws { let keyStore = try KeyStore(keyDirectory: keyDirectory) let wallet = try keyStore.import(mnemonic: mnemonic, name: "name", encryptPassword: "newPassword", coins: [.ethereum]) - let storedData = wallet.key.decryptMnemonic(password: "newPassword") + let storedData = wallet.key.decryptMnemonic(password: Data("newPassword".utf8)) XCTAssertNotNil(storedData) XCTAssertEqual(wallet.accounts.count, 1) diff --git a/swift/Tests/Keystore/KeystoreKeyTests.swift b/swift/Tests/Keystore/KeystoreKeyTests.swift index 580a1f8dae1..cad779e3105 100755 --- a/swift/Tests/Keystore/KeystoreKeyTests.swift +++ b/swift/Tests/Keystore/KeystoreKeyTests.swift @@ -25,21 +25,21 @@ class KeystoreKeyTests: XCTestCase { let url = Bundle(for: type(of: self)).url(forResource: "key", withExtension: "json")! let key = StoredKey.load(path: url.path)! - XCTAssertNil(key.decryptPrivateKey(password: "password")) + XCTAssertNil(key.decryptPrivateKey(password: Data("password".utf8))) } func testDecrypt() { let url = Bundle(for: type(of: self)).url(forResource: "key", withExtension: "json")! let key = StoredKey.load(path: url.path)! - let privateKey = key.decryptPrivateKey(password: "testpassword")! + let privateKey = key.decryptPrivateKey(password: Data("testpassword".utf8))! XCTAssertEqual(privateKey.hexString, "7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d") } func testCreateWallet() { let privateKeyData = Data(hexString: "3a1076bf45ab87712ad64ccb3b10217737f7faacbf2872e88fdd9a537d8fe266")! - let key = StoredKey.importPrivateKey(privateKey: privateKeyData, name: "name", password: "password", coin: .ethereum)! - let decrypted = key.decryptPrivateKey(password: "password")! + let key = StoredKey.importPrivateKey(privateKey: privateKeyData, name: "name", password: Data("password".utf8), coin: .ethereum)! + let decrypted = key.decryptPrivateKey(password: Data("password".utf8))! XCTAssertEqual(decrypted.hexString, privateKeyData.hexString) } @@ -59,4 +59,64 @@ class KeystoreKeyTests: XCTestCase { XCTAssertEqual(account.address.description, "3PWazDi9n1Hfyq9gXFxDxzADNL8RNYyK2y") } + + func testLongHexPassword() { + let json = """ + { + "address": "34bae2218c254ed190c0f5b1dd4323aee8e7da09", + "id": "86066d8c-8dba-4d81-afd4-934e2a2b72a2", + "version": 3, + "crypto": { + "cipher": "aes-128-ctr", + "cipherparams": { + "iv": "a4976ad73057007ad788d1f792db851d" + }, + "ciphertext": "5e4458d69964172c492616b751d6589b4ad7da4217dcfccecc3f4e515a934bb8", + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "n": 4096, + "p": 6, + "r": 8, + "salt": "24c72d92bf88a4f7c7b3f5e3cb3620714d71fceabbb0bc6099f50c6d5d898e7c" + }, + "mac": "c15e3035ddcaca766dfc56648978d33e94d3c57d4a5e13fcf8b5f8dbb0902900" + } + } + """.data(using: .utf8)! + let keystore = StoredKey.importJSON(json: json)! + let password = Data(hexString: "2d6eefbfbd4622efbfbdefbfbd516718efbfbdefbfbdefbfbdefbfbd59efbfbd30efbfbdefbfbd3a4348efbfbd2aefbfbdefbfbd49efbfbd27efbfbd0638efbfbdefbfbdefbfbd4cefbfbd6befbfbdefbfbd6defbfbdefbfbd63efbfbd5aefbfbd61262b70efbfbdefbfbdefbfbdefbfbdefbfbdc7aa373163417cefbfbdefbfbdefbfbd44efbfbdefbfbd1d10efbfbdefbfbdefbfbd61dc9e5b124befbfbd11efbfbdefbfbd2fefbfbdefbfbd3d7c574868efbfbdefbfbdefbfbd37043b7b5c1a436471592f02efbfbd18efbfbdefbfbd2befbfbdefbfbd7218efbfbd6a68efbfbdcb8e5f3328773ec48174efbfbd67efbfbdefbfbdefbfbdefbfbdefbfbd2a31efbfbd7f60efbfbdd884efbfbd57efbfbd25efbfbd590459efbfbd37efbfbd2bdca20fefbfbdefbfbdefbfbdefbfbd39450113efbfbdefbfbdefbfbd454671efbfbdefbfbdd49fefbfbd47efbfbdefbfbdefbfbdefbfbd00efbfbdefbfbdefbfbdefbfbd05203f4c17712defbfbd7bd1bbdc967902efbfbdc98a77efbfbd707a36efbfbd12efbfbdefbfbd57c78cefbfbdefbfbdefbfbd10efbfbdefbfbdefbfbde1a1bb08efbfbdefbfbd26efbfbdefbfbd58efbfbdefbfbdc4b1efbfbd295fefbfbd0eefbfbdefbfbdefbfbd0e6eefbfbd")! + let data = keystore.decryptPrivateKey(password: password) + XCTAssertEqual(data?.hexString, "043c5429c7872502531708ec0d821c711691402caf37ef7ba78a8c506f10653b") + } + + func testLongPassword() { + let json = """ + { + "address": "b92bcd5b14d2d70651d483c8f03bae79223b88ec", + "id": "480fc670-e5e6-4b39-ba33-61f54ce792f9", + "version": 3, + "crypto": { + "cipher": "aes-128-ctr", + "cipherparams": { + "iv": "5d88369e4306bcc98e1fe70e7710f3a0" + }, + "ciphertext": "de9bac5d1ca94cdd067a51275a56f0766ed3631de108609ee240c42a0994f97e", + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "n": 4096, + "p": 6, + "r": 8, + "salt": "3849479dd4880793cfd92ebfeb30c60dccf04f3f76a2778fe89bead4237ddad4" + }, + "mac": "361df97ff456009849ab1ffd4e71b61d7e66c9d2071c5a7563d1bbbdb0b2653b" + } + } + """.data(using: .utf8)! + let keystore = StoredKey.importJSON(json: json)! + let password = "2d6eefbfbd4622efbfbdefbfbd516718efbfbdefbfbdefbfbdefbfbd59efbfbd30efbfbdefbfbd3a4348efbfbd2aefbfbdefbfbd49efbfbd27efbfbd0638efbfbdefbfbdefbfbd4cefbfbd6befbfbdefbfbd6defbfbdefbfbd63efbfbd5aefbfbd61262b70efbfbdefbfbdefbfbdefbfbdefbfbdc7aa373163417cefbfbdefbfbdefbfbd44efbfbdefbfbd1d10efbfbdefbfbdefbfbd61dc9e5b124befbfbd11efbfbdefbfbd2fefbfbdefbfbd3d7c574868efbfbdefbfbdefbfbd37043b7b5c1a436471592f02efbfbd18efbfbdefbfbd2befbfbdefbfbd7218efbfbd6a68efbfbdcb8e5f3328773ec48174efbfbd67efbfbdefbfbdefbfbdefbfbdefbfbd2a31efbfbd7f60efbfbdd884efbfbd57efbfbd25efbfbd590459efbfbd37efbfbd2bdca20fefbfbdefbfbdefbfbdefbfbd39450113efbfbdefbfbdefbfbd454671efbfbdefbfbdd49fefbfbd47efbfbdefbfbdefbfbdefbfbd00efbfbdefbfbdefbfbdefbfbd05203f4c17712defbfbd7bd1bbdc967902efbfbdc98a77efbfbd707a36efbfbd12efbfbdefbfbd57c78cefbfbdefbfbdefbfbd10efbfbdefbfbdefbfbde1a1bb08efbfbdefbfbd26efbfbdefbfbd58efbfbdefbfbdc4b1efbfbd295fefbfbd0eefbfbdefbfbdefbfbd0e6eefbfbd".data(using: .utf8)! + let data = keystore.decryptPrivateKey(password: password) + XCTAssertEqual(data?.hexString, "4357b2f9a6150ba969bc52f01c98cce5313595fe49f2d08303759c73e5c7a46c") + } } diff --git a/swift/Tests/Keystore/WalletTests.swift b/swift/Tests/Keystore/WalletTests.swift index 983797344cc..6b31424870e 100755 --- a/swift/Tests/Keystore/WalletTests.swift +++ b/swift/Tests/Keystore/WalletTests.swift @@ -21,7 +21,7 @@ class WalletTests: XCTestCase { func testIdentifier() throws { let url = URL(string: "UTC--2018-07-23T15-42-07.380692005-42000--6E199F01-FA96-4ADF-9A4B-36EE4B1E08C7")! - let key = StoredKey(name: "name", password: "password") + let key = StoredKey(name: "name", password: Data("password".utf8)) let wallet = Wallet(keyURL: url, key: key) XCTAssertEqual(wallet.identifier, "UTC--2018-07-23T15-42-07.380692005-42000--6E199F01-FA96-4ADF-9A4B-36EE4B1E08C7") } diff --git a/swift/cpp.xcconfig.in b/swift/cpp.xcconfig.in index 9d351112b5b..9e2fd5ef152 100644 --- a/swift/cpp.xcconfig.in +++ b/swift/cpp.xcconfig.in @@ -5,4 +5,4 @@ // file LICENSE at the root of the source code distribution tree. HEADER_SEARCH_PATHS = $(SRCROOT)/../src @Boost_INCLUDE_DIRS@ -SYSTEM_HEADER_SEARCH_PATHS = $(SRCROOT)/../src/build/local/include $(SRCROOT)/../build/protobuf/staging/protobuf-3.9.0/src +SYSTEM_HEADER_SEARCH_PATHS = $(SRCROOT)/../src/build/local/include $(SRCROOT)/../build/local/src/protobuf/protobuf-3.9.0/src diff --git a/swift/protobuf b/swift/protobuf index 42dacc8e080..b0c567bc5a1 120000 --- a/swift/protobuf +++ b/swift/protobuf @@ -1 +1 @@ -../build/protobuf/staging/protobuf-3.9.0/src \ No newline at end of file +../build/local/src/protobuf/protobuf-3.9.0/src \ No newline at end of file diff --git a/tests/Bech32AddressTests.cpp b/tests/Bech32AddressTests.cpp index ff425cb7c4f..4b6024ecd5e 100644 --- a/tests/Bech32AddressTests.cpp +++ b/tests/Bech32AddressTests.cpp @@ -27,6 +27,10 @@ TEST(Bech32Address, Valid) { ASSERT_TRUE(Bech32Address::isValid("io187wzp08vnhjjpkydnr97qlh8kh0dpkkytfam8j", "io")); ASSERT_TRUE(Bech32Address::isValid("zil1fwh4ltdguhde9s7nysnp33d5wye6uqpugufkz7", "zil")); + + ASSERT_TRUE(Bech32Address::isValid("erd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2fsmsgldz", "erd")); + ASSERT_TRUE(Bech32Address::isValid("erd1cux02zersde0l7hhklzhywcxk4u9n4py5tdxyx7vrvhnza2r4gmq4vw35r", "erd")); + ASSERT_TRUE(Bech32Address::isValid("erd19nu5t7hszckwah5nlcadmk5rlchtugzplznskffpwecygcu0520s9tnyy0", "erd")); } TEST(Bech32Address, Invalid) { @@ -48,6 +52,10 @@ TEST(Bech32Address, Invalid) { ASSERT_FALSE(Bech32Address::isValid("")); ASSERT_FALSE(Bech32Address::isValid("0x")); ASSERT_FALSE(Bech32Address::isValid("91cddcebe846ce4d47712287eee53cf17c2cfb7")); + + ASSERT_FALSE(Bech32Address::isValid("", "erd")); + ASSERT_FALSE(Bech32Address::isValid("erd1cux02zersde0l7hhklzhywcxk4u9n4py5tdxyx7vrvhnza2r4gmq4vw35!", "erd")); + ASSERT_FALSE(Bech32Address::isValid("xerd19nu5t7hszckwah5nlcadmk5rlchtugzplznskffpwecygcu0520s9tnyy0", "erd")); } TEST(Bech32Address, InvalidWrongPrefix) { diff --git a/tests/Bitcoin/BitcoinScriptTests.cpp b/tests/Bitcoin/BitcoinScriptTests.cpp new file mode 100644 index 00000000000..c54505e9894 --- /dev/null +++ b/tests/Bitcoin/BitcoinScriptTests.cpp @@ -0,0 +1,285 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#include "Bitcoin/Script.h" +#include "../interface/TWTestUtilities.h" +#include "HexCoding.h" + +#include + +using namespace TW; +using namespace TW::Bitcoin; + +const Script PayToScriptHash(parse_hex("a914" "4733f37cf4db86fbc2efed2500b4f4e49f312023" "87")); +const Script PayToWitnessScriptHash(parse_hex("0020" "ff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3db")); +const Script PayToWitnessPublicKeyHash(parse_hex("0014" "79091972186c449eb1ded22b78e40d009bdf0089")); +const Script PayToPublicKeySecp256k1(parse_hex("21" "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432" "ac")); +const Script PayToPublicKeySecp256k1Extended(parse_hex("41" "0499c6f51ad6f98c9c583f8e92bb7758ab2ca9a04110c0a1126ec43e5453d196c1" "66b489a4b7c491e7688e6ebea3a71fc3a1a48d60f98d5ce84c93b65e423fde91ac")); +const Script PayToPublicKeyHash(parse_hex("76a914" "79091972186c449eb1ded22b78e40d009bdf0089" "88ac")); + +TEST(BitcoinScript, PayToPublicKey) { + Data res; + EXPECT_EQ(PayToPublicKeySecp256k1.matchPayToPublicKey(res), true); + EXPECT_EQ(hex(res), "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432"); + EXPECT_EQ(PayToPublicKeySecp256k1Extended.matchPayToPublicKey(res), true); + EXPECT_EQ(hex(res), "0499c6f51ad6f98c9c583f8e92bb7758ab2ca9a04110c0a1126ec43e5453d196c1"); + + EXPECT_EQ(PayToScriptHash.matchPayToPublicKey(res), false); + EXPECT_EQ(PayToWitnessScriptHash.matchPayToPublicKey(res), false); + EXPECT_EQ(PayToWitnessPublicKeyHash.matchPayToPublicKey(res), false); + EXPECT_EQ(PayToPublicKeyHash.matchPayToPublicKey(res), false); +} + +TEST(BitcoinScript, PayToPublicKeyHash) { + Data res; + EXPECT_EQ(PayToPublicKeyHash.matchPayToPublicKeyHash(res), true); + EXPECT_EQ(hex(res), "79091972186c449eb1ded22b78e40d009bdf0089"); + EXPECT_EQ(PayToPublicKeySecp256k1.matchPayToPublicKey(res), true); + EXPECT_EQ(hex(res), "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432"); + EXPECT_EQ(PayToPublicKeySecp256k1Extended.matchPayToPublicKey(res), true); + EXPECT_EQ(hex(res), "0499c6f51ad6f98c9c583f8e92bb7758ab2ca9a04110c0a1126ec43e5453d196c1"); + + EXPECT_EQ(PayToScriptHash.matchPayToPublicKeyHash(res), false); + EXPECT_EQ(PayToWitnessScriptHash.matchPayToPublicKeyHash(res), false); + EXPECT_EQ(PayToWitnessPublicKeyHash.matchPayToPublicKeyHash(res), false); +} + +TEST(BitcoinScript, PayToScriptHash) { + EXPECT_EQ(PayToScriptHash.isPayToScriptHash(), true); + EXPECT_EQ(PayToScriptHash.bytes.size(), 23); + + EXPECT_EQ(PayToWitnessScriptHash.isPayToScriptHash(), false); + EXPECT_EQ(PayToWitnessPublicKeyHash.isPayToScriptHash(), false); + EXPECT_EQ(PayToPublicKeySecp256k1.isPayToScriptHash(), false); + EXPECT_EQ(PayToPublicKeySecp256k1Extended.isPayToScriptHash(), false); + EXPECT_EQ(PayToPublicKeyHash.isPayToScriptHash(), false); + + Data res; + EXPECT_EQ(PayToScriptHash.matchPayToScriptHash(res), true); + EXPECT_EQ(hex(res), "4733f37cf4db86fbc2efed2500b4f4e49f312023"); + + EXPECT_EQ(PayToWitnessScriptHash.matchPayToScriptHash(res), false); + EXPECT_EQ(PayToWitnessPublicKeyHash.matchPayToScriptHash(res), false); + EXPECT_EQ(PayToPublicKeySecp256k1.matchPayToScriptHash(res), false); + EXPECT_EQ(PayToPublicKeySecp256k1Extended.matchPayToScriptHash(res), false); + EXPECT_EQ(PayToPublicKeyHash.matchPayToScriptHash(res), false); +} + +TEST(BitcoinScript, PayToWitnessScriptHash) { + EXPECT_EQ(PayToWitnessScriptHash.isPayToWitnessScriptHash(), true); + EXPECT_EQ(PayToWitnessScriptHash.bytes.size(), 34); + + EXPECT_EQ(PayToScriptHash.isPayToWitnessScriptHash(), false); + EXPECT_EQ(PayToWitnessPublicKeyHash.isPayToWitnessScriptHash(), false); + EXPECT_EQ(PayToPublicKeySecp256k1.isPayToWitnessScriptHash(), false); + EXPECT_EQ(PayToPublicKeySecp256k1Extended.isPayToWitnessScriptHash(), false); + EXPECT_EQ(PayToPublicKeyHash.isPayToWitnessScriptHash(), false); + + Data res; + EXPECT_EQ(PayToWitnessScriptHash.matchPayToWitnessScriptHash(res), true); + EXPECT_EQ(hex(res), "ff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3db"); + + EXPECT_EQ(PayToScriptHash.matchPayToWitnessScriptHash(res), false); + EXPECT_EQ(PayToWitnessPublicKeyHash.matchPayToWitnessScriptHash(res), false); + EXPECT_EQ(PayToPublicKeySecp256k1.matchPayToWitnessScriptHash(res), false); + EXPECT_EQ(PayToPublicKeySecp256k1Extended.matchPayToWitnessScriptHash(res), false); + EXPECT_EQ(PayToPublicKeyHash.matchPayToWitnessScriptHash(res), false); +} + +TEST(BitcoinScript, PayToWitnessPublicKeyHash) { + EXPECT_EQ(PayToWitnessPublicKeyHash.isPayToWitnessPublicKeyHash(), true); + EXPECT_EQ(PayToWitnessPublicKeyHash.bytes.size(), 22); + + EXPECT_EQ(PayToScriptHash.isPayToWitnessPublicKeyHash(), false); + EXPECT_EQ(PayToWitnessScriptHash.isPayToWitnessPublicKeyHash(), false); + EXPECT_EQ(PayToPublicKeySecp256k1.isPayToWitnessPublicKeyHash(), false); + EXPECT_EQ(PayToPublicKeySecp256k1Extended.isPayToWitnessPublicKeyHash(), false); + EXPECT_EQ(PayToPublicKeyHash.isPayToWitnessPublicKeyHash(), false); + + Data res; + EXPECT_EQ(PayToWitnessPublicKeyHash.matchPayToWitnessPublicKeyHash(res), true); + EXPECT_EQ(hex(res), "79091972186c449eb1ded22b78e40d009bdf0089"); + + EXPECT_EQ(PayToScriptHash.matchPayToWitnessPublicKeyHash(res), false); + EXPECT_EQ(PayToWitnessScriptHash.matchPayToWitnessPublicKeyHash(res), false); + EXPECT_EQ(PayToPublicKeySecp256k1.matchPayToWitnessPublicKeyHash(res), false); + EXPECT_EQ(PayToPublicKeySecp256k1Extended.matchPayToWitnessPublicKeyHash(res), false); + EXPECT_EQ(PayToPublicKeyHash.matchPayToWitnessPublicKeyHash(res), false); +} + +TEST(BitcoinScript, WitnessProgram) { + EXPECT_EQ(PayToWitnessScriptHash.isWitnessProgram(), true); + EXPECT_EQ(PayToWitnessPublicKeyHash.isWitnessProgram(), true); + + EXPECT_EQ(PayToScriptHash.isWitnessProgram(), false); + EXPECT_EQ(PayToPublicKeySecp256k1.isWitnessProgram(), false); + EXPECT_EQ(PayToPublicKeySecp256k1Extended.isWitnessProgram(), false); + EXPECT_EQ(PayToPublicKeyHash.isWitnessProgram(), false); +} + +TEST(BitcoinScript, EncodeNumber) { + EXPECT_EQ(Script::encodeNumber(0), OP_0); + EXPECT_EQ(Script::encodeNumber(1), OP_1); + EXPECT_EQ(Script::encodeNumber(3), OP_3); + EXPECT_EQ(Script::encodeNumber(9), OP_9); +} + +TEST(BitcoinScript, DecodeNumber) { + EXPECT_EQ(Script::decodeNumber(OP_0), 0); + EXPECT_EQ(Script::decodeNumber(OP_1), 1); + EXPECT_EQ(Script::decodeNumber(OP_3), 3); + EXPECT_EQ(Script::decodeNumber(OP_9), 9); +} + +TEST(BitcoinScript, GetScriptOp) { + { + size_t index = 5; uint8_t opcode; Data operand; + EXPECT_EQ(Script(parse_hex("")).getScriptOp(index, opcode, operand), false); + } + { + size_t index = 0; uint8_t opcode; Data operand; + EXPECT_EQ(Script(parse_hex("4f")).getScriptOp(index, opcode, operand), true); + EXPECT_EQ(index, 1); + EXPECT_EQ(opcode, 0x4f); + EXPECT_EQ(hex(operand), ""); + } + { + size_t index = 0; uint8_t opcode; Data operand; + EXPECT_EQ(Script(parse_hex("05" "0102030405")).getScriptOp(index, opcode, operand), true); + EXPECT_EQ(index, 6); + EXPECT_EQ(opcode, 0x05); + EXPECT_EQ(hex(operand), "0102030405"); + } + { // OP_PUSHDATA1 + size_t index = 0; uint8_t opcode; Data operand; + EXPECT_EQ(Script(parse_hex("4c" "05" "0102030405")).getScriptOp(index, opcode, operand), true); + EXPECT_EQ(index, 7); + EXPECT_EQ(opcode, 0x4c); + EXPECT_EQ(hex(operand), "0102030405"); + } + { // OP_PUSHDATA1 too short + size_t index = 0; uint8_t opcode; Data operand; + EXPECT_EQ(Script(parse_hex("4c")).getScriptOp(index, opcode, operand), false); + } + { // OP_PUSHDATA1 too short + size_t index = 0; uint8_t opcode; Data operand; + EXPECT_EQ(Script(parse_hex("4c" "05" "010203")).getScriptOp(index, opcode, operand), false); + } + { // OP_PUSHDATA2 + size_t index = 0; uint8_t opcode; Data operand; + EXPECT_EQ(Script(parse_hex("4d" "0500" "0102030405")).getScriptOp(index, opcode, operand), true); + EXPECT_EQ(index, 8); + EXPECT_EQ(opcode, 0x4d); + EXPECT_EQ(hex(operand), "0102030405"); + } + { // OP_PUSHDATA2 too short + size_t index = 0; uint8_t opcode; Data operand; + EXPECT_EQ(Script(parse_hex("4d" "05")).getScriptOp(index, opcode, operand), false); + } + { // OP_PUSHDATA2 too short + size_t index = 0; uint8_t opcode; Data operand; + EXPECT_EQ(Script(parse_hex("4d" "0500" "010203")).getScriptOp(index, opcode, operand), false); + } + { // OP_PUSHDATA4 + size_t index = 0; uint8_t opcode; Data operand; + EXPECT_EQ(Script(parse_hex("4e" "05000000" "0102030405")).getScriptOp(index, opcode, operand), true); + EXPECT_EQ(index, 10); + EXPECT_EQ(opcode, 0x4e); + EXPECT_EQ(hex(operand), "0102030405"); + } + { // OP_PUSHDATA4 too short + size_t index = 0; uint8_t opcode; Data operand; + EXPECT_EQ(Script(parse_hex("4e" "0500")).getScriptOp(index, opcode, operand), false); + } + { // OP_PUSHDATA4 too short + size_t index = 0; uint8_t opcode; Data operand; + EXPECT_EQ(Script(parse_hex("4e" "05000000" "010203")).getScriptOp(index, opcode, operand), false); + } +} + +TEST(BitcoinScript, MatchMultiSig) { + std::vector keys; + int required; + EXPECT_EQ(Script(parse_hex("")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("20")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("ae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("00ae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("4fae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("20ae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("514cae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("514c05ae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("51ae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("51" "05" "0102030405" "ae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("51" "21" "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432" "ae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("51" "21" "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432" "00ae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("51" "21" "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432" "52ae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("51" "21" "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432" "51aeae")).matchMultisig(keys, required), false); + + // valid one key + EXPECT_EQ(Script(parse_hex("51" "21" "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432" "51" "ae")).matchMultisig(keys, required), true); + EXPECT_EQ(required, 1); + ASSERT_EQ(keys.size(), 1); + EXPECT_EQ(hex(keys[0]), "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432"); + + EXPECT_EQ(Script(parse_hex("51" "21" "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432" "21" "0399c6f51ad6f98c9c583f8e92bb7758ab2ca9a04110c0a1126ec43e5453d196c1" "51" "ae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("52" "21" "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432" "21" "0399c6f51ad6f98c9c583f8e92bb7758ab2ca9a04110c0a1126ec43e5453d196c1" "51" "ae")).matchMultisig(keys, required), false); + + // valid two keys + EXPECT_EQ(Script(parse_hex("52" "21" "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432" "21" "0399c6f51ad6f98c9c583f8e92bb7758ab2ca9a04110c0a1126ec43e5453d196c1" "52" "ae")).matchMultisig(keys, required), true); + EXPECT_EQ(required, 2); + ASSERT_EQ(keys.size(), 2); + EXPECT_EQ(hex(keys[0]), "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432"); + EXPECT_EQ(hex(keys[1]), "0399c6f51ad6f98c9c583f8e92bb7758ab2ca9a04110c0a1126ec43e5453d196c1"); + + // OP_PUSHDATA1 + EXPECT_EQ(Script(parse_hex("514cae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("514c" "05" "ae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("514c" "05" "0102030405" "ae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("514c" "21" "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432" "ae")).matchMultisig(keys, required), false); + + // valid one key, OP_PUSHDATA1 + EXPECT_EQ(Script(parse_hex("514c" "21" "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432" "51" "ae")).matchMultisig(keys, required), true); + EXPECT_EQ(required, 1); + ASSERT_EQ(keys.size(), 1); + EXPECT_EQ(hex(keys[0]), "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432"); + + // OP_PUSHDATA2 + EXPECT_EQ(Script(parse_hex("514dae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("514d" "0500" "ae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("514d" "0500" "0102030405" "ae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("514d" "2100" "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432" "ae")).matchMultisig(keys, required), false); + + // valid one key, OP_PUSHDATA2 + EXPECT_EQ(Script(parse_hex("514d" "2100" "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432" "51" "ae")).matchMultisig(keys, required), true); + EXPECT_EQ(required, 1); + ASSERT_EQ(keys.size(), 1); + EXPECT_EQ(hex(keys[0]), "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432"); + + // OP_PUSHDATA4 + EXPECT_EQ(Script(parse_hex("514eae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("514e" "0500" "ae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("514e" "05000000" "ae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("514e" "05000000" "0102030405" "ae")).matchMultisig(keys, required), false); + EXPECT_EQ(Script(parse_hex("514e" "21000000" "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432" "ae")).matchMultisig(keys, required), false); + + // valid one key, OP_PUSHDATA2 + EXPECT_EQ(Script(parse_hex("514e" "21000000" "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432" "51" "ae")).matchMultisig(keys, required), true); + EXPECT_EQ(required, 1); + ASSERT_EQ(keys.size(), 1); + EXPECT_EQ(hex(keys[0]), "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432"); + + // valid three keys, mixed + EXPECT_EQ(Script(parse_hex("53" + "21" "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432" + "4d" "2100" "0399c6f51ad6f98c9c583f8e92bb7758ab2ca9a04110c0a1126ec43e5453d196c1" + "4e" "21000000" "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432" + "53" "ae")).matchMultisig(keys, required), true); + EXPECT_EQ(required, 3); + ASSERT_EQ(keys.size(), 3); + EXPECT_EQ(hex(keys[0]), "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432"); + EXPECT_EQ(hex(keys[1]), "0399c6f51ad6f98c9c583f8e92bb7758ab2ca9a04110c0a1126ec43e5453d196c1"); + EXPECT_EQ(hex(keys[2]), "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432"); +} diff --git a/tests/Bitcoin/TWBitcoinScriptTests.cpp b/tests/Bitcoin/TWBitcoinScriptTests.cpp index 6e5c716fcc5..5337008e9a7 100644 --- a/tests/Bitcoin/TWBitcoinScriptTests.cpp +++ b/tests/Bitcoin/TWBitcoinScriptTests.cpp @@ -11,7 +11,124 @@ #include -TEST(BitcoinScript, ScriptHash) { +const auto PayToScriptHash = TWBitcoinScriptCreateWithData(DATA("a914" "4733f37cf4db86fbc2efed2500b4f4e49f312023" "87").get()); +const auto PayToWitnessScriptHash = TWBitcoinScriptCreateWithData(DATA("0020" "ff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3db").get()); +const auto PayToWitnessPublicKeyHash = TWBitcoinScriptCreateWithData(DATA("0014" "79091972186c449eb1ded22b78e40d009bdf0089").get()); +const auto PayToPublicKeySecp256k1 = TWBitcoinScriptCreateWithData(DATA("21" "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432" "ac").get()); +const auto PayToPublicKeyHash = TWBitcoinScriptCreateWithData(DATA("76a914" "79091972186c449eb1ded22b78e40d009bdf0089" "88ac").get()); + +TEST(TWBitcoinScript, Create) { + auto data = DATA("a9144733f37cf4db86fbc2efed2500b4f4e49f31202387"); + { + auto script = TWBitcoinScriptCreateWithData(data.get()); + ASSERT_TRUE(script != nullptr); + ASSERT_EQ(TWBitcoinScriptSize(script), 23); + } + { + auto script = TWBitcoinScriptCreateWithBytes(TWDataBytes(data.get()), TWDataSize(data.get())); + ASSERT_TRUE(script != nullptr); + ASSERT_EQ(TWBitcoinScriptSize(script), 23); + + auto scriptCopy = TWBitcoinScriptCreateCopy(script); + ASSERT_TRUE(scriptCopy != nullptr); + ASSERT_EQ(TWBitcoinScriptSize(scriptCopy), 23); + } +} + +TEST(TWBitcoinScript, Equals) { + auto data = DATA("a9144733f37cf4db86fbc2efed2500b4f4e49f31202387"); + auto script = TWBitcoinScriptCreateWithBytes(TWDataBytes(data.get()), TWDataSize(data.get())); + auto scriptCopy = TWBitcoinScriptCreateCopy(script); + ASSERT_TRUE(TWBitcoinScriptEqual(script, scriptCopy)); +} + +TEST(TWBitcoinScript, IsPayToScriptHash) { + ASSERT_TRUE(TWBitcoinScriptIsPayToScriptHash(PayToScriptHash)); +} + +TEST(TWBitcoinScript, IsPayToWitnessScriptHash) { + ASSERT_TRUE(TWBitcoinScriptIsPayToWitnessScriptHash(PayToWitnessScriptHash)); +} + +TEST(TWBitcoinScript, IsPayToWitnessPublicKeyHash) { + ASSERT_TRUE(TWBitcoinScriptIsPayToWitnessPublicKeyHash(PayToWitnessPublicKeyHash)); +} + +TEST(TWBitcoinScript, IsWitnessProgram) { + ASSERT_TRUE(TWBitcoinScriptIsWitnessProgram(PayToWitnessScriptHash)); + ASSERT_TRUE(TWBitcoinScriptIsWitnessProgram(PayToWitnessPublicKeyHash)); + ASSERT_FALSE(TWBitcoinScriptIsWitnessProgram(PayToScriptHash)); +} + +TEST(TWBitcoinScript, MatchPayToPubkey) { + const auto res = WRAPD(TWBitcoinScriptMatchPayToPubkey(PayToPublicKeySecp256k1)); + ASSERT_TRUE(res.get() != nullptr); + const auto hexRes = WRAPS(TWStringCreateWithHexData(res.get())); + ASSERT_STREQ(TWStringUTF8Bytes(hexRes.get()), "03c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432"); + + ASSERT_EQ(TWBitcoinScriptMatchPayToPubkey(PayToScriptHash), nullptr); +} + +TEST(TWBitcoinScript, TWBitcoinScriptMatchPayToPubkeyHash) { + const auto res = WRAPD(TWBitcoinScriptMatchPayToPubkeyHash(PayToPublicKeyHash)); + ASSERT_TRUE(res.get() != nullptr); + const auto hexRes = WRAPS(TWStringCreateWithHexData(res.get())); + ASSERT_STREQ(TWStringUTF8Bytes(hexRes.get()), "79091972186c449eb1ded22b78e40d009bdf0089"); + + ASSERT_EQ(TWBitcoinScriptMatchPayToPubkeyHash(PayToScriptHash), nullptr); +} + +TEST(TWBitcoinScript, MatchPayToScriptHash) { + const auto res = WRAPD(TWBitcoinScriptMatchPayToScriptHash(PayToScriptHash)); + ASSERT_TRUE(res.get() != nullptr); + const auto hexRes = WRAPS(TWStringCreateWithHexData(res.get())); + ASSERT_STREQ(TWStringUTF8Bytes(hexRes.get()), "4733f37cf4db86fbc2efed2500b4f4e49f312023"); + + ASSERT_EQ(TWBitcoinScriptMatchPayToScriptHash(PayToPublicKeySecp256k1), nullptr); +} + +TEST(TWBitcoinScript, MatchPayToWitnessPublicKeyHash) { + const auto res = WRAPD(TWBitcoinScriptMatchPayToWitnessPublicKeyHash(PayToWitnessPublicKeyHash)); + ASSERT_TRUE(res.get() != nullptr); + const auto hexRes = WRAPS(TWStringCreateWithHexData(res.get())); + ASSERT_STREQ(TWStringUTF8Bytes(hexRes.get()), "79091972186c449eb1ded22b78e40d009bdf0089"); + + ASSERT_EQ(TWBitcoinScriptMatchPayToWitnessPublicKeyHash(PayToPublicKeySecp256k1), nullptr); +} + +TEST(TWBitcoinScript, MatchPayToWitnessScriptHash) { + const auto res = WRAPD(TWBitcoinScriptMatchPayToWitnessScriptHash(PayToWitnessScriptHash)); + ASSERT_TRUE(res.get() != nullptr); + const auto hexRes = WRAPS(TWStringCreateWithHexData(res.get())); + ASSERT_STREQ(TWStringUTF8Bytes(hexRes.get()), "ff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3db"); + + ASSERT_EQ(TWBitcoinScriptMatchPayToWitnessScriptHash(PayToPublicKeySecp256k1), nullptr); +} + +TEST(TWBitcoinScript, Encode) { + const auto res = WRAPD(TWBitcoinScriptEncode(PayToScriptHash)); + ASSERT_TRUE(res.get() != nullptr); + const auto hexRes = WRAPS(TWStringCreateWithHexData(res.get())); + ASSERT_STREQ(TWStringUTF8Bytes(hexRes.get()), "17a9144733f37cf4db86fbc2efed2500b4f4e49f31202387"); +} + +TEST(TWBitcoinScript, BuildPayToWitnessPubkeyHash) { + const auto hash = DATA("79091972186c449eb1ded22b78e40d009bdf0089"); + const auto script = TWBitcoinScriptBuildPayToWitnessPubkeyHash(hash.get()); + ASSERT_TRUE(script != nullptr); + const auto hex = WRAPS(TWStringCreateWithHexData(WRAPD(TWBitcoinScriptData(script)).get())); + ASSERT_STREQ(TWStringUTF8Bytes(hex.get()), "0014" "79091972186c449eb1ded22b78e40d009bdf0089"); +} + +TEST(TWBitcoinScript, BuildPayToWitnessScriptHash) { + const auto hash = DATA("ff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3db"); + const auto script = TWBitcoinScriptBuildPayToWitnessScriptHash(hash.get()); + ASSERT_TRUE(script != nullptr); + const auto hex = WRAPS(TWStringCreateWithHexData(WRAPD(TWBitcoinScriptData(script)).get())); + ASSERT_STREQ(TWStringUTF8Bytes(hex.get()), "0020" "ff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3db"); +} + +TEST(TWBitcoinScript, ScriptHash) { auto pkData = DATA("cf5007e19af3641199f21f3fa54dff2fa2627471"); auto script = WRAP(TWBitcoinScript, TWBitcoinScriptBuildPayToPublicKeyHash(pkData.get())); @@ -26,7 +143,7 @@ TEST(BitcoinScript, ScriptHash) { ASSERT_STREQ(TWStringUTF8Bytes(hexData.get()), "c470d22e69a2a967f2cec0cd5a5aebb955cdd395"); } -TEST(BitcoinScript, RedeemScript) { +TEST(TWBitcoinScript, RedeemScript) { auto pkData = DATA("cf5007e19af3641199f21f3fa54dff2fa2627471"); auto embeddedScript = WRAP(TWBitcoinScript, TWBitcoinScriptBuildPayToPublicKeyHash(pkData.get())); @@ -40,7 +157,7 @@ TEST(BitcoinScript, RedeemScript) { ASSERT_STREQ(TWStringUTF8Bytes(hexData.get()), "a914c470d22e69a2a967f2cec0cd5a5aebb955cdd39587"); } -TEST(BitcoinScript, LockScriptForP2PKHAddress) { +TEST(TWBitcoinScript, LockScriptForP2PKHAddress) { auto script = WRAP(TWBitcoinScript, TWBitcoinScriptBuildForAddress(STRING("1Cu32FVupVCgHkMMRJdYJugxwo2Aprgk7H").get(), TWCoinTypeBitcoin)); auto scriptData = WRAPD(TWBitcoinScriptData(script.get())); assertHexEqual(scriptData, "76a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac"); @@ -50,7 +167,7 @@ TEST(BitcoinScript, LockScriptForP2PKHAddress) { assertHexEqual(scriptPub2Data, "76a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac"); } -TEST(BitcoinScript, LockScriptForP2SHAddress) { +TEST(TWBitcoinScript, LockScriptForP2SHAddress) { auto script = WRAP(TWBitcoinScript, TWBitcoinScriptBuildForAddress(STRING("37rHiL4DN2wkt8pgCAUfYJRxhir98ZGN1y").get(), TWCoinTypeBitcoin)); auto scriptData = WRAPD(TWBitcoinScriptData(script.get())); assertHexEqual(scriptData, "a9144391adbec172cad6a9fc3eebca36aeec6640abda87"); @@ -60,7 +177,7 @@ TEST(BitcoinScript, LockScriptForP2SHAddress) { assertHexEqual(scriptPub2Data, "a914ad40768af6419a20bdb94d83c06b6c8c94721dc087"); } -TEST(BitcoinScript, LockScriptForP2WPKHAddress) { +TEST(TWBitcoinScript, LockScriptForP2WPKHAddress) { auto script = WRAP(TWBitcoinScript, TWBitcoinScriptBuildForAddress(STRING("bc1q6hppaw7uld68amnnu5vpp5dd5u7k92c2vtdtkq").get(), TWCoinTypeBitcoin)); auto scriptData = WRAPD(TWBitcoinScriptData(script.get())); assertHexEqual(scriptData, "0014d5c21ebbdcfb747eee73e51810d1ada73d62ab0a"); @@ -70,13 +187,13 @@ TEST(BitcoinScript, LockScriptForP2WPKHAddress) { assertHexEqual(scriptPub2Data, "0014039f2ffd2b28703f0e9c73ccf3ce564adebbb5e8"); } -TEST(BitcoinScript, LockScriptForP2WSHAddress) { +TEST(TWBitcoinScript, LockScriptForP2WSHAddress) { auto script = WRAP(TWBitcoinScript, TWBitcoinScriptBuildForAddress(STRING("bc1qcuqamesrt803xld4l2j2vxx8rxmrx7aq82mkw7xwxh643wzqjlnqutkcv2").get(), TWCoinTypeBitcoin)); auto scriptData = WRAPD(TWBitcoinScriptData(script.get())); assertHexEqual(scriptData, "0020c701dde60359df137db5faa4a618c719b6337ba03ab76778ce35f558b84097e6"); } -TEST(BitcoinScript, LockScriptForCashAddress) { +TEST(TWBitcoinScript, LockScriptForCashAddress) { auto script = WRAP(TWBitcoinScript, TWBitcoinScriptBuildForAddress(STRING("bitcoincash:pzclklsyx9f068hd00a0vene45akeyrg7vv0053uqf").get(), TWCoinTypeBitcoin)); auto scriptData = WRAPD(TWBitcoinScriptData(script.get())); assertHexEqual(scriptData, "a914b1fb7e043152fd1eed7bfaf66679ad3b6c9068f387"); diff --git a/tests/Bitcoin/TWBitcoinSigningTests.cpp b/tests/Bitcoin/TWBitcoinSigningTests.cpp index 931e8dfe46f..45137ad48ef 100644 --- a/tests/Bitcoin/TWBitcoinSigningTests.cpp +++ b/tests/Bitcoin/TWBitcoinSigningTests.cpp @@ -249,7 +249,7 @@ TEST(BitcoinSigning, SignP2SH_P2WPKH) { ASSERT_EQ(hex(utxoPubkeyHash.begin(), utxoPubkeyHash.end()), "79091972186c449eb1ded22b78e40d009bdf0089"); input.add_private_key(utxoKey0.bytes.data(), utxoKey0.bytes.size()); - auto redeemScript = Script::buildPayToWitnessPubkeyHash(utxoPubkeyHash); + auto redeemScript = Script::buildPayToWitnessPublicKeyHash(utxoPubkeyHash); auto scriptHash = Hash::ripemd(Hash::sha256(redeemScript.bytes)); ASSERT_EQ(hex(scriptHash.begin(), scriptHash.end()), "4733f37cf4db86fbc2efed2500b4f4e49f312023"); auto scriptString = std::string(redeemScript.bytes.begin(), redeemScript.bytes.end()); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f74d949fcdb..f6acfc476be 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,7 +6,7 @@ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) # Add googletest directly to our build. This defines # the gtest and gtest_main targets. -add_subdirectory(${CMAKE_SOURCE_DIR}/wallet-core/build/gtest/staging/googletest-release-1.8.1 +add_subdirectory(${CMAKE_SOURCE_DIR}/build/local/src/gtest/googletest-release-1.8.1 ${CMAKE_CURRENT_BINARY_DIR}/googletest-build EXCLUDE_FROM_ALL) diff --git a/tests/CoinAddressDerivationTests.cpp b/tests/CoinAddressDerivationTests.cpp index 16ac09114df..1bf597c6d88 100644 --- a/tests/CoinAddressDerivationTests.cpp +++ b/tests/CoinAddressDerivationTests.cpp @@ -71,6 +71,7 @@ TEST(Coin, DeriveAddress) { EXPECT_EQ(TW::deriveAddress(TWCoinTypeFilecoin, privateKey), "f1qsx7qwiojh5duxbxhbqgnlyx5hmpcf7mcz5oxsy"); EXPECT_EQ(TW::deriveAddress(TWCoinTypeNEAR, privateKey), "NEAR2p5878zbFhxnrm7meL7TmqwtvBaqcBddyp5eGzZbovZ5HYrdGj"); EXPECT_EQ(TW::deriveAddress(TWCoinTypeSolana, privateKey), "H4JcMPicKkHcxxDjkyyrLoQj7Kcibd9t815ak4UvTr9M"); + EXPECT_EQ(TW::deriveAddress(TWCoinTypeElrond, privateKey), "erd1a6f6fan035ttsxdmn04ellxdlnwpgyhg0lhx5vjv92v6rc8xw9yq83344f"); } } // namespace TW diff --git a/tests/CoinAddressValidationTests.cpp b/tests/CoinAddressValidationTests.cpp index 7b08cf9f61b..86a0d7f309a 100644 --- a/tests/CoinAddressValidationTests.cpp +++ b/tests/CoinAddressValidationTests.cpp @@ -373,4 +373,10 @@ TEST(Coin, ValidateAddressVeChain) { EXPECT_EQ(normalizeAddress(TWCoinTypeVeChain, "0x9d8a62f656a8d1615c1294fd71e9cfb3e4855a4f"), "0x9d8A62f656a8d1615C1294fd71e9CFb3E4855A4F"); } +TEST(Coin, ValidateAddressElrond) { + EXPECT_TRUE(validateAddress(TWCoinTypeElrond, "erd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2fsmsgldz")); + EXPECT_FALSE(validateAddress(TWCoinTypeElrond, "xerd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2fsmsgldz")); +} + + } // namespace TW diff --git a/tests/DigitalGold/AddressTests.cpp b/tests/DigitalGold/AddressTests.cpp new file mode 100644 index 00000000000..ae22b98df65 --- /dev/null +++ b/tests/DigitalGold/AddressTests.cpp @@ -0,0 +1,70 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#include "HexCoding.h" +#include "Bitcoin/Address.h" +#include "Coin.h" +#include "PublicKey.h" +#include "PrivateKey.h" +#include +#include + +using namespace TW; +using namespace TW::Bitcoin; + +TEST(DigitalGoldAddress, Valid) { + ASSERT_TRUE(Address::isValid("GJCMxPGMH3LVoGtZ3yEhPYbMVnYwSybBzi")); + ASSERT_TRUE(Address::isValid("GaLFdPjbDVGcv7v6xuhbvpXUq8mtMkR24y")); + ASSERT_TRUE(Address::isValid("GfxjHLysUq5XmPqtYPVyzdVm39QSDpFdET")); + ASSERT_TRUE(Address::isValid("Gdzoxj6QFLDndw5htN2hLJ8JwKRWYHdX2K")); + ASSERT_TRUE(Address::isValid("GJKt1CQ4wj2i7QTL2VzhXGQ7u7uUXJ7s5A")); + ASSERT_TRUE(Address::isValid("Gc5JdxYv2k1FfJMr689J66VxQ4yGp97GzZ")); + ASSERT_TRUE(Address::isValid("GdfXJwBdQUwD1nuySrQeZjFw8KEtPEoBeB")); + ASSERT_TRUE(Address::isValid("GcSsKzmisNB5KCH6wJr6NZyoSMyydVvi22")); + ASSERT_TRUE(Address::isValid("GKm9Uj8R6MPqNw2xkhXNYKsvUy46n8E655")); + ASSERT_TRUE(Address::isValid("GJu16E3CmFdSknrzbKpXacW2MPoLwiesTv")); + ASSERT_TRUE(Address::isValid("GTWUe2J9amAkhGm6ePrg2knPXYwNZWL2AH")); + ASSERT_TRUE(Address::isValid("GJBJoGst6SPYweTdE2rLXpc7ky3JaN8s3M")); + ASSERT_TRUE(Address::isValid("GYPHQbxED8GFtpHkZShNzAxyZDrUVKjPFC")); + + // TODO: test segwit addresses +} + +TEST(DigitalGoldAddress, Invalid) { + + const byte p2pkh = p2pkhPrefix(TWCoinTypeDigitalGold); + const byte p2sh = p2shPrefix(TWCoinTypeDigitalGold); + + ASSERT_FALSE(Address::isValid("GZ8fKGGqBZtenPR8hL-----BpMcagkXg5g")); + ASSERT_FALSE(Address::isValid("1MVk8kVbs7nepTGwbQN1H46UDjSDAUgcRU", {{p2pkh}, {p2sh}})); // valid bitcoin address, but invalid dgld address + + // TODO: Add more tests +} + +TEST(DigitalGoldAddress, FromPrivateKey) { + + const byte p2pkh = p2pkhPrefix(TWCoinTypeDigitalGold); + const byte p2sh = p2shPrefix(TWCoinTypeDigitalGold); + + auto privateKey = PrivateKey(parse_hex("63832fb769a6f12b0a403b8906d6b718a3994b1c1ace78be359a7ff39b3a7362")); + auto address = Address(privateKey.getPublicKey(TWPublicKeyTypeSECP256k1), p2pkh); + ASSERT_EQ(address.string(), "GNxs8kNGP4E18is7TRvjh9WknrStwMmS2N"); +} + +TEST(DigitalGoldAddress, FromPublicKey) { + + const byte p2pkh = p2pkhPrefix(TWCoinTypeDigitalGold); + const byte p2sh = p2shPrefix(TWCoinTypeDigitalGold); + + auto publicKey = PublicKey(parse_hex("028bd49b59eaa0aa4485ef35bc0433cf5071eeb41b229d17c5563d935ca474a9b4"), TWPublicKeyTypeSECP256k1); + auto address = Address(publicKey, p2pkh); + ASSERT_EQ(address.string(), "GSvAp2iiodmfkuS4xcpAyJo7s5xhPGw6YY"); +} + +TEST(DigitalGoldAddress, FromString) { + auto address = Address("GRZ3JdwD4LuiJd2x7kKfFVJr6MdHREj7ie"); + ASSERT_EQ(address.string(), "GRZ3JdwD4LuiJd2x7kKfFVJr6MdHREj7ie"); +} diff --git a/tests/DigitalGold/SignerTests.cpp b/tests/DigitalGold/SignerTests.cpp new file mode 100644 index 00000000000..789de98713d --- /dev/null +++ b/tests/DigitalGold/SignerTests.cpp @@ -0,0 +1,34 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#include "Bitcoin/Signer.h" +#include "Bitcoin/Address.h" +#include "HexCoding.h" +#include "PrivateKey.h" +#include "PublicKey.h" + +#include + +using namespace TW; +using namespace TW::Bitcoin; + +// TODO: Add tests + +TEST(DigitalGoldSigner, Sign) { + // TODO: Finalize test implementation + + //auto key = PrivateKey(parse_hex("__PRIVKEY_DATA__")); + //auto publicKey = key.getPublicKey(TWPublicKeyTypeED25519); + //auto from = Address(publicKey); + //auto to = Address("__TO_ADDRESS__"); + //... + //auto transaction = Transaction(...) + //auto signature = Signer::sign(key, transaction); + //auto result = transaction.serialize(signature); + + //ASSERT_EQ(hex(serialized), "__RESULT__"); + //ASSERT_EQ(...) +} diff --git a/tests/DigitalGold/TWAnyAddressTests.cpp b/tests/DigitalGold/TWAnyAddressTests.cpp new file mode 100644 index 00000000000..8537c7bc5a9 --- /dev/null +++ b/tests/DigitalGold/TWAnyAddressTests.cpp @@ -0,0 +1,19 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#include +#include "HexCoding.h" + +#include "../interface/TWTestUtilities.h" +#include + +using namespace TW; + +// TODO: Finalize tests + +TEST(TWDigitalGold, Address) { + // TODO: Finalize test implementation +} diff --git a/tests/DigitalGold/TWAnySignerTests.cpp b/tests/DigitalGold/TWAnySignerTests.cpp new file mode 100644 index 00000000000..593acfd700e --- /dev/null +++ b/tests/DigitalGold/TWAnySignerTests.cpp @@ -0,0 +1,19 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#include +#include "HexCoding.h" + +#include "../interface/TWTestUtilities.h" +#include + +using namespace TW; + +// TODO: Finalize tests + +TEST(TWAnySignerDigitalGold, Sign) { + // TODO: Finalize test implementation +} diff --git a/tests/DigitalGold/TWCoinTypeTests.cpp b/tests/DigitalGold/TWCoinTypeTests.cpp new file mode 100644 index 00000000000..632e8383af6 --- /dev/null +++ b/tests/DigitalGold/TWCoinTypeTests.cpp @@ -0,0 +1,34 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. +// +// This is a GENERATED FILE, changes made here MAY BE LOST. +// Generated one-time (codegen/bin/cointests) +// + +#include "../interface/TWTestUtilities.h" +#include +#include + + +TEST(TWDigitalGoldCoinType, TWCoinType) { + auto symbol = WRAPS(TWCoinTypeConfigurationGetSymbol(TWCoinTypeDigitalGold)); + auto txId = TWStringCreateWithUTF8Bytes("68e203d1837aad907f4c09b22835e78304a7ae5c4268d0c2487958e3a1858b6e"); + auto txUrl = WRAPS(TWCoinTypeConfigurationGetTransactionURL(TWCoinTypeDigitalGold, txId)); + auto accId = TWStringCreateWithUTF8Bytes("g3X4Jwf9WLuBqET7tr2bCkDX3A2FGBrUm8"); + auto accUrl = WRAPS(TWCoinTypeConfigurationGetAccountURL(TWCoinTypeDigitalGold, accId)); + auto id = WRAPS(TWCoinTypeConfigurationGetID(TWCoinTypeDigitalGold)); + auto name = WRAPS(TWCoinTypeConfigurationGetName(TWCoinTypeDigitalGold)); + + ASSERT_EQ(TWCoinTypeConfigurationGetDecimals(TWCoinTypeDigitalGold), 8); + ASSERT_EQ(TWBlockchainBitcoin, TWCoinTypeBlockchain(TWCoinTypeDigitalGold)); + ASSERT_EQ(0x61, TWCoinTypeP2shPrefix(TWCoinTypeDigitalGold)); + ASSERT_EQ(0x0, TWCoinTypeStaticPrefix(TWCoinTypeDigitalGold)); + assertStringsEqual(symbol, "DGLD"); + assertStringsEqual(txUrl, "https://explorer.dgld.ch/tx/68e203d1837aad907f4c09b22835e78304a7ae5c4268d0c2487958e3a1858b6e"); + assertStringsEqual(accUrl, "https://explorer.dgld.ch/address/g3X4Jwf9WLuBqET7tr2bCkDX3A2FGBrUm8"); + assertStringsEqual(id, "dgld"); + assertStringsEqual(name, "DigitalGold"); +} diff --git a/tests/Elrond/AddressTests.cpp b/tests/Elrond/AddressTests.cpp new file mode 100644 index 00000000000..3dd1fb6f166 --- /dev/null +++ b/tests/Elrond/AddressTests.cpp @@ -0,0 +1,79 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#include +#include + +#include "HexCoding.h" +#include "PublicKey.h" +#include "PrivateKey.h" +#include "Elrond/Address.h" +#include "TestAccounts.h" + +using namespace TW; +using namespace TW::Elrond; + + +TEST(ElrondAddress, Valid) { + ASSERT_TRUE(Address::isValid(ALICE_BECH32)); + ASSERT_TRUE(Address::isValid(BOB_BECH32)); + ASSERT_TRUE(Address::isValid(CAROL_BECH32)); +} + +TEST(ElrondAddress, Invalid) { + ASSERT_FALSE(Address::isValid("")); + ASSERT_FALSE(Address::isValid("foo")); + ASSERT_FALSE(Address::isValid("10z9xdugayn528ksaesdwlhf006fw5sg2qmmm0h52fvxczwgesyvq5pwemr")); + ASSERT_FALSE(Address::isValid("xerd10z9xdugayn528ksaesdwlhf006fw5sg2qmmm0h52fvxczwgesyvq5pwemr")); + ASSERT_FALSE(Address::isValid("foo10z9xdugayn528ksaesdwlhf006fw5sg2qmmm0h52fvxczwgesyvq5pwemr")); + ASSERT_FALSE(Address::isValid(ALICE_PUBKEY_HEX)); +} + +TEST(ElrondAddress, FromString) { + Address alice, bob, carol; + ASSERT_TRUE(Address::decode(ALICE_BECH32, alice)); + ASSERT_TRUE(Address::decode(BOB_BECH32, bob)); + ASSERT_TRUE(Address::decode(CAROL_BECH32, carol)); + + ASSERT_EQ(ALICE_PUBKEY_HEX, hex(alice.getKeyHash())); + ASSERT_EQ(BOB_PUBKEY_HEX, hex(bob.getKeyHash())); + ASSERT_EQ(CAROL_PUBKEY_HEX, hex(carol.getKeyHash())); +} + +TEST(ElrondAddress, FromData) { + const auto alice = Address(parse_hex(ALICE_PUBKEY_HEX)); + const auto bob = Address(parse_hex(BOB_PUBKEY_HEX)); + const auto carol = Address(parse_hex(CAROL_PUBKEY_HEX)); + + ASSERT_EQ(ALICE_BECH32, alice.string()); + ASSERT_EQ(BOB_BECH32, bob.string()); + ASSERT_EQ(CAROL_BECH32, carol.string()); +} + +TEST(ElrondAddress, FromPrivateKey) { + auto aliceKey = PrivateKey(parse_hex(ALICE_SEED_HEX)); + auto alice = Address(aliceKey.getPublicKey(TWPublicKeyTypeED25519)); + ASSERT_EQ(ALICE_BECH32, alice.string()); + + auto bobKey = PrivateKey(parse_hex(BOB_SEED_HEX)); + auto bob = Address(bobKey.getPublicKey(TWPublicKeyTypeED25519)); + ASSERT_EQ(BOB_BECH32, bob.string()); + + auto carolKey = PrivateKey(parse_hex(CAROL_SEED_HEX)); + auto carol = Address(carolKey.getPublicKey(TWPublicKeyTypeED25519)); + ASSERT_EQ(CAROL_BECH32, carol.string()); +} + +TEST(ElrondAddress, FromPublicKey) { + auto alice = PublicKey(parse_hex(ALICE_PUBKEY_HEX), TWPublicKeyTypeED25519); + ASSERT_EQ(ALICE_BECH32, Address(alice).string()); + + auto bob = PublicKey(parse_hex(BOB_PUBKEY_HEX), TWPublicKeyTypeED25519); + ASSERT_EQ(BOB_BECH32, Address(bob).string()); + + auto carol = PublicKey(parse_hex(CAROL_PUBKEY_HEX), TWPublicKeyTypeED25519); + ASSERT_EQ(CAROL_BECH32, Address(carol).string()); +} diff --git a/tests/Elrond/SerializationTests.cpp b/tests/Elrond/SerializationTests.cpp new file mode 100644 index 00000000000..80c048bb9da --- /dev/null +++ b/tests/Elrond/SerializationTests.cpp @@ -0,0 +1,54 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#include +#include +#include "boost/format.hpp" + +#include "HexCoding.h" +#include "Elrond/Serialization.h" +#include "TestAccounts.h" + +using namespace TW; +using namespace TW::Elrond; + +TEST(ElrondSerialization, SignableString) { + Proto::TransactionMessage message; + message.set_nonce(42); + message.set_value("43"); + message.set_sender("alice"); + message.set_receiver("bob"); + message.set_data("foobar"); + + string jsonString = serializeTransaction(message); + ASSERT_EQ(R"({"nonce":42,"value":"43","receiver":"bob","sender":"alice","gasPrice":0,"gasLimit":0,"data":"Zm9vYmFy"})", jsonString); +} + +TEST(ElrondSerialization, SignableStringWithRealData) { + Proto::TransactionMessage message; + message.set_nonce(15); + message.set_value("100"); + message.set_sender(ALICE_BECH32); + message.set_receiver(BOB_BECH32); + message.set_gas_price(200000000000000); + message.set_gas_limit(500000000); + message.set_data("for dinner"); + + string expected = (boost::format(R"({"nonce":15,"value":"100","receiver":"%1%","sender":"%2%","gasPrice":200000000000000,"gasLimit":500000000,"data":"Zm9yIGRpbm5lcg=="})") % BOB_BECH32 % ALICE_BECH32).str(); + string actual = serializeTransaction(message); + ASSERT_EQ(expected, actual); +} + +TEST(ElrondSerialization, SignableStringWithoutData) { + Proto::TransactionMessage message; + message.set_nonce(42); + message.set_value("43"); + message.set_sender("feed"); + message.set_receiver("abba"); + + string jsonString = serializeTransaction(message); + ASSERT_EQ(R"({"nonce":42,"value":"43","receiver":"abba","sender":"feed","gasPrice":0,"gasLimit":0})", jsonString); +} diff --git a/tests/Elrond/SignerTests.cpp b/tests/Elrond/SignerTests.cpp new file mode 100644 index 00000000000..adda6c83a4d --- /dev/null +++ b/tests/Elrond/SignerTests.cpp @@ -0,0 +1,89 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#include +#include "boost/format.hpp" + +#include "HexCoding.h" +#include "PrivateKey.h" +#include "PublicKey.h" +#include "Elrond/Signer.h" +#include "Elrond/Address.h" +#include "TestAccounts.h" + +using namespace TW; +using namespace TW::Elrond; + + +TEST(ElrondSigner, Sign) { + auto input = Proto::SigningInput(); + auto privateKey = PrivateKey(parse_hex(ALICE_SEED_HEX)); + input.set_private_key(privateKey.bytes.data(), privateKey.bytes.size()); + + input.mutable_transaction()->set_nonce(0); + input.mutable_transaction()->set_value("0"); + input.mutable_transaction()->set_sender(ALICE_BECH32); + input.mutable_transaction()->set_receiver(BOB_BECH32); + input.mutable_transaction()->set_gas_price(200000000000000); + input.mutable_transaction()->set_gas_limit(500000000); + input.mutable_transaction()->set_data("foo"); + + auto output = Signer::sign(input); + auto signature = output.signature(); + auto encoded = output.encoded(); + auto expectedSignature = "b88ad2fe98a7316ea432a0a76c18cd87200fe75f27a8f053ea6532b40317dbec5136c5463aef132ae951b7e60d45d921caaa5903e70821dcda98f237d4ec4308"; + auto expectedEncoded = (boost::format(R"({"nonce":0,"value":"0","receiver":"%1%","sender":"%2%","gasPrice":200000000000000,"gasLimit":500000000,"data":"foo","signature":"%3%"})") % BOB_BECH32 % ALICE_BECH32 % expectedSignature).str(); + + ASSERT_EQ(expectedSignature, signature); + ASSERT_EQ(expectedEncoded, encoded); +} + +TEST(ElrondSigner, SignJSON) { + // Shuffle some fields, assume arbitrary order in the input + auto input = (boost::format(R"({"transaction" : {"data":"foo","value":"0","nonce":0,"receiver":"%1%","sender":"%2%","gasPrice":200000000000000,"gasLimit":500000000}})") % BOB_BECH32 % ALICE_BECH32).str(); + auto privateKey = PrivateKey(parse_hex(ALICE_SEED_HEX)); + + auto encoded = Signer::signJSON(input, privateKey.bytes); + auto expectedSignature = "b88ad2fe98a7316ea432a0a76c18cd87200fe75f27a8f053ea6532b40317dbec5136c5463aef132ae951b7e60d45d921caaa5903e70821dcda98f237d4ec4308"; + auto expectedEncoded = (boost::format(R"({"nonce":0,"value":"0","receiver":"%1%","sender":"%2%","gasPrice":200000000000000,"gasLimit":500000000,"data":"foo","signature":"%3%"})") % BOB_BECH32 % ALICE_BECH32 % expectedSignature).str(); + + ASSERT_EQ(expectedEncoded, encoded); +} + +TEST(ElrondSigner, SignWithoutData) { + auto input = Proto::SigningInput(); + auto privateKey = PrivateKey(parse_hex(ALICE_SEED_HEX)); + input.set_private_key(privateKey.bytes.data(), privateKey.bytes.size()); + + input.mutable_transaction()->set_nonce(0); + input.mutable_transaction()->set_value("0"); + input.mutable_transaction()->set_sender(ALICE_BECH32); + input.mutable_transaction()->set_receiver(BOB_BECH32); + input.mutable_transaction()->set_gas_price(200000000000000); + input.mutable_transaction()->set_gas_limit(500000000); + input.mutable_transaction()->set_data(""); + + auto output = Signer::sign(input); + auto signature = output.signature(); + auto encoded = output.encoded(); + auto expectedSignature = "39ab0e18bfce04bf53c9610faa3b9e7cecfca919510a7631e529e9086279b70a4832df32a5d1b8fdceb4e9082f2995da97f9195532c8d611ee749bc312cbf90c"; + auto expectedEncoded = (boost::format(R"({"nonce":0,"value":"0","receiver":"%1%","sender":"%2%","gasPrice":200000000000000,"gasLimit":500000000,"data":"","signature":"%3%"})") % BOB_BECH32 % ALICE_BECH32 % expectedSignature).str(); + + ASSERT_EQ(expectedSignature, signature); + ASSERT_EQ(expectedEncoded, encoded); +} + +TEST(ElrondSigner, SignJSONWithoutData) { + // Shuffle some fields, assume arbitrary order in the input + auto input = (boost::format(R"({"transaction" : {"value":"0","nonce":0,"receiver":"%1%","sender":"%2%","gasPrice":200000000000000,"gasLimit":500000000}})") % BOB_BECH32 % ALICE_BECH32).str(); + auto privateKey = PrivateKey(parse_hex(ALICE_SEED_HEX)); + + auto encoded = Signer::signJSON(input, privateKey.bytes); + auto expectedSignature = "39ab0e18bfce04bf53c9610faa3b9e7cecfca919510a7631e529e9086279b70a4832df32a5d1b8fdceb4e9082f2995da97f9195532c8d611ee749bc312cbf90c"; + auto expectedEncoded = (boost::format(R"({"nonce":0,"value":"0","receiver":"%1%","sender":"%2%","gasPrice":200000000000000,"gasLimit":500000000,"data":"","signature":"%3%"})") % BOB_BECH32 % ALICE_BECH32 % expectedSignature).str(); + + ASSERT_EQ(expectedEncoded, encoded); +} diff --git a/tests/Elrond/TWAnySignerTests.cpp b/tests/Elrond/TWAnySignerTests.cpp new file mode 100644 index 00000000000..f9366ab52ba --- /dev/null +++ b/tests/Elrond/TWAnySignerTests.cpp @@ -0,0 +1,55 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#include +#include "boost/format.hpp" + +#include +#include "HexCoding.h" +#include "../interface/TWTestUtilities.h" +#include "Elrond/Signer.h" +#include "TestAccounts.h" + +using namespace TW; +using namespace TW::Elrond; + + +TEST(TWAnySignerElrond, Sign) { + auto input = Proto::SigningInput(); + auto privateKey = PrivateKey(parse_hex(ALICE_SEED_HEX)); + input.set_private_key(privateKey.bytes.data(), privateKey.bytes.size()); + + input.mutable_transaction()->set_nonce(0); + input.mutable_transaction()->set_value("0"); + input.mutable_transaction()->set_sender(ALICE_BECH32); + input.mutable_transaction()->set_receiver(BOB_BECH32); + input.mutable_transaction()->set_gas_price(200000000000000); + input.mutable_transaction()->set_gas_limit(500000000); + input.mutable_transaction()->set_data("foo"); + + Proto::SigningOutput output; + ANY_SIGN(input, TWCoinTypeElrond); + + auto signature = output.signature(); + auto encoded = output.encoded(); + auto expectedSignature = "b88ad2fe98a7316ea432a0a76c18cd87200fe75f27a8f053ea6532b40317dbec5136c5463aef132ae951b7e60d45d921caaa5903e70821dcda98f237d4ec4308"; + auto expectedEncoded = (boost::format(R"({"nonce":0,"value":"0","receiver":"%1%","sender":"%2%","gasPrice":200000000000000,"gasLimit":500000000,"data":"foo","signature":"%3%"})") % BOB_BECH32 % ALICE_BECH32 % expectedSignature).str(); + + ASSERT_EQ(expectedSignature, signature); + ASSERT_EQ(expectedEncoded, encoded); +} + +TEST(TWAnySignerElrond, SignJSON) { + // Shuffle some fields, assume arbitrary order in the input + auto input = STRING((boost::format(R"({"transaction" : {"data":"foo","value":"0","nonce":0,"receiver":"%1%","sender":"%2%","gasPrice":200000000000000,"gasLimit":500000000}})") % BOB_BECH32 % ALICE_BECH32).str().c_str()); + auto privateKey = DATA(ALICE_SEED_HEX); + auto encoded = WRAPS(TWAnySignerSignJSON(input.get(), privateKey.get(), TWCoinTypeElrond)); + auto expectedSignature = "b88ad2fe98a7316ea432a0a76c18cd87200fe75f27a8f053ea6532b40317dbec5136c5463aef132ae951b7e60d45d921caaa5903e70821dcda98f237d4ec4308"; + auto expectedEncoded = (boost::format(R"({"nonce":0,"value":"0","receiver":"%1%","sender":"%2%","gasPrice":200000000000000,"gasLimit":500000000,"data":"foo","signature":"%3%"})") % BOB_BECH32 % ALICE_BECH32 % expectedSignature).str(); + + ASSERT_TRUE(TWAnySignerSupportsJSON(TWCoinTypeElrond)); + assertStringsEqual(encoded, expectedEncoded.c_str()); +} diff --git a/tests/Elrond/TWCoinTypeTests.cpp b/tests/Elrond/TWCoinTypeTests.cpp new file mode 100644 index 00000000000..9e73e615721 --- /dev/null +++ b/tests/Elrond/TWCoinTypeTests.cpp @@ -0,0 +1,34 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. +// +// This is a GENERATED FILE, changes made here MAY BE LOST. +// Generated one-time (codegen/bin/cointests) +// + +#include "../interface/TWTestUtilities.h" +#include +#include + + +TEST(TWElrondCoinType, TWCoinType) { + auto symbol = WRAPS(TWCoinTypeConfigurationGetSymbol(TWCoinTypeElrond)); + auto txId = TWStringCreateWithUTF8Bytes("1fc9785cb8bea0129a16cf7bddc97630c176a556ea566f0e72923c882b5cb3c8"); + auto txUrl = WRAPS(TWCoinTypeConfigurationGetTransactionURL(TWCoinTypeElrond, txId)); + auto accId = TWStringCreateWithUTF8Bytes("erd12yne790km8ezwetkz7m3hmqy9utdc6vdkgsunfzpwguec6v04p2qtk9uqj"); + auto accUrl = WRAPS(TWCoinTypeConfigurationGetAccountURL(TWCoinTypeElrond, accId)); + auto id = WRAPS(TWCoinTypeConfigurationGetID(TWCoinTypeElrond)); + auto name = WRAPS(TWCoinTypeConfigurationGetName(TWCoinTypeElrond)); + + ASSERT_EQ(TWCoinTypeConfigurationGetDecimals(TWCoinTypeElrond), 18); + ASSERT_EQ(TWBlockchainElrondNetwork, TWCoinTypeBlockchain(TWCoinTypeElrond)); + ASSERT_EQ(0x0, TWCoinTypeP2shPrefix(TWCoinTypeElrond)); + ASSERT_EQ(0x0, TWCoinTypeStaticPrefix(TWCoinTypeElrond)); + assertStringsEqual(symbol, "ERD"); + assertStringsEqual(txUrl, "https://explorer.elrond.com/transactions/1fc9785cb8bea0129a16cf7bddc97630c176a556ea566f0e72923c882b5cb3c8"); + assertStringsEqual(accUrl, "https://explorer.elrond.com/address/erd12yne790km8ezwetkz7m3hmqy9utdc6vdkgsunfzpwguec6v04p2qtk9uqj"); + assertStringsEqual(id, "elrond"); + assertStringsEqual(name, "Elrond"); +} diff --git a/tests/Elrond/TestAccounts.h b/tests/Elrond/TestAccounts.h new file mode 100644 index 00000000000..55060002abd --- /dev/null +++ b/tests/Elrond/TestAccounts.h @@ -0,0 +1,17 @@ +// Copyright © 2017-2020 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#pragma once + +const auto ALICE_BECH32 = "erd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2fsmsgldz"; +const auto ALICE_SEED_HEX = "1a927e2af5306a9bb2ea777f73e06ecc0ac9aaa72fb4ea3fecf659451394cccf"; +const auto ALICE_PUBKEY_HEX = "fd691bb5e85d102687d81079dffce842d4dc328276d2d4c60d8fd1c3433c3293"; +const auto BOB_BECH32 = "erd1cux02zersde0l7hhklzhywcxk4u9n4py5tdxyx7vrvhnza2r4gmq4vw35r"; +const auto BOB_SEED_HEX = "e3a3a3d1ac40d42d8fd4c569a9749b65a1250dd3d10b6f4e438297662ea4850e"; +const auto BOB_PUBKEY_HEX = "c70cf50b238372fffaf7b7c5723b06b57859d424a2da621bcc1b2f317543aa36"; +const auto CAROL_BECH32 = "erd19nu5t7hszckwah5nlcadmk5rlchtugzplznskffpwecygcu0520s9tnyy0"; +const auto CAROL_SEED_HEX = "a926316cc3daf8ff25ba3e417797e6dfd51f62ae735ab07148234732f7314052"; +const auto CAROL_PUBKEY_HEX = "2cf945faf0162ceede93fe3addda83fe2ebe2041f8a70b2521767044638fa29f"; diff --git a/tests/FIO/AddressTests.cpp b/tests/FIO/AddressTests.cpp index 62d117e99d9..f78e3ae25f2 100644 --- a/tests/FIO/AddressTests.cpp +++ b/tests/FIO/AddressTests.cpp @@ -35,10 +35,9 @@ TEST(FIOAddress, ValidateData) { } TEST(FIOAddress, FromString) { - ASSERT_EQ( - Address("FIO5kJKNHwctcfUM5XZyiWSqSTM5HTzznJP9F3ZdbhaQAHEVq575o").string(), - "FIO5kJKNHwctcfUM5XZyiWSqSTM5HTzznJP9F3ZdbhaQAHEVq575o" - ); + Address addr("FIO5kJKNHwctcfUM5XZyiWSqSTM5HTzznJP9F3ZdbhaQAHEVq575o"); + ASSERT_EQ(addr.string(), "FIO5kJKNHwctcfUM5XZyiWSqSTM5HTzznJP9F3ZdbhaQAHEVq575o"); + ASSERT_EQ(hex(addr.bytes), "0271195c66ec2799e436757a70cd8431d4b17733a097b18a5f7f1b6b085978ff0f343fc54e"); } TEST(FIOAddress, FromStringInvalid) { diff --git a/tests/FIO/TWCoinTypeTests.cpp b/tests/FIO/TWCoinTypeTests.cpp index 60c5bf35440..b7bdaa4469a 100644 --- a/tests/FIO/TWCoinTypeTests.cpp +++ b/tests/FIO/TWCoinTypeTests.cpp @@ -15,9 +15,9 @@ TEST(TWFIOCoinType, TWCoinType) { auto symbol = WRAPS(TWCoinTypeConfigurationGetSymbol(TWCoinTypeFIO)); - auto txId = TWStringCreateWithUTF8Bytes("t123"); + auto txId = TWStringCreateWithUTF8Bytes("930d1d3cf8988b39b5f64b64e9d61314a3e05a155d9e3505bdf863aab1adddf3"); auto txUrl = WRAPS(TWCoinTypeConfigurationGetTransactionURL(TWCoinTypeFIO, txId)); - auto accId = TWStringCreateWithUTF8Bytes("a12"); + auto accId = TWStringCreateWithUTF8Bytes("f5axfpgffiqz"); auto accUrl = WRAPS(TWCoinTypeConfigurationGetAccountURL(TWCoinTypeFIO, accId)); auto id = WRAPS(TWCoinTypeConfigurationGetID(TWCoinTypeFIO)); auto name = WRAPS(TWCoinTypeConfigurationGetName(TWCoinTypeFIO)); @@ -27,8 +27,8 @@ TEST(TWFIOCoinType, TWCoinType) { ASSERT_EQ(0x0, TWCoinTypeP2shPrefix(TWCoinTypeFIO)); ASSERT_EQ(0x0, TWCoinTypeStaticPrefix(TWCoinTypeFIO)); assertStringsEqual(symbol, "FIO"); - assertStringsEqual(txUrl, "https://fio.foundation/?t123"); - assertStringsEqual(accUrl, "https://fio.foundation/?a12"); + assertStringsEqual(txUrl, "https://explorer.fioprotocol.io/transaction/930d1d3cf8988b39b5f64b64e9d61314a3e05a155d9e3505bdf863aab1adddf3"); + assertStringsEqual(accUrl, "https://explorer.fioprotocol.io/account/f5axfpgffiqz"); assertStringsEqual(id, "fio"); assertStringsEqual(name, "FIO"); } diff --git a/tests/Filecoin/TWAnySignerTests.cpp b/tests/Filecoin/TWAnySignerTests.cpp index 6df308c8c47..e1dd177277e 100644 --- a/tests/Filecoin/TWAnySignerTests.cpp +++ b/tests/Filecoin/TWAnySignerTests.cpp @@ -59,3 +59,16 @@ TEST(TWAnySignerFilecoin, Sign) { TWDataDelete(inputData); TWDataDelete(outputData); } + +TEST(TWAnySignerFilecoin, SignJSON) { + auto json = STRING(R"({"toAddress":"f3um6uo3qt5of54xjbx3hsxbw5mbsc6auxzrvfxekn5bv3duewqyn2tg5rhrlx73qahzzpkhuj7a34iq7oifsq","nonce":"2","value":"IIasNRBSYAAA","gasPrice":"Ag==","gasLimit":"1000"})"); + auto key = DATA("1d969865e189957b9824bd34f26d5cbf357fda1a6d844cbf0c9ab1ed93fa7dbe"); + auto result = WRAPS(TWAnySignerSignJSON(json.get(), key.get(), TWCoinTypeFilecoin)); + + ASSERT_TRUE(TWAnySignerSupportsJSON(TWCoinTypeFilecoin)); + assertStringsEqual(result, + "8288583103a33d476e13eb8bde5d21becf2b86dd60642f0297cc6a5b914de86bb1d096861ba99bb13c57" + "7fee003e72f51e89f837c45501cf01bf485f61435e6770b52615bf455e043a2361024a002086ac351052" + "600000420002430003e800405842014e896d4fa72a1f39c37a4415629dfbb7ea301b7f001fff60befa48" + "5903f51d824659ba19c5bc969d7206de7afabfc4a0eec2dd34f15e58a064adf4ee9f72e64f01"); +} diff --git a/tests/Groestlcoin/TWGroestlcoinSigningTests.cpp b/tests/Groestlcoin/TWGroestlcoinSigningTests.cpp index 28d75b48d4c..c8a098a7aff 100644 --- a/tests/Groestlcoin/TWGroestlcoinSigningTests.cpp +++ b/tests/Groestlcoin/TWGroestlcoinSigningTests.cpp @@ -91,7 +91,7 @@ TEST(GroestlcoinSigning, SignP2SH_P2WPKH) { EXPECT_EQ(hex(utxoPubkeyHash.begin(), utxoPubkeyHash.end()), "2fc7d70acef142d1f7b5ef2f20b1a9b759797674"); input.add_private_key(utxoKey0.bytes.data(), utxoKey0.bytes.size()); - auto redeemScript = Script::buildPayToWitnessPubkeyHash(utxoPubkeyHash); + auto redeemScript = Script::buildPayToWitnessPublicKeyHash(utxoPubkeyHash); auto scriptHash = Hash::ripemd(Hash::sha256(redeemScript.bytes)); ASSERT_EQ(hex(scriptHash.begin(), scriptHash.end()), "0055b0c94df477ee6b9f75185dfc9aa8ce2e52e4"); auto scriptString = std::string(redeemScript.bytes.begin(), redeemScript.bytes.end()); diff --git a/tests/IoTeX/StakingTests.cpp b/tests/IoTeX/StakingTests.cpp index 96a79d3734f..0668a4a927d 100644 --- a/tests/IoTeX/StakingTests.cpp +++ b/tests/IoTeX/StakingTests.cpp @@ -4,193 +4,334 @@ // terms governing use, modification, and redistribution, is contained in the // file LICENSE at the root of the source code distribution tree. -#include "IoTeX/Staking.h" -#include "IoTeX/Signer.h" #include "Data.h" #include "HexCoding.h" +#include "IoTeX/Signer.h" +#include "IoTeX/Staking.h" +#include "PrivateKey.h" #include "proto/IoTeX.pb.h" #include "../interface/TWTestUtilities.h" - +#include #include using namespace TW; using namespace TW::IoTeX; -static const uint64_t pyggyIndex01 = 1001; -static std::string IOTEX_STAKING_CONTRACT = "io1xpq62aw85uqzrccg9y5hnryv8ld2nkpycc3gza"; -static const Data IOTEX_STAKING_TEST = TW::data(std::string("this is a test")); -static const Data candidate12 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; +TEST(TWIoTeXStaking, Create) { + std::string IOTEX_STAKING_CANDIDATE = "io19d0p3ah4g8ww9d7kcxfq87yxe7fnr8rpth5shj"; + std::string IOTEX_STAKING_PAYLOAD = "payload"; + std::string IOTEX_STAKING_AMOUNT = "100"; + Data candidate(IOTEX_STAKING_CANDIDATE.begin(), IOTEX_STAKING_CANDIDATE.end()); + Data payload(IOTEX_STAKING_PAYLOAD.begin(), IOTEX_STAKING_PAYLOAD.end()); + Data amount(IOTEX_STAKING_AMOUNT.begin(), IOTEX_STAKING_AMOUNT.end()); -TEST(IoTeXStaking, Stake) { - Data result; - stakingStake(candidate12, pyggyIndex01, true, IOTEX_STAKING_TEST, result); - ASSERT_EQ(hex(result), "07c35fc00102030405060708090a0b0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000e7468697320697320612074657374000000000000000000000000000000000000"); + auto stake = stakingCreate(candidate, amount, 10000, true, payload); + ASSERT_EQ(hex(stake), "0a29696f313964307033616834673877773964376b63786671383779786537666e723872" + "7074683573686a120331303018904e20012a077061796c6f6164"); } -TEST(IoTeXStaking, Unstake) { - Data result; - stakingUnstake(pyggyIndex01, IOTEX_STAKING_TEST, result); - ASSERT_EQ(hex(result), "c8fd6ed000000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000e7468697320697320612074657374000000000000000000000000000000000000"); +TEST(TWIoTeXStaking, AddDeposit) { + std::string IOTEX_STAKING_PAYLOAD = "payload"; + std::string IOTEX_STAKING_AMOUNT = "10"; + Data payload(IOTEX_STAKING_PAYLOAD.begin(), IOTEX_STAKING_PAYLOAD.end()); + Data amount(IOTEX_STAKING_AMOUNT.begin(), IOTEX_STAKING_AMOUNT.end()); + + auto stake = stakingAddDeposit(10, amount, payload); + + ASSERT_EQ(hex(stake), "080a120231301a077061796c6f6164"); } -TEST(IoTeXStaking, Withdraw) { - Data result; - stakingWithdraw(pyggyIndex01, IOTEX_STAKING_TEST, result); - ASSERT_EQ(hex(result), "030ba25d00000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000e7468697320697320612074657374000000000000000000000000000000000000"); +TEST(TWIoTeXStaking, Unstake) { + std::string IOTEX_STAKING_PAYLOAD = "payload"; + Data payload(IOTEX_STAKING_PAYLOAD.begin(), IOTEX_STAKING_PAYLOAD.end()); + + auto stake = stakingUnstake(10, payload); + + ASSERT_EQ(hex(stake), "080a12077061796c6f6164"); } -TEST(IoTeXStaking, AddStake) { - Data result; - stakingAddStake(pyggyIndex01, IOTEX_STAKING_TEST, result); - ASSERT_EQ(hex(result), "6e7b301700000000000000000000000000000000000000000000000000000000000003e90000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000e7468697320697320612074657374000000000000000000000000000000000000"); +TEST(TWIoTeXStaking, Withdraw) { + std::string IOTEX_STAKING_PAYLOAD = "payload"; + Data payload(IOTEX_STAKING_PAYLOAD.begin(), IOTEX_STAKING_PAYLOAD.end()); + + auto stake = stakingWithdraw(10, payload); + + ASSERT_EQ(hex(stake), "080a12077061796c6f6164"); } -TEST(IoTeXStaking, MoveStake) { - Data result; - stakingMoveStake(pyggyIndex01, candidate12, IOTEX_STAKING_TEST, result); - ASSERT_EQ(hex(result), "d3e41fd200000000000000000000000000000000000000000000000000000000000003e90102030405060708090a0b0c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000e7468697320697320612074657374000000000000000000000000000000000000"); +TEST(TWIoTeXStaking, Restake) { + std::string IOTEX_STAKING_PAYLOAD = "payload"; + Data payload(IOTEX_STAKING_PAYLOAD.begin(), IOTEX_STAKING_PAYLOAD.end()); + + auto stake = stakingRestake(10, 1000, true, payload); + + ASSERT_EQ(hex(stake), "080a10e807180122077061796c6f6164"); } -TEST(IoTeXStaking, SignStake) { - auto input = Proto::SigningInput(); - input.set_version(1); - input.set_nonce(123); - input.set_gaslimit(888); - input.set_gasprice("999"); - auto keyhex = parse_hex("0806c458b262edd333a191e92f561aff338211ee3e18ab315a074a2d82aa343f"); - input.set_privatekey(keyhex.data(), keyhex.size()); +TEST(TWIoTeXStaking, ChangeCandidate) { + std::string IOTEX_STAKING_CANDIDATE = "io1xpq62aw85uqzrccg9y5hnryv8ld2nkpycc3gza"; + std::string IOTEX_STAKING_PAYLOAD = "payload"; + Data candidate(IOTEX_STAKING_CANDIDATE.begin(), IOTEX_STAKING_CANDIDATE.end()); + Data payload(IOTEX_STAKING_PAYLOAD.begin(), IOTEX_STAKING_PAYLOAD.end()); + + auto stake = stakingChangeCandidate(10, candidate, payload); - // staking is implemented using the Execution message - auto staking = input.mutable_call(); - staking->set_amount("456"); - staking->set_contract(IOTEX_STAKING_CONTRACT); - - // call staking API to generate calldata - // data = "this is a test" here, it could be null (user leaves data empty when signing the tx) - Data stake; - stakingStake(candidate12, pyggyIndex01, true, IOTEX_STAKING_TEST, stake); - staking->set_data(stake.data(), stake.size()); - - auto signer = IoTeX::Signer(std::move(input)); - // raw action's hash - ASSERT_EQ(hex(signer.hash()), "cc3c8f7a0129455d70457c4be42a8b31d8e1df59594c99041b6b6d091b295b32"); - // build() signs the tx - auto output = signer.build(); - // signed action's serialized bytes - auto encoded = output.encoded(); - ASSERT_EQ(hex(encoded.begin(), encoded.end()), "0a86020801107b18f806220339393962f7010a033435361229696f3178707136326177383575717a72636367397935686e727976386c64326e6b7079636333677a611ac40107c35fc00102030405060708090a0b0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000e74686973206973206120746573740000000000000000000000000000000000001241044e18306ae9ef4ec9d07bf6e705442d4d1a75e6cdf750330ca2d880f2cc54607c9c33deb9eae9c06e06e04fe9ce3d43962cc67d5aa34fbeb71270d4bad3d648d91a41a558bc9a4bfba920242ccd4d5c5da363ec534d4dd5eb67f88e9db7aaad5c50ad62dfe298c0e54e311ebba045f48cea1136e42a123a8e6b03d3e6ed82d4ec2b9401"); - // signed action's hash - ASSERT_EQ(hex(output.hash()), "41b1f8be5f6b884c06556fba2611716e8e514b507f5a653fc02ac50ba13fbd6c"); + ASSERT_EQ(hex(stake), "080a1229696f3178707136326177383575717a72636367397935686e727976386c" + "64326e6b7079636333677a611a077061796c6f6164"); } -TEST(IoTeXStaking, SignUnstake) { - auto input = Proto::SigningInput(); - input.set_version(1); - input.set_nonce(123); - input.set_gaslimit(888); - input.set_gasprice("999"); - auto keyhex = parse_hex("0806c458b262edd333a191e92f561aff338211ee3e18ab315a074a2d82aa343f"); - input.set_privatekey(keyhex.data(), keyhex.size()); +TEST(TWIoTeXStaking, Transfer) { + std::string IOTEX_STAKING_CANDIDATE = "io1xpq62aw85uqzrccg9y5hnryv8ld2nkpycc3gza"; + std::string IOTEX_STAKING_PAYLOAD = "payload"; + Data candidate(IOTEX_STAKING_CANDIDATE.begin(), IOTEX_STAKING_CANDIDATE.end()); + Data payload(IOTEX_STAKING_PAYLOAD.begin(), IOTEX_STAKING_PAYLOAD.end()); + + auto stake = stakingTransfer(10, candidate, payload); - // staking is implemented using the Execution message - auto staking = input.mutable_call(); - staking->set_amount("456"); - staking->set_contract(IOTEX_STAKING_CONTRACT); - - // call staking API to generate calldata - Data unstake; - stakingUnstake(pyggyIndex01, Data{}, unstake); - staking->set_data(unstake.data(), unstake.size()); - - auto signer = IoTeX::Signer(std::move(input)); - // raw action's hash - ASSERT_EQ(hex(signer.hash()), "784f3d71246dfe897c1cb02da94e8ef1ac2381ac7f25ecfee80eaa78237db95b"); - // build() signs the tx - auto output = signer.build(); - // signed action's hash - ASSERT_EQ(hex(output.hash()), "b93a2874a72ce4eb8a41a20c209cf3fd188671ed8be8239a57960cbed887e962"); + ASSERT_EQ(hex(stake), "080a1229696f3178707136326177383575717a72636367397935686e727976386c6432" + "6e6b7079636333677a611a077061796c6f6164"); } -TEST(IoTeXStaking, SignWithdraw) { - auto input = Proto::SigningInput(); - input.set_version(1); - input.set_nonce(123); - input.set_gaslimit(888); - input.set_gasprice("999"); - auto keyhex = parse_hex("0806c458b262edd333a191e92f561aff338211ee3e18ab315a074a2d82aa343f"); - input.set_privatekey(keyhex.data(), keyhex.size()); +TEST(TWIoTeXStaking, CandidateRegister) { + std::string IOTEX_STAKING_NAME = "test"; + std::string IOTEX_STAKING_OPERATOR = "io10a298zmzvrt4guq79a9f4x7qedj59y7ery84he"; + std::string IOTEX_STAKING_REWARD = "io13sj9mzpewn25ymheukte4v39hvjdtrfp00mlyv"; + std::string IOTEX_STAKING_OWNER = "io19d0p3ah4g8ww9d7kcxfq87yxe7fnr8rpth5shj"; + std::string IOTEX_STAKING_AMOUNT = "100"; + std::string IOTEX_STAKING_PAYLOAD = "payload"; + Data name(IOTEX_STAKING_NAME.begin(), IOTEX_STAKING_NAME.end()); + Data operatorAddress(IOTEX_STAKING_OPERATOR.begin(), IOTEX_STAKING_OPERATOR.end()); + Data reward(IOTEX_STAKING_REWARD.begin(), IOTEX_STAKING_REWARD.end()); + Data amount(IOTEX_STAKING_AMOUNT.begin(), IOTEX_STAKING_AMOUNT.end()); + Data owner(IOTEX_STAKING_OWNER.begin(), IOTEX_STAKING_OWNER.end()); + Data payload(IOTEX_STAKING_PAYLOAD.begin(), IOTEX_STAKING_PAYLOAD.end()); + + auto stake = + candidateRegister(name, operatorAddress, reward, amount, 10000, false, owner, payload); - // staking is implemented using the Execution message - auto staking = input.mutable_call(); - staking->set_amount("456"); - staking->set_contract(IOTEX_STAKING_CONTRACT); - - // call staking API to generate calldata - Data withdraw; - stakingWithdraw(pyggyIndex01, Data{}, withdraw); - staking->set_data(withdraw.data(), withdraw.size()); - - auto signer = IoTeX::Signer(std::move(input)); - // raw action's hash - ASSERT_EQ(hex(signer.hash()), "ff55882624b2a1d6ae2d9fdec5f8a0f13b2f23c8b28c8ba91773b63f49b97fcc"); - // build() signs the tx - auto output = signer.build(); - // signed action's hash - ASSERT_EQ(hex(output.hash()), "2b2657247a72cb262de214b4e793c7a01fa2139fd5d12a46d43c24f87f9e2396"); + ASSERT_EQ(hex(stake), + "0a5c0a04746573741229696f3130613239387a6d7a7672743467757137396139663478377165646a3539" + "7937657279383468651a29696f3133736a396d7a7065776e3235796d6865756b74653476333968766a64" + "7472667030306d6c7976120331303018904e2a29696f313964307033616834673877773964376b637866" + "71383779786537666e7238727074683573686a32077061796c6f6164"); } -TEST(IoTeXStaking, SignAddStake) { - auto input = Proto::SigningInput(); - input.set_version(1); - input.set_nonce(123); - input.set_gaslimit(888); - input.set_gasprice("999"); - auto keyhex = parse_hex("0806c458b262edd333a191e92f561aff338211ee3e18ab315a074a2d82aa343f"); - input.set_privatekey(keyhex.data(), keyhex.size()); +TEST(TWIoTeXStaking, CandidateUpdate) { + std::string IOTEX_STAKING_NAME = "test"; + std::string IOTEX_STAKING_OPERATOR = "io1cl6rl2ev5dfa988qmgzg2x4hfazmp9vn2g66ng"; + std::string IOTEX_STAKING_REWARD = "io1juvx5g063eu4ts832nukp4vgcwk2gnc5cu9ayd"; + Data name(IOTEX_STAKING_NAME.begin(), IOTEX_STAKING_NAME.end()); + Data operatorAddress(IOTEX_STAKING_OPERATOR.begin(), IOTEX_STAKING_OPERATOR.end()); + Data reward(IOTEX_STAKING_REWARD.begin(), IOTEX_STAKING_REWARD.end()); + + auto stake = candidateUpdate(name, operatorAddress, reward); - // staking is implemented using the Execution message - auto staking = input.mutable_call(); - staking->set_amount("456"); - staking->set_contract(IOTEX_STAKING_CONTRACT); - - // call staking API to generate calldata - Data addStake; - stakingAddStake(pyggyIndex01, Data{}, addStake); - staking->set_data(addStake.data(), addStake.size()); - - auto signer = IoTeX::Signer(std::move(input)); - // raw action's hash - ASSERT_EQ(hex(signer.hash()), "7581e7f779429aa502879581fdc29f87917acfe638069255b6f033c45d7f24fe"); - // build() signs the tx - auto output = signer.build(); - // signed action's hash - ASSERT_EQ(hex(output.hash()), "c71058812a5febe5cdcdaf9499ba0b2c895f88d1acd3203e5097b307c2a5f1d1"); + ASSERT_EQ(hex(stake), "0a04746573741229696f31636c36726c32657635646661393838716d677a6732783468" + "66617a6d7039766e326736366e671a29696f316a757678356730363365753474733833" + "326e756b7034766763776b32676e6335637539617964"); } -TEST(IoTeXStaking, SignMoveStake) { +TEST(TWIoTeXStaking, SignAll) { auto input = Proto::SigningInput(); input.set_version(1); - input.set_nonce(123); - input.set_gaslimit(888); - input.set_gasprice("999"); - auto keyhex = parse_hex("0806c458b262edd333a191e92f561aff338211ee3e18ab315a074a2d82aa343f"); + input.set_nonce(0); + input.set_gaslimit(1000000); + input.set_gasprice("10"); + auto keyhex = parse_hex("cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1"); input.set_privatekey(keyhex.data(), keyhex.size()); + Proto::SigningOutput output; + + { // sign stakecreate + auto action = input.mutable_stakecreate(); + action->set_candidatename("io19d0p3ah4g8ww9d7kcxfq87yxe7fnr8rpth5shj"); + action->set_stakedamount("100"); + action->set_stakedduration(10000); + action->set_autostake(true); + action->set_payload("payload"); + ANY_SIGN(input, TWCoinTypeIoTeX); + ASSERT_EQ(hex(output.encoded()), + "0a4b080118c0843d22023130c2023e0a29696f313964307033616834673877773964376b63786671" + "3837797865" + "37666e7238727074683573686a120331303018904e20012a077061796c6f6164124104755ce6d890" + "3f6b3793bd" + "db4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c" + "0bc76ef30d" + "d6a1038ed9da8daf331a412e8bac421bab88dcd99c26ac8ffbf27f11ee57a41e7d2537891bfed5ae" + "d8e2e026d4" + "6e55d1b856787bc1cd7c1216a6e2534c5b5d1097c3afe8e657aa27cbbb0801"); + // signed action's hash + ASSERT_EQ(hex(output.hash()), + "f1785e47b4200c752bb6518bd18097a41e075438b8c18c9cb00e1ae2f38ce767"); + input.release_stakecreate(); + output.release_encoded(); + output.release_hash(); + } + { // sign stakeadddeposit + auto action = input.mutable_stakeadddeposit(); + action->set_bucketindex(10); + action->set_amount("10"); + action->set_payload("payload"); + ANY_SIGN(input, TWCoinTypeIoTeX); + ASSERT_EQ( + hex(output.encoded()), + "0a1c080118c0843d22023130da020f080a120231301a077061796c6f6164124104755ce6d8903f6b3793" + "bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0b" + "c76ef30dd6a1038ed9da8daf331a41a48ab1feba8181d760de946aefed7d815a89fd9b1ab503d2392bb5" + "5e1bb75eec42dddc8bd642f89accc3a37b3cf15a103a95d66695fdf0647b202869fdd66bcb01"); + // signed action's hash + ASSERT_EQ(hex(output.hash()), + "ca8937d6f224a4e4bf93cb5605581de2d26fb0481e1dfc1eef384ee7ccf94b73"); + input.release_stakeadddeposit(); + output.release_encoded(); + output.release_hash(); + } + { // sign stakeunstake + auto action = input.mutable_stakeunstake(); + action->set_bucketindex(10); + action->set_payload("payload"); + ANY_SIGN(input, TWCoinTypeIoTeX); + ASSERT_EQ( + hex(output.encoded()), + "0a18080118c0843d22023130ca020b080a12077061796c6f6164124104755ce6d8903f6b3793bddb4ea5" + "d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30d" + "d6a1038ed9da8daf331a4100adee39b48e1d3dbbd65298a57c7889709fc4df39987130da306f6997374a" + "184b7e7c232a42f21e89b06e6e7ceab81303c6b7483152d08d19ac829b22eb81e601"); + // signed action's hash + ASSERT_EQ(hex(output.hash()), + "bed58b64a6c4e959eca60a86f0b2149ce0e1dd527ac5fd26aef725ebf7c22a7d"); + input.release_stakeunstake(); + output.release_encoded(); + output.release_hash(); + } + { // sign stakewithdraw + auto action = input.mutable_stakewithdraw(); + action->set_bucketindex(10); + action->set_payload("payload"); + ANY_SIGN(input, TWCoinTypeIoTeX); + ASSERT_EQ( + hex(output.encoded()), + "0a18080118c0843d22023130d2020b080a12077061796c6f6164124104755ce6d8903f6b3793bddb4ea5" + "d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30d" + "d6a1038ed9da8daf331a4152644d102186be6640d46b517331f3402e24424b0d85129595421d28503d75" + "340b2922f5a0d4f667bbd6f576d9816770286b2ce032ba22eaec3952e24da4756b00"); + // signed action's hash + ASSERT_EQ(hex(output.hash()), + "28049348cf34f1aa927caa250e7a1b08778c44efaf73b565b6fa9abe843871b4"); + input.release_stakewithdraw(); + output.release_encoded(); + output.release_hash(); + } + { // sign stakerestake + auto action = input.mutable_stakerestake(); + action->set_bucketindex(10); + action->set_stakedduration(1000); + action->set_autostake(true); + action->set_payload("payload"); + ANY_SIGN(input, TWCoinTypeIoTeX); + ASSERT_EQ( + hex(output.encoded()), + "0a1d080118c0843d22023130e20210080a10e807180122077061796c6f6164124104755ce6d8903f6b37" + "93bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c" + "0bc76ef30dd6a1038ed9da8daf331a41e2e763aed5b1fd1a8601de0f0ae34eb05162e34b0389ae3418ee" + "dbf762f64959634a968313a6516dba3a97b34efba4753bbed3a33d409ecbd45ac75007cd8e9101"); + // signed action's hash + ASSERT_EQ(hex(output.hash()), + "8816e8f784a1fce40b54d1cd172bb6976fd9552f1570c73d1d9fcdc5635424a9"); + input.release_stakerestake(); + output.release_encoded(); + output.release_hash(); + } + { // sign stakechangecandidate + auto action = input.mutable_stakechangecandidate(); + action->set_bucketindex(10); + action->set_candidatename("io1xpq62aw85uqzrccg9y5hnryv8ld2nkpycc3gza"); + action->set_payload("payload"); + ANY_SIGN(input, TWCoinTypeIoTeX); + ASSERT_EQ( + hex(output.encoded()), + "0a43080118c0843d22023130ea0236080a1229696f3178707136326177383575717a7263636739793568" + "6e727976386c64326e6b7079636333677a611a077061796c6f6164124104755ce6d8903f6b3793bddb4e" + "a5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef3" + "0dd6a1038ed9da8daf331a41d519eb3747163b945b862989b7e82a7f8468001e9683757cb88d5ddd95f8" + "1895047429e858bd48f7d59a88bfec92de231d216293aeba1e4fbe11461d9c9fc99801"); + // signed action's hash + ASSERT_EQ(hex(output.hash()), + "186526b5b9fe74e25beb52c83c41780a69108160bef2ddaf3bffb9f1f1e5e73a"); + input.release_stakechangecandidate(); + output.release_encoded(); + output.release_hash(); + } + { // sign staketransfer + auto action = input.mutable_staketransferownership(); + action->set_bucketindex(10); + action->set_voteraddress("io1xpq62aw85uqzrccg9y5hnryv8ld2nkpycc3gza"); + action->set_payload("payload"); + ANY_SIGN(input, TWCoinTypeIoTeX); + ASSERT_EQ( + hex(output.encoded()), + "0a43080118c0843d22023130f20236080a1229696f3178707136326177383575717a7263636739793568" + "6e727976386c64326e6b7079636333677a611a077061796c6f6164124104755ce6d8903f6b3793bddb4e" + "a5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef3" + "0dd6a1038ed9da8daf331a41fa26db427ab87a56a129196c1604f2e22c4dd2a1f99b2217bc916260757d" + "00093d9e6dccdf53e3b0b64e41a69d71c238fbf9281625164694a74dfbeba075d0ce01"); + // signed action's hash + ASSERT_EQ(hex(output.hash()), + "74b2e1d6a09ba5d1298fa422d5850991ae516865077282196295a38f93c78b85"); + input.release_staketransferownership(); + output.release_encoded(); + output.release_hash(); + } + { // sign candidateupdate + auto action = input.mutable_candidateupdate(); + action->set_name("test"); + action->set_operatoraddress("io1cl6rl2ev5dfa988qmgzg2x4hfazmp9vn2g66ng"); + action->set_rewardaddress("io1juvx5g063eu4ts832nukp4vgcwk2gnc5cu9ayd"); + ANY_SIGN(input, TWCoinTypeIoTeX); + ASSERT_EQ( + hex(output.encoded()), + "0a69080118c0843d2202313082035c0a04746573741229696f31636c36726c3265763564666139383871" + "6d677a673278346866617a6d7039766e326736366e671a29696f316a7576783567303633657534747338" + "33326e756b7034766763776b32676e6335637539617964124104755ce6d8903f6b3793bddb4ea5d3589d" + "637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99a5c1335b583c0bc76ef30dd6a103" + "8ed9da8daf331a4101885c9c6684a4a8f2f5bf11f8326f27be48658f292e8f55ec8a11a604bb0c563a11" + "ebf12d995ca1c152e00f8e0f0edf288db711aa10dbdfd5b7d73b4a28e1f701"); + // signed action's hash + ASSERT_EQ(hex(output.hash()), + "ca1a28f0e9a58ffc67037cc75066dbdd8e024aa2b2e416e4d6ce16c3d86282e5"); + input.release_candidateupdate(); + output.release_encoded(); + output.release_hash(); + } + { // sign candidateregister + input.set_gasprice("1000"); + auto cbi = input.mutable_candidateregister()->mutable_candidate(); + cbi->set_name("test"); + cbi->set_operatoraddress("io10a298zmzvrt4guq79a9f4x7qedj59y7ery84he"); + cbi->set_rewardaddress("io13sj9mzpewn25ymheukte4v39hvjdtrfp00mlyv"); - // staking is implemented using the Execution message - auto staking = input.mutable_call(); - staking->set_amount("456"); - staking->set_contract(IOTEX_STAKING_CONTRACT); - - // call staking API to generate calldata - Data moveStake; - stakingMoveStake(pyggyIndex01, candidate12, Data{}, moveStake); - staking->set_data(moveStake.data(), moveStake.size()); - - auto signer = IoTeX::Signer(std::move(input)); - // raw action's hash - ASSERT_EQ(hex(signer.hash()), "818637b9708ec9e075c7a17f23757cb6895eae6dd3331f7e44129efae6ca9a21"); - // build() signs the tx - auto output = signer.build(); - // signed action's hash - ASSERT_EQ(hex(output.hash()), "33290ded342efaebf795855be73d34cbac149a2415ff9558de10303e6126f30d"); + auto action = input.mutable_candidateregister(); + action->set_stakedamount("100"); + action->set_stakedduration(10000); + action->set_autostake(false); + action->set_owneraddress("io19d0p3ah4g8ww9d7kcxfq87yxe7fnr8rpth5shj"); + action->set_payload("payload"); + ANY_SIGN(input, TWCoinTypeIoTeX); + ASSERT_EQ(hex(output.encoded()), + "0aaa01080118c0843d220431303030fa029a010a5c0a04746573741229696f3130613239387a6d7a" + "7672743467" + "757137396139663478377165646a35397937657279383468651a29696f3133736a396d7a7065776e" + "3235796d68" + "65756b74653476333968766a647472667030306d6c7976120331303018904e2a29696f3139643070" + "3361683467" + "3877773964376b63786671383779786537666e7238727074683573686a32077061796c6f61641241" + "04755ce6d8" + "903f6b3793bddb4ea5d3589d637de2d209ae0ea930815c82db564ee8cc448886f639e8a0c7e94e99" + "a5c1335b58" + "3c0bc76ef30dd6a1038ed9da8daf331a417819b5bcb635e3577acc8ca757f2c3d6afa451c2b6ff8a" + "9179b141ac" + "68e2c50305679e5d09d288da6f0fb52876a86c74deab6a5247edc6d371de5c2f121e159400"); + // signed action's hash + ASSERT_EQ(hex(output.hash()), + "35f53a536e014b32b85df50483ef04849b80ad60635b3b1979c5ba1096b65237"); + } } diff --git a/tests/IoTeX/TWIoTeXStakingTests.cpp b/tests/IoTeX/TWIoTeXStakingTests.cpp deleted file mode 100644 index 502e5dc62f9..00000000000 --- a/tests/IoTeX/TWIoTeXStakingTests.cpp +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright © 2017-2020 Trust Wallet. -// -// This file is part of Trust. The full Trust copyright notice, including -// terms governing use, modification, and redistribution, is contained in the -// file LICENSE at the root of the source code distribution tree. - -#include "Data.h" -#include "HexCoding.h" -#include "PrivateKey.h" -#include "IoTeX/Signer.h" -#include "proto/IoTeX.pb.h" -#include "../interface/TWTestUtilities.h" - -#include - -using namespace TW; -using namespace TW::IoTeX; - -static const char *_Nonnull IOTEX_STAKING_CONTRACT = "io1xpq62aw85uqzrccg9y5hnryv8ld2nkpycc3gza"; -static const char * IOTEX_STAKING_TEST = "this is a test"; - -TEST(TWIoTeXStaking, SignStake) { - auto input = Proto::SigningInput(); - input.set_version(1); - input.set_nonce(123); - input.set_gaslimit(888); - input.set_gasprice("999"); - auto keyhex = parse_hex("0806c458b262edd333a191e92f561aff338211ee3e18ab315a074a2d82aa343f"); - input.set_privatekey(keyhex.data(), keyhex.size()); - - auto& staking = *input.mutable_staking(); - staking.set_amount("456"); - staking.set_contract(IOTEX_STAKING_CONTRACT); - - auto name = Data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; - auto candidate = std::string(name.begin(), name.end()); - auto& stake = *staking.mutable_stake(); - stake.set_candidate(candidate); - stake.set_duration(1001); - stake.set_nondecay(true); - stake.set_data(IOTEX_STAKING_TEST); - - auto signer = IoTeX::Signer(std::move(input)); - // raw action's hash - ASSERT_EQ(hex(signer.hash()), "cc3c8f7a0129455d70457c4be42a8b31d8e1df59594c99041b6b6d091b295b32"); - // build() signs the tx - auto output = signer.build(); - // signed action's serialized bytes - auto encoded = output.encoded(); - ASSERT_EQ(hex(encoded.begin(), encoded.end()), "0a86020801107b18f806220339393962f7010a033435361229696f3178707136326177383575717a72636367397935686e727976386c64326e6b7079636333677a611ac40107c35fc00102030405060708090a0b0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000e74686973206973206120746573740000000000000000000000000000000000001241044e18306ae9ef4ec9d07bf6e705442d4d1a75e6cdf750330ca2d880f2cc54607c9c33deb9eae9c06e06e04fe9ce3d43962cc67d5aa34fbeb71270d4bad3d648d91a41a558bc9a4bfba920242ccd4d5c5da363ec534d4dd5eb67f88e9db7aaad5c50ad62dfe298c0e54e311ebba045f48cea1136e42a123a8e6b03d3e6ed82d4ec2b9401"); - // signed action's hash - ASSERT_EQ(hex(output.hash()), "41b1f8be5f6b884c06556fba2611716e8e514b507f5a653fc02ac50ba13fbd6c"); -} - -TEST(TWIoTeXStaking, SignUnstake) { - auto input = Proto::SigningInput(); - input.set_version(1); - input.set_nonce(123); - input.set_gaslimit(888); - input.set_gasprice("999"); - auto keyhex = parse_hex("0806c458b262edd333a191e92f561aff338211ee3e18ab315a074a2d82aa343f"); - input.set_privatekey(keyhex.data(), keyhex.size()); - - auto& staking = *input.mutable_staking(); - staking.set_amount("456"); - staking.set_contract(IOTEX_STAKING_CONTRACT); - - auto& unstake = *staking.mutable_unstake(); - unstake.set_piggy_index(1001); - - auto signer = IoTeX::Signer(std::move(input)); - // raw action's hash - ASSERT_EQ(hex(signer.hash()), "784f3d71246dfe897c1cb02da94e8ef1ac2381ac7f25ecfee80eaa78237db95b"); - // build() signs the tx - auto output = signer.build(); - // signed action's hash - ASSERT_EQ(hex(output.hash()), "b93a2874a72ce4eb8a41a20c209cf3fd188671ed8be8239a57960cbed887e962"); -} - -TEST(TWIoTeXStaking, SignWithdraw) { - auto input = Proto::SigningInput(); - input.set_version(1); - input.set_nonce(123); - input.set_gaslimit(888); - input.set_gasprice("999"); - auto keyhex = parse_hex("0806c458b262edd333a191e92f561aff338211ee3e18ab315a074a2d82aa343f"); - input.set_privatekey(keyhex.data(), keyhex.size()); - - auto& staking = *input.mutable_staking(); - staking.set_amount("456"); - staking.set_contract(IOTEX_STAKING_CONTRACT); - - auto& withdraw = *staking.mutable_withdraw(); - withdraw.set_piggy_index(1001); - - auto signer = IoTeX::Signer(std::move(input)); - // raw action's hash - ASSERT_EQ(hex(signer.hash()), "ff55882624b2a1d6ae2d9fdec5f8a0f13b2f23c8b28c8ba91773b63f49b97fcc"); - // build() signs the tx - auto output = signer.build(); - // signed action's hash - ASSERT_EQ(hex(output.hash()), "2b2657247a72cb262de214b4e793c7a01fa2139fd5d12a46d43c24f87f9e2396"); -} - -TEST(TWIoTeXStaking, SignAddStake) { - auto input = Proto::SigningInput(); - input.set_version(1); - input.set_nonce(123); - input.set_gaslimit(888); - input.set_gasprice("999"); - auto keyhex = parse_hex("0806c458b262edd333a191e92f561aff338211ee3e18ab315a074a2d82aa343f"); - input.set_privatekey(keyhex.data(), keyhex.size()); - - auto& staking = *input.mutable_staking(); - staking.set_amount("456"); - staking.set_contract(IOTEX_STAKING_CONTRACT); - - auto& add = *staking.mutable_addstake(); - add.set_piggy_index(1001); - - auto signer = IoTeX::Signer(std::move(input)); - // raw action's hash - ASSERT_EQ(hex(signer.hash()), "7581e7f779429aa502879581fdc29f87917acfe638069255b6f033c45d7f24fe"); - // build() signs the tx - auto output = signer.build(); - // signed action's hash - ASSERT_EQ(hex(output.hash()), "c71058812a5febe5cdcdaf9499ba0b2c895f88d1acd3203e5097b307c2a5f1d1"); -} - -TEST(TWIoTeXStaking, SignMoveStake) { - auto input = Proto::SigningInput(); - input.set_version(1); - input.set_nonce(123); - input.set_gaslimit(888); - input.set_gasprice("999"); - auto keyhex = parse_hex("0806c458b262edd333a191e92f561aff338211ee3e18ab315a074a2d82aa343f"); - input.set_privatekey(keyhex.data(), keyhex.size()); - - auto& staking = *input.mutable_staking(); - staking.set_amount("456"); - staking.set_contract(IOTEX_STAKING_CONTRACT); - - auto name = Data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; - auto candidate = std::string(name.begin(), name.end()); - auto& move = *staking.mutable_movestake(); - move.set_candidate(candidate); - move.set_piggy_index(1001); - - auto signer = IoTeX::Signer(std::move(input)); - // raw action's hash - ASSERT_EQ(hex(signer.hash()), "818637b9708ec9e075c7a17f23757cb6895eae6dd3331f7e44129efae6ca9a21"); - // build() signs the tx - auto output = signer.build(); - // signed action's hash - ASSERT_EQ(hex(output.hash()), "33290ded342efaebf795855be73d34cbac149a2415ff9558de10303e6126f30d"); -} diff --git a/tests/Keystore/Data/ethereum-wallet-address-no-0x.json b/tests/Keystore/Data/ethereum-wallet-address-no-0x.json index 87f0f870863..43cc9c51a9a 100644 --- a/tests/Keystore/Data/ethereum-wallet-address-no-0x.json +++ b/tests/Keystore/Data/ethereum-wallet-address-no-0x.json @@ -1 +1,25 @@ -{"activeAccounts":[{"address":"Ac1ec44E4f0ca7D172B7803f6836De87Fb72b309","derivationPath":"m/44'/60'/0'/0/0"}],"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"630d0a62bc8a6187c47fdb6c8b7bd38c"},"ciphertext":"4ec6d0157bde53900020d45c9db9235acdb366f727fe456b5a4536f20ea0848c","kdf":"scrypt","kdfparams":{"dklen":32,"n":4096,"p":6,"r":8,"salt":"4c3d38c0d114cb92b2cb4a44e92e27cf588f9ecd59840c8dea087e89d350d836"},"mac":"9748b96453a03bcdec2e714153d8d69f16cde7d398750932281f68844a6b2616"},"id":"48aa6b37-8276-44fe-aa4e-819145771183","type":"private-key","version":3} \ No newline at end of file +{ + "activeAccounts": [{ + "address": "Ac1ec44E4f0ca7D172B7803f6836De87Fb72b309", + "derivationPath": "m/44'/60'/0'/0/0" + }], + "crypto": { + "cipher": "aes-128-ctr", + "cipherparams": { + "iv": "630d0a62bc8a6187c47fdb6c8b7bd38c" + }, + "ciphertext": "4ec6d0157bde53900020d45c9db9235acdb366f727fe456b5a4536f20ea0848c", + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "n": 4096, + "p": 6, + "r": 8, + "salt": "4c3d38c0d114cb92b2cb4a44e92e27cf588f9ecd59840c8dea087e89d350d836" + }, + "mac": "9748b96453a03bcdec2e714153d8d69f16cde7d398750932281f68844a6b2616" + }, + "id": "48aa6b37-8276-44fe-aa4e-819145771183", + "type": "private-key", + "version": 3 +} \ No newline at end of file diff --git a/tests/Keystore/Data/myetherwallet.uu b/tests/Keystore/Data/myetherwallet.uu index 10e2dab212d..751f16207e5 100755 --- a/tests/Keystore/Data/myetherwallet.uu +++ b/tests/Keystore/Data/myetherwallet.uu @@ -1 +1,21 @@ -{"version":3,"id":"beb60dc6-7553-4215-9aa7-4b26883da373","address":"8562fcccbae3019f5a716997609b301ac31fe04a","Crypto":{"ciphertext":"ed9de8b5568bac97c8199b82b197b61977440d360acec2ecf4f74f3da91308ab","cipherparams":{"iv":"cf6730826d91ce908aa15771952ab3e8"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"dklen":32,"salt":"2904ecde7e2e5c6cb89291b2741bdd3dff3088f98a7013d63084c746efd7524f","n":1024,"r":8,"p":1},"mac":"cdb237916f98742d4e8f313638e16b04a4a780e69dd61c6407932be42d269c95"}} \ No newline at end of file +{ + "version": 3, + "id": "beb60dc6-7553-4215-9aa7-4b26883da373", + "address": "8562fcccbae3019f5a716997609b301ac31fe04a", + "Crypto": { + "ciphertext": "ed9de8b5568bac97c8199b82b197b61977440d360acec2ecf4f74f3da91308ab", + "cipherparams": { + "iv": "cf6730826d91ce908aa15771952ab3e8" + }, + "cipher": "aes-128-ctr", + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "salt": "2904ecde7e2e5c6cb89291b2741bdd3dff3088f98a7013d63084c746efd7524f", + "n": 1024, + "r": 8, + "p": 1 + }, + "mac": "cdb237916f98742d4e8f313638e16b04a4a780e69dd61c6407932be42d269c95" + } +} \ No newline at end of file diff --git a/tests/Keystore/Data/web3j.json b/tests/Keystore/Data/web3j.json new file mode 100644 index 00000000000..b47dc6a2d51 --- /dev/null +++ b/tests/Keystore/Data/web3j.json @@ -0,0 +1,21 @@ +{ + "address": "34bae2218c254ed190c0f5b1dd4323aee8e7da09", + "id": "86066d8c-8dba-4d81-afd4-934e2a2b72a2", + "version": 3, + "crypto": { + "cipher": "aes-128-ctr", + "cipherparams": { + "iv": "a4976ad73057007ad788d1f792db851d" + }, + "ciphertext": "5e4458d69964172c492616b751d6589b4ad7da4217dcfccecc3f4e515a934bb8", + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "n": 4096, + "p": 6, + "r": 8, + "salt": "24c72d92bf88a4f7c7b3f5e3cb3620714d71fceabbb0bc6099f50c6d5d898e7c" + }, + "mac": "c15e3035ddcaca766dfc56648978d33e94d3c57d4a5e13fcf8b5f8dbb0902900" + } +} \ No newline at end of file diff --git a/tests/Keystore/StoredKeyTests.cpp b/tests/Keystore/StoredKeyTests.cpp index d5648c661e8..5e385323ac0 100644 --- a/tests/Keystore/StoredKeyTests.cpp +++ b/tests/Keystore/StoredKeyTests.cpp @@ -8,6 +8,7 @@ #include "Coin.h" #include "HexCoding.h" +#include "Data.h" #include "PrivateKey.h" #include @@ -19,7 +20,8 @@ namespace TW::Keystore { using namespace std; -const auto password = "password"; +const auto passwordString = "password"; +const auto password = TW::data(string(passwordString)); const auto mnemonic = "team engine square letter hero song dizzy scrub tornado fabric divert saddle"; const TWCoinType coinTypeBc = TWCoinTypeBitcoin; @@ -176,14 +178,14 @@ TEST(StoredKey, LoadLegacyPrivateKey) { const auto key = StoredKey::load(TESTS_ROOT + "/Keystore/Data/legacy-private-key.json"); EXPECT_EQ(key.id, "3051ca7d-3d36-4a4a-acc2-09e9083732b0"); EXPECT_EQ(key.accounts[0].coin(), TWCoinTypeEthereum); - EXPECT_EQ(hex(key.payload.decrypt("testpassword")), "7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d"); + EXPECT_EQ(hex(key.payload.decrypt(TW::data("testpassword"))), "7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d"); } TEST(StoredKey, LoadLivepeerKey) { const auto key = StoredKey::load(TESTS_ROOT + "/Keystore/Data/livepeer.json"); EXPECT_EQ(key.id, "70ea3601-ee21-4e94-a7e4-66255a987d22"); EXPECT_EQ(key.accounts[0].coin(), TWCoinTypeEthereum); - EXPECT_EQ(hex(key.payload.decrypt("Radchenko")), "09b4379d9a41a71d94ee36357bccb4d77b45e7fd9307e2c0f673dd54c0558c73"); + EXPECT_EQ(hex(key.payload.decrypt(TW::data("Radchenko"))), "09b4379d9a41a71d94ee36357bccb4d77b45e7fd9307e2c0f673dd54c0558c73"); } TEST(StoredKey, LoadPBKDF2Key) { @@ -196,7 +198,7 @@ TEST(StoredKey, LoadPBKDF2Key) { EXPECT_EQ(boost::get(payload.kdfParams).iterations, 262144); EXPECT_EQ(hex(boost::get(payload.kdfParams).salt), "ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd"); - EXPECT_EQ(hex(payload.decrypt("testpassword")), "7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d"); + EXPECT_EQ(hex(payload.decrypt(TW::data("testpassword"))), "7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d"); } TEST(StoredKey, LoadLegacyMnemonic) { @@ -216,6 +218,14 @@ TEST(StoredKey, LoadLegacyMnemonic) { EXPECT_EQ(key.accounts[1].extendedPublicKey, "zpub6r97AegwVxVbJeuDAWP5KQgX5y4Q6KyFUrsFQRn8yzSXrnmpwg1ZKHSWwECR1Kiqgr4h93WN5kdS48KC6hVFniuZHqVFXjULZZkCwurqyPn"); } +TEST(StoredKey, LoadFromWeb3j) { + const auto key = StoredKey::load(TESTS_ROOT + "/Keystore/Data/web3j.json"); + EXPECT_EQ(key.id, "86066d8c-8dba-4d81-afd4-934e2a2b72a2"); + const auto password = parse_hex("2d6eefbfbd4622efbfbdefbfbd516718efbfbdefbfbdefbfbdefbfbd59efbfbd30efbfbdefbfbd3a4348efbfbd2aefbfbdefbfbd49efbfbd27efbfbd0638efbfbdefbfbdefbfbd4cefbfbd6befbfbdefbfbd6defbfbdefbfbd63efbfbd5aefbfbd61262b70efbfbdefbfbdefbfbdefbfbdefbfbdc7aa373163417cefbfbdefbfbdefbfbd44efbfbdefbfbd1d10efbfbdefbfbdefbfbd61dc9e5b124befbfbd11efbfbdefbfbd2fefbfbdefbfbd3d7c574868efbfbdefbfbdefbfbd37043b7b5c1a436471592f02efbfbd18efbfbdefbfbd2befbfbdefbfbd7218efbfbd6a68efbfbdcb8e5f3328773ec48174efbfbd67efbfbdefbfbdefbfbdefbfbdefbfbd2a31efbfbd7f60efbfbdd884efbfbd57efbfbd25efbfbd590459efbfbd37efbfbd2bdca20fefbfbdefbfbdefbfbdefbfbd39450113efbfbdefbfbdefbfbd454671efbfbdefbfbdd49fefbfbd47efbfbdefbfbdefbfbdefbfbd00efbfbdefbfbdefbfbdefbfbd05203f4c17712defbfbd7bd1bbdc967902efbfbdc98a77efbfbd707a36efbfbd12efbfbdefbfbd57c78cefbfbdefbfbdefbfbd10efbfbdefbfbdefbfbde1a1bb08efbfbdefbfbd26efbfbdefbfbd58efbfbdefbfbdc4b1efbfbd295fefbfbd0eefbfbdefbfbdefbfbd0e6eefbfbd"); + const auto data = key.payload.decrypt(password); + EXPECT_EQ(hex(data), "043c5429c7872502531708ec0d821c711691402caf37ef7ba78a8c506f10653b"); +} + TEST(StoredKey, ReadWallet) { const auto key = StoredKey::load(TESTS_ROOT + "/Keystore/Data/key.json"); @@ -250,12 +260,12 @@ TEST(StoredKey, InvalidPassword) { TEST(StoredKey, EmptyAccounts) { const auto key = StoredKey::load(TESTS_ROOT + "/Keystore/Data/empty-accounts.json"); - ASSERT_NO_THROW(key.payload.decrypt("testpassword")); + ASSERT_NO_THROW(key.payload.decrypt(TW::data("testpassword"))); } TEST(StoredKey, Decrypt) { const auto key = StoredKey::load(TESTS_ROOT + "/Keystore/Data/key.json"); - const auto privateKey = key.payload.decrypt("testpassword"); + const auto privateKey = key.payload.decrypt(TW::data("testpassword")); EXPECT_EQ(hex(privateKey), "7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d"); } @@ -310,7 +320,7 @@ TEST(StoredKey, MissingAddress) { TEST(StoredKey, EtherWalletAddressNo0x) { auto key = StoredKey::load(TESTS_ROOT + "/Keystore/Data/ethereum-wallet-address-no-0x.json"); - key.fixAddresses("15748c4e3dca6ae2110535576ab0c398cb79d985707c68ee6c9f9df9d421dd53"); + key.fixAddresses(TW::data("15748c4e3dca6ae2110535576ab0c398cb79d985707c68ee6c9f9df9d421dd53")); EXPECT_EQ(key.account(TWCoinTypeEthereum, nullptr)->address, "0xAc1ec44E4f0ca7D172B7803f6836De87Fb72b309"); } diff --git a/tests/Stellar/TWCoinTypeTests.cpp b/tests/Stellar/TWCoinTypeTests.cpp index a93bbfdbefa..52397d75d8a 100644 --- a/tests/Stellar/TWCoinTypeTests.cpp +++ b/tests/Stellar/TWCoinTypeTests.cpp @@ -15,9 +15,9 @@ TEST(TWStellarCoinType, TWCoinType) { auto symbol = WRAPS(TWCoinTypeConfigurationGetSymbol(TWCoinTypeStellar)); - auto txId = TWStringCreateWithUTF8Bytes("t123"); + auto txId = TWStringCreateWithUTF8Bytes("d9aeabfa9d24df8c5755125f8af243b74cd3ff878656cfa72c566a8824bf6e84"); auto txUrl = WRAPS(TWCoinTypeConfigurationGetTransactionURL(TWCoinTypeStellar, txId)); - auto accId = TWStringCreateWithUTF8Bytes("a12"); + auto accId = TWStringCreateWithUTF8Bytes("GCILJZQ3CKBKBUJWW4TAM6Q37LJA5MQX6GMSFSQN75BPLWIZ33OPRG52"); auto accUrl = WRAPS(TWCoinTypeConfigurationGetAccountURL(TWCoinTypeStellar, accId)); auto id = WRAPS(TWCoinTypeConfigurationGetID(TWCoinTypeStellar)); auto name = WRAPS(TWCoinTypeConfigurationGetName(TWCoinTypeStellar)); @@ -27,8 +27,8 @@ TEST(TWStellarCoinType, TWCoinType) { ASSERT_EQ(0x0, TWCoinTypeP2shPrefix(TWCoinTypeStellar)); ASSERT_EQ(0x0, TWCoinTypeStaticPrefix(TWCoinTypeStellar)); assertStringsEqual(symbol, "XLM"); - assertStringsEqual(txUrl, "https://stellarscan.io/transaction/t123"); - assertStringsEqual(accUrl, "https://stellarscan.io/account/a12"); + assertStringsEqual(txUrl, "https://blockchair.com/stellar/transaction/d9aeabfa9d24df8c5755125f8af243b74cd3ff878656cfa72c566a8824bf6e84"); + assertStringsEqual(accUrl, "https://blockchair.com/stellar/account/GCILJZQ3CKBKBUJWW4TAM6Q37LJA5MQX6GMSFSQN75BPLWIZ33OPRG52"); assertStringsEqual(id, "stellar"); assertStringsEqual(name, "Stellar"); } diff --git a/tests/Zcash/TWCoinTypeTests.cpp b/tests/Zcash/TWCoinTypeTests.cpp index fc887dd9891..da6af47b0d6 100644 --- a/tests/Zcash/TWCoinTypeTests.cpp +++ b/tests/Zcash/TWCoinTypeTests.cpp @@ -15,9 +15,9 @@ TEST(TWZcashCoinType, TWCoinType) { auto symbol = WRAPS(TWCoinTypeConfigurationGetSymbol(TWCoinTypeZcash)); - auto txId = TWStringCreateWithUTF8Bytes("t123"); + auto txId = TWStringCreateWithUTF8Bytes("f2438a93039faf08d39bd3df1f7b5f19a2c29ffe8753127e2956ab4461adab35"); auto txUrl = WRAPS(TWCoinTypeConfigurationGetTransactionURL(TWCoinTypeZcash, txId)); - auto accId = TWStringCreateWithUTF8Bytes("a12"); + auto accId = TWStringCreateWithUTF8Bytes("t1Yfrf1dssDLmaMBsq2LFKWPbS5vH3nGpa2"); auto accUrl = WRAPS(TWCoinTypeConfigurationGetAccountURL(TWCoinTypeZcash, accId)); auto id = WRAPS(TWCoinTypeConfigurationGetID(TWCoinTypeZcash)); auto name = WRAPS(TWCoinTypeConfigurationGetName(TWCoinTypeZcash)); @@ -27,8 +27,8 @@ TEST(TWZcashCoinType, TWCoinType) { ASSERT_EQ(0xbd, TWCoinTypeP2shPrefix(TWCoinTypeZcash)); ASSERT_EQ(0x1c, TWCoinTypeStaticPrefix(TWCoinTypeZcash)); assertStringsEqual(symbol, "ZEC"); - assertStringsEqual(txUrl, "https://sochain.com/tx/ZEC/t123"); - assertStringsEqual(accUrl, "https://sochain.com/address/ZEC/a12"); + assertStringsEqual(txUrl, "https://blockchair.com/zcash/transaction/f2438a93039faf08d39bd3df1f7b5f19a2c29ffe8753127e2956ab4461adab35"); + assertStringsEqual(accUrl, "https://blockchair.com/zcash/address/t1Yfrf1dssDLmaMBsq2LFKWPbS5vH3nGpa2"); assertStringsEqual(id, "zcash"); assertStringsEqual(name, "Zcash"); } diff --git a/tests/interface/TWAnyAddressTests.cpp b/tests/interface/TWAnyAddressTests.cpp index c35b6935a79..dbc77477d5d 100644 --- a/tests/interface/TWAnyAddressTests.cpp +++ b/tests/interface/TWAnyAddressTests.cpp @@ -119,4 +119,11 @@ TEST(AnyAddress, Data) { auto keyHash = WRAPD(TWAnyAddressData(addr.get())); assertHexEqual(keyHash, "172bdf43265c0adfe105a1a8c45b3f406a38362f24"); } + // elrond + { + auto string = STRING("erd1l453hd0gt5gzdp7czpuall8ggt2dcv5zwmfdf3sd3lguxseux2fsmsgldz"); + auto addr = WRAP(TWAnyAddress, TWAnyAddressCreateWithString(string.get(), TWCoinTypeElrond)); + auto pubkey = WRAPD(TWAnyAddressData(addr.get())); + assertHexEqual(pubkey, "fd691bb5e85d102687d81079dffce842d4dc328276d2d4c60d8fd1c3433c3293"); + } } diff --git a/tests/interface/TWHDWalletTests.cpp b/tests/interface/TWHDWalletTests.cpp index 62f67695f0e..6b286eee3cb 100644 --- a/tests/interface/TWHDWalletTests.cpp +++ b/tests/interface/TWHDWalletTests.cpp @@ -231,6 +231,16 @@ TEST(HDWallet, DeriveAlgorand) { assertHexEqual(privateKeyData, "ce0b7ac644e2b7d9d14d3928b11643f43e48c33d3e328d059fef8add7f070e82"); } +TEST(HDWallet, DeriveElrond) { + auto wallet = WRAP(TWHDWallet, TWHDWalletCreateWithMnemonic(words.get(), passphrase.get())); + auto privateKey = WRAP(TWPrivateKey, TWHDWalletGetKeyForCoin(wallet.get(), TWCoinTypeElrond)); + auto privateKeyData = WRAPD(TWPrivateKeyData(privateKey.get())); + auto address = WRAPS(TWCoinTypeDeriveAddress(TWCoinTypeElrond, privateKey.get())); + + assertHexEqual(privateKeyData, "0eb593141de897d60a0883320793eb49e63d556ccdf783a87ec014f150d50453"); + assertStringsEqual(address, "erd1a6l7q9cfvrgr80xuzm37tapdr4zm3mwrtl6vt8f45df45x7eadfs8ds5vv"); +} + TEST(HDWallet, ExtendedKeys) { auto words = STRING("abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"); auto wallet = WRAP(TWHDWallet, TWHDWalletCreateWithMnemonic(words.get(), STRING("").get())); diff --git a/tests/interface/TWHRPTests.cpp b/tests/interface/TWHRPTests.cpp index 11af1a19e50..3b04ad4f8c3 100644 --- a/tests/interface/TWHRPTests.cpp +++ b/tests/interface/TWHRPTests.cpp @@ -28,6 +28,7 @@ TEST(TWHRP, StringForHRP) { ASSERT_STREQ(stringForHRP(TWHRPMonacoin), "mona"); ASSERT_STREQ(stringForHRP(TWHRPKava), "kava"); ASSERT_STREQ(stringForHRP(TWHRPCardano), "addr"); + ASSERT_STREQ(stringForHRP(TWHRPElrond), "erd"); } TEST(TWHRP, HRPForString) { @@ -47,6 +48,7 @@ TEST(TWHRP, HRPForString) { ASSERT_EQ(hrpForString("mona"), TWHRPMonacoin); ASSERT_EQ(hrpForString("kava"), TWHRPKava); ASSERT_EQ(hrpForString("addr"), TWHRPCardano); + ASSERT_EQ(hrpForString("erd"), TWHRPElrond); } TEST(TWHPR, HPRByCoinType) { @@ -65,6 +67,7 @@ TEST(TWHPR, HPRByCoinType) { ASSERT_EQ(TWHRPMonacoin, TWCoinTypeHRP(TWCoinTypeMonacoin)); ASSERT_EQ(TWHRPKava, TWCoinTypeHRP(TWCoinTypeKava)); ASSERT_EQ(TWHRPCardano, TWCoinTypeHRP(TWCoinTypeCardano)); + ASSERT_EQ(TWHRPElrond, TWCoinTypeHRP(TWCoinTypeElrond)); ASSERT_EQ(TWHRPUnknown, TWCoinTypeHRP(TWCoinTypeAion)); ASSERT_EQ(TWHRPUnknown, TWCoinTypeHRP(TWCoinTypeCallisto)); diff --git a/tests/interface/TWStoredKeyTests.cpp b/tests/interface/TWStoredKeyTests.cpp index b769752db9b..1f4aca4262b 100644 --- a/tests/interface/TWStoredKeyTests.cpp +++ b/tests/interface/TWStoredKeyTests.cpp @@ -10,7 +10,7 @@ #include #include #include - +#include #include "../src/HexCoding.h" #include @@ -24,17 +24,19 @@ using namespace std; /// Return a StoredKey instance that can be used for further tests. Needs to be deleted at the end. -struct TWStoredKey *_Nonnull createAStoredKey(TWCoinType coin, const string& password) { +struct TWStoredKey *_Nonnull createAStoredKey(TWCoinType coin, TWData* password) { const auto mnemonic = WRAPS(TWStringCreateWithUTF8Bytes("team engine square letter hero song dizzy scrub tornado fabric divert saddle")); const auto name = WRAPS(TWStringCreateWithUTF8Bytes("name")); - const auto password2 = WRAPS(TWStringCreateWithUTF8Bytes(password.c_str())); - const auto key = TWStoredKeyImportHDWallet(mnemonic.get(), name.get(), password2.get(), coin); + const auto key = TWStoredKeyImportHDWallet(mnemonic.get(), name.get(), password, coin); return key; } /// Return a StoredKey instance that can be used for further tests. Needs to be deleted at the end. struct TWStoredKey *_Nonnull createDefaultStoredKey() { - return createAStoredKey(TWCoinTypeBitcoin, "password"); + const auto passwordString = WRAPS(TWStringCreateWithUTF8Bytes("password")); + const auto password = WRAPD(TWDataCreateWithBytes(reinterpret_cast(TWStringUTF8Bytes(passwordString.get())), TWStringSize(passwordString.get()))); + + return createAStoredKey(TWCoinTypeBitcoin, password.get()); } TEST(TWStoredKey, loadPBKDF2Key) { @@ -52,7 +54,8 @@ TEST(TWStoredKey, loadNonexistent) { TEST(TWStoredKey, createWallet) { const auto name = WRAPS(TWStringCreateWithUTF8Bytes("name")); - const auto password = WRAPS(TWStringCreateWithUTF8Bytes("password")); + const auto passwordString = WRAPS(TWStringCreateWithUTF8Bytes("password")); + const auto password = WRAPD(TWDataCreateWithBytes(reinterpret_cast(TWStringUTF8Bytes(passwordString.get())), TWStringSize(passwordString.get()))); const auto key = TWStoredKeyCreate(name.get(), password.get()); const auto name2 = WRAPS(TWStoredKeyName(key)); EXPECT_EQ(string(TWStringUTF8Bytes(name2.get())), "name"); @@ -66,7 +69,8 @@ TEST(TWStoredKey, importPrivateKey) { const auto privateKeyHex = "3a1076bf45ab87712ad64ccb3b10217737f7faacbf2872e88fdd9a537d8fe266"; const auto privateKey = WRAPD(TWDataCreateWithHexString(TWStringCreateWithUTF8Bytes(privateKeyHex))); const auto name = WRAPS(TWStringCreateWithUTF8Bytes("name")); - const auto password = WRAPS(TWStringCreateWithUTF8Bytes("password")); + const auto passwordString = WRAPS(TWStringCreateWithUTF8Bytes("password")); + const auto password = WRAPD(TWDataCreateWithBytes(reinterpret_cast(TWStringUTF8Bytes(passwordString.get())), TWStringSize(passwordString.get()))); const auto coin = TWCoinTypeBitcoin; const auto key = TWStoredKeyImportPrivateKey(privateKey.get(), name.get(), password.get(), coin); const auto privateKey2 = WRAPD(TWStoredKeyDecryptPrivateKey(key, password.get())); @@ -83,7 +87,8 @@ TEST(TWStoredKey, importPrivateKey) { TEST(TWStoredKey, importHDWallet) { const auto mnemonic = WRAPS(TWStringCreateWithUTF8Bytes("team engine square letter hero song dizzy scrub tornado fabric divert saddle")); const auto name = WRAPS(TWStringCreateWithUTF8Bytes("name")); - const auto password = WRAPS(TWStringCreateWithUTF8Bytes("password")); + const auto passwordString = WRAPS(TWStringCreateWithUTF8Bytes("password")); + const auto password = WRAPD(TWDataCreateWithBytes(reinterpret_cast(TWStringUTF8Bytes(passwordString.get())), TWStringSize(passwordString.get()))); const auto coin = TWCoinTypeBitcoin; const auto key = TWStoredKeyImportHDWallet(mnemonic.get(), name.get(), password.get(), coin); EXPECT_TRUE(TWStoredKeyIsMnemonic(key)); @@ -96,11 +101,13 @@ TEST(TWStoredKey, importHDWallet) { } TEST(TWStoredKey, addressAddRemove) { - const auto password = "password"; + const auto passwordString = WRAPS(TWStringCreateWithUTF8Bytes("password")); + const auto password = WRAPD(TWDataCreateWithBytes(reinterpret_cast(TWStringUTF8Bytes(passwordString.get())), TWStringSize(passwordString.get()))); + const auto coin = TWCoinTypeBitcoin; - const auto key = createAStoredKey(coin, password); + const auto key = createAStoredKey(coin, password.get()); - const auto wallet = TWStoredKeyWallet(key, WRAPS(TWStringCreateWithUTF8Bytes(password)).get()); + const auto wallet = TWStoredKeyWallet(key, password.get()); const auto accountCoin = TWStoredKeyAccountForCoin(key, coin, wallet); const auto accountAddress = WRAPS(TWAccountAddress(accountCoin)); EXPECT_EQ(string(TWStringUTF8Bytes(accountAddress.get())), "bc1qturc268v0f2srjh4r2zu4t6zk4gdutqd5a6zny"); @@ -171,9 +178,11 @@ TEST(TWStoredKey, importJsonInvalid) { } TEST(TWStoredKey, fixAddresses) { - const auto password = "password"; - const auto key = createAStoredKey(TWCoinTypeBitcoin, password); - EXPECT_TRUE(TWStoredKeyFixAddresses(key, WRAPS(TWStringCreateWithUTF8Bytes(password)).get())); + const auto passwordString = WRAPS(TWStringCreateWithUTF8Bytes("password")); + const auto password = WRAPD(TWDataCreateWithBytes(reinterpret_cast(TWStringUTF8Bytes(passwordString.get())), TWStringSize(passwordString.get()))); + + const auto key = createAStoredKey(TWCoinTypeBitcoin, password.get()); + EXPECT_TRUE(TWStoredKeyFixAddresses(key, password.get())); TWStoredKeyDelete(key); } @@ -181,10 +190,11 @@ TEST(TWStoredKey, importInvalidKey) { auto bytes = TW::parse_hex("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"); auto data = WRAPD(TWDataCreateWithBytes(bytes.data(), bytes.size())); auto name = WRAPS(TWStringCreateWithUTF8Bytes("test")); + auto password = WRAPD(TWDataCreateWithBytes(reinterpret_cast(TWStringUTF8Bytes(name.get())), TWStringSize(name.get()))); - auto eth = TWStoredKeyImportPrivateKey(data.get(), name.get(), name.get(), TWCoinTypeEthereum); - auto ont = TWStoredKeyImportPrivateKey(data.get(), name.get(), name.get(), TWCoinTypeOntology); - auto tezos = TWStoredKeyImportPrivateKey(data.get(), name.get(), name.get(), TWCoinTypeTezos); + auto eth = TWStoredKeyImportPrivateKey(data.get(), name.get(), password.get(), TWCoinTypeEthereum); + auto ont = TWStoredKeyImportPrivateKey(data.get(), name.get(), password.get(), TWCoinTypeOntology); + auto tezos = TWStoredKeyImportPrivateKey(data.get(), name.get(), password.get(), TWCoinTypeTezos); ASSERT_EQ(eth, nullptr); ASSERT_EQ(ont, nullptr); @@ -192,9 +202,13 @@ TEST(TWStoredKey, importInvalidKey) { } TEST(TWStoredKey, removeAccountForCoin) { - auto password = "password"; - auto key = TWStoredKeyCreate("Test KeyStore", password); - auto wallet = TWStoredKeyWallet(key, password); + const auto name = WRAPS(TWStringCreateWithUTF8Bytes("Test Keystore")); + + const auto passwordString = WRAPS(TWStringCreateWithUTF8Bytes("password")); + const auto password = WRAPD(TWDataCreateWithBytes(reinterpret_cast(TWStringUTF8Bytes(passwordString.get())), TWStringSize(passwordString.get()))); + + auto key = TWStoredKeyCreate(name.get(), password.get()); + auto wallet = TWStoredKeyWallet(key, password.get()); ASSERT_NE(TWStoredKeyAccountForCoin(key, TWCoinTypeEthereum, wallet), nullptr); ASSERT_NE(TWStoredKeyAccountForCoin(key, TWCoinTypeBitcoin, wallet), nullptr); @@ -211,8 +225,12 @@ TEST(TWStoredKey, removeAccountForCoin) { TEST(TWStoredKey, getWalletPasswordInvalid) { const auto name = WRAPS(TWStringCreateWithUTF8Bytes("name")); - const auto password = WRAPS(TWStringCreateWithUTF8Bytes("password")); - const auto passwordInvalid = WRAPS(TWStringCreateWithUTF8Bytes("_THIS_IS_INVALID_PASSWORD_")); + const auto passwordString = WRAPS(TWStringCreateWithUTF8Bytes("password")); + const auto password = WRAPD(TWDataCreateWithBytes(reinterpret_cast(TWStringUTF8Bytes(passwordString.get())), TWStringSize(passwordString.get()))); + + const auto invalidString = WRAPS(TWStringCreateWithUTF8Bytes("_THIS_IS_INVALID_PASSWORD_")); + const auto passwordInvalid = WRAPD(TWDataCreateWithBytes(reinterpret_cast(TWStringUTF8Bytes(invalidString.get())), TWStringSize(invalidString.get()))); + auto key = TWStoredKeyCreate (name.get(), password.get()); ASSERT_NE(TWStoredKeyWallet(key, password.get()), nullptr); ASSERT_EQ(TWStoredKeyWallet(key, passwordInvalid.get()), nullptr); diff --git a/tests/interface/TWTestUtilities.cpp b/tests/interface/TWTestUtilities.cpp index 14d256a89bc..0db28b1ea1a 100644 --- a/tests/interface/TWTestUtilities.cpp +++ b/tests/interface/TWTestUtilities.cpp @@ -7,7 +7,7 @@ #include "TWTestUtilities.h" #include -#include +#include using namespace std; diff --git a/tools/coverage b/tools/coverage index aea89ceac39..a60dd5266d7 100755 --- a/tools/coverage +++ b/tools/coverage @@ -4,7 +4,23 @@ set -e -lcov --capture --directory . --output-file coverage.info +function install_llvm_gcov() { + cat << EOF > /tmp/llvm-gcov.sh +#!/bin/bash +exec /usr/bin/llvm-cov gcov "\$@" +EOF + sudo chmod 755 /tmp/llvm-gcov.sh +} + +if [[ `uname` == "Darwin" ]]; then + echo "gcov is llvm-cov on macOS" + lcov --capture --directory . --output-file coverage.info +else + echo "call llvm-cov on Linux" + install_llvm_gcov + lcov --gcov-tool /tmp/llvm-gcov.sh --capture --directory . --output-file coverage.info +fi + lcov --remove coverage.info '/usr/*' --output-file coverage.info lcov --remove coverage.info '/Applications/*' --output-file coverage.info lcov --remove coverage.info '*/build/*' --output-file coverage.info diff --git a/tools/generate-files b/tools/generate-files index 20079f3c417..523835e157c 100755 --- a/tools/generate-files +++ b/tools/generate-files @@ -59,7 +59,6 @@ fi # Generate internal message protocol Protobuf files -- not every time "$PROTOC" -I=$PREFIX/include -I=src/Tron/Protobuf --cpp_out=src/Tron/Protobuf src/Tron/Protobuf/*.proto "$PROTOC" -I=$PREFIX/include -I=src/Zilliqa/Protobuf --cpp_out=src/Zilliqa/Protobuf src/Zilliqa/Protobuf/*.proto -"$PROTOC" -I=$PREFIX/include -I=src/IoTeX/Protobuf --cpp_out=src/IoTeX/Protobuf src/IoTeX/Protobuf/*.proto # Generate Proto interface file "$PROTOC" -I=$PREFIX/include -I=src/proto --plugin=$PREFIX/bin/protoc-gen-c-typedef --c-typedef_out include/TrustWalletCore src/proto/*.proto diff --git a/tools/install-dependencies b/tools/install-dependencies index 53536a5afd5..5dc7c28ad64 100755 --- a/tools/install-dependencies +++ b/tools/install-dependencies @@ -16,7 +16,7 @@ export LD_RUN_PATH="$PREFIX/lib" # Download Google Test export GTEST_VERSION=1.8.1 -GTEST_DIR="$ROOT/build/gtest/staging" +GTEST_DIR="$ROOT/build/local/src/gtest" mkdir -p "$GTEST_DIR" cd "$GTEST_DIR" if [ ! -f release-$GTEST_VERSION.tar.gz ]; then @@ -26,13 +26,13 @@ tar xzf release-$GTEST_VERSION.tar.gz # Build gtest cd googletest-release-$GTEST_VERSION -cmake -DCMAKE_INSTALL_PREFIX:PATH=$PREFIX -H. +cmake -DCMAKE_INSTALL_PREFIX:PATH=$PREFIX . make make install # Download Check export CHECK_VERSION=0.12.0 -CHECK_DIR="$ROOT/build/check/staging" +CHECK_DIR="$ROOT/build/local/src/check" mkdir -p "$CHECK_DIR" cd "$CHECK_DIR" if [ ! -f check-$CHECK_VERSION.tar.gz ]; then @@ -48,7 +48,7 @@ make install # Download Nlohmann JSON export JSON_VERSION=3.5.0 -JSON_DIR="$ROOT/build/json/staging" +JSON_DIR="$ROOT/build/local/json" mkdir -p "$JSON_DIR" cd "$JSON_DIR" if [ ! -f include.zip ]; then @@ -58,7 +58,7 @@ unzip -d "$PREFIX" -o include.zip # Download Protobuf sources export PROTOBUF_VERSION=3.9.0 -PROTOBUF_DIR="$ROOT/build/protobuf/staging" +PROTOBUF_DIR="$ROOT/build/local/src/protobuf" mkdir -p "$PROTOBUF_DIR" cd "$PROTOBUF_DIR" if [ ! -f protobuf-java-$PROTOBUF_VERSION.tar.gz ]; then @@ -75,10 +75,10 @@ make install make clean "$PREFIX/bin/protoc" --version -if [ -x "$(command -v swift)" ]; then +if [[ -x "$(command -v swift)" && `uname` == "Darwin" ]]; then # Download Swift Protobuf sources export SWIFT_PROTOBUF_VERSION=1.7.0 - SWIFT_PROTOBUF_DIR="$ROOT/build/swift-protobuf/staging" + SWIFT_PROTOBUF_DIR="$ROOT/build/local/src/swift-protobuf" mkdir -p "$SWIFT_PROTOBUF_DIR" cd "$SWIFT_PROTOBUF_DIR" if [ ! -f $SWIFT_PROTOBUF_VERSION.tar.gz ]; then diff --git a/tools/ios-test b/tools/ios-test index 1206d3c57a5..8c68a4b70f9 100755 --- a/tools/ios-test +++ b/tools/ios-test @@ -7,5 +7,5 @@ set -e pushd swift xcodegen pod install -xcrun xcodebuild -workspace TrustWalletCore.xcworkspace -scheme TrustWalletCore -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 11,OS=13.0' test +xcrun xcodebuild -workspace TrustWalletCore.xcworkspace -scheme TrustWalletCore -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 11' test popd diff --git a/tools/lint-cppcheck-all b/tools/lint-cppcheck-all new file mode 100755 index 00000000000..09ee00310bf --- /dev/null +++ b/tools/lint-cppcheck-all @@ -0,0 +1,7 @@ +#!/bin/bash +# +# This script lints all of the C++ code with cppcheck. + +set -e + +find src \( -name "*.cpp" -o -name "*.h" \) -not -path "./src/proto/*" -not -path "./src/Tron/Protobuf/*" -exec cppcheck --force --quiet --enable=all '{}' \; diff --git a/tools/lint-cppcheck-diff b/tools/lint-cppcheck-diff new file mode 100755 index 00000000000..2b568769fea --- /dev/null +++ b/tools/lint-cppcheck-diff @@ -0,0 +1,15 @@ +#!/usr/bin/env ruby +# +# This script lints the files modified in the current branch with cppcheck. + +merge_base = `git merge-base HEAD origin/master`.strip +changed_files = `git diff --name-only HEAD #{merge_base}`.strip.split(/\s/) +files = changed_files.select { |f| File.extname(f) == '.cpp' || File.extname(f) == '.h' } +if files.empty? + puts 'No files to lint' + exit 0 +end + +puts "Linting #{files.count} files" +system "cppcheck --quiet --force --enable=all #{files.join(' ')}" +exit $?.exitstatus diff --git a/tools/samples-build b/tools/samples-build new file mode 100755 index 00000000000..c956e7bc4c8 --- /dev/null +++ b/tools/samples-build @@ -0,0 +1,73 @@ +#!/bin/bash +# +# This script builds the sample applications. + +set -e + +if [ -z $1 ] +then + echo "No platform argument given, use all|linux|ios|android" + set $1 'linux' +fi + +if [ ! "$1" = "linux" ] && [ ! "$1" = "ios" ] && [ ! "$1" = "android" ] && [ ! "$1" = "all" ] +then + echo "Wrong platform argument given, use all|linux|ios|android" + set $1 'linux' +fi + +echo "Platform argument: "$1 + +build_cpp() { + pushd samples/cpp + echo "Building CPP sample app:"`pwd` + cmake . -DWALLET_CORE=../../ + make + echo "Building CPP sample app: done" + popd +} + +build_ios() { + pushd samples/osx/cocoapods + echo "Building OSX sample app:"`pwd` + pod repo update + pod install + echo "Building OSX sample app: done" + popd +} + +build_android() { + pushd samples/android + echo "Building Android sample app:"`pwd` + ./gradlew assembleDebug + echo "Building Android sample app: done" + popd +} + +build_go() { + pushd samples/go + echo "Building GO sample app:"`pwd` + go build -o main + echo "Building GO sample app: done" + popd +} + +if [ "$1" = "linux" ]; then + build_cpp + build_go +fi + +if [ "$1" = "ios" ]; then + build_ios +fi + +if [ "$1" = "android" ]; then + build_android +fi + +if [ "$1" = "all" ]; then + build_cpp + build_go + build_ios + build_android +fi diff --git a/trezor-crypto/src/bip32.c b/trezor-crypto/src/bip32.c index b397a89abee..3f5d51c610f 100644 --- a/trezor-crypto/src/bip32.c +++ b/trezor-crypto/src/bip32.c @@ -632,11 +632,11 @@ int hdnode_sign(HDNode *node, const uint8_t *msg, uint32_t msg_len, HasherType h } else if (node->curve == &ed25519_keccak_info) { ed25519_sign_keccak(msg, msg_len, node->private_key, node->public_key + 1, sig); } else if (node->curve == &curve25519_info) { - uint8_t ed25519_public_key[32]; - memset(ed25519_public_key, 0, 32); - curve25519_pk_to_ed25519(ed25519_public_key, node->public_key + 1); - ed25519_sign(msg, msg_len, node->private_key, ed25519_public_key, sig); - const uint8_t sign_bit = ed25519_public_key[31] & 0x80; + uint8_t ed25519_public_key_val[32]; + memset(ed25519_public_key_val, 0, 32); + curve25519_pk_to_ed25519(ed25519_public_key_val, node->public_key + 1); + ed25519_sign(msg, msg_len, node->private_key, ed25519_public_key_val, sig); + const uint8_t sign_bit = ed25519_public_key_val[31] & 0x80; sig[63] = sig[63] & 127; sig[63] |= sign_bit; } diff --git a/trezor-crypto/tests/CMakeLists.txt b/trezor-crypto/tests/CMakeLists.txt index 36f9ca1bbb8..53420c90f7d 100644 --- a/trezor-crypto/tests/CMakeLists.txt +++ b/trezor-crypto/tests/CMakeLists.txt @@ -1,10 +1,10 @@ enable_testing() -find_library(check PATH ${CMAKE_SOURCE_DIR}/wallet-core/build/local/lib/pkgconfig NO_DEFAULT_PATH) +find_library(check PATH ${CMAKE_SOURCE_DIR}/build/local/lib/pkgconfig NO_DEFAULT_PATH) # Test executable add_executable(TrezorCryptoTests test_check.c) target_link_libraries(TrezorCryptoTests TrezorCrypto check) -target_include_directories(TrezorCryptoTests PRIVATE ${CMAKE_SOURCE_DIR}/wallet-core/src) +target_include_directories(TrezorCryptoTests PRIVATE ${CMAKE_SOURCE_DIR}/src) add_test(NAME test_check COMMAND TrezorCryptoTests) diff --git a/walletconsole/lib/Coins.cpp b/walletconsole/lib/Coins.cpp index 368c1b9853e..b59344190b2 100644 --- a/walletconsole/lib/Coins.cpp +++ b/walletconsole/lib/Coins.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #define WRAPS(x) std::shared_ptr(x, TWStringDelete) diff --git a/walletconsole/lib/Util.cpp b/walletconsole/lib/Util.cpp index 5a54509998e..7b8b1305a9c 100644 --- a/walletconsole/lib/Util.cpp +++ b/walletconsole/lib/Util.cpp @@ -14,6 +14,7 @@ #include #include #include +#include namespace TW::WalletConsole { @@ -79,6 +80,7 @@ bool Util::fileR(const string& fileName, string& res) { char* buffer = new char[length]; if (!infile.read(buffer, length)) { _out << "Could not read file '" << fileName << "'" << endl; + delete[] buffer; return false; } int red = infile.gcount(); diff --git a/walletconsole/lib/Util.h b/walletconsole/lib/Util.h index f86ed09e34e..5522610339b 100644 --- a/walletconsole/lib/Util.h +++ b/walletconsole/lib/Util.h @@ -8,6 +8,7 @@ #include #include +#include namespace TW::WalletConsole {