From fdc37294248349bb96275d1220d2d0e7c12b15e9 Mon Sep 17 00:00:00 2001 From: Viktor Radchenko <1641795+vikmeup@users.noreply.github.com> Date: Sun, 10 Mar 2019 21:28:18 -0700 Subject: [PATCH] Add static method sign for BinanceSigner (#123) * Add static sign method * Add TWData *_Nonnull * Update TWRippleSigner.h * Update BinanceSignerTests * Add binance signing output * Update TestBinanceTransactionSigning.kt * Fix binance android --- JNI/cpp/BinanceSigner.c | 25 +- JNI/cpp/BinanceSigner.h | 8 +- JNI/java/wallet/core/jni/BinanceSigner.java | 36 +- JNI/java/wallet/core/jni/proto/Binance.java | 522 +++++++++++++++++- .../binance/TestBinanceTransactionSigning.kt | 5 +- include/TrustWalletCore/TWBinanceProto.h | 1 + include/TrustWalletCore/TWBinanceSigner.h | 15 +- include/TrustWalletCore/TWRippleSigner.h | 2 +- src/interface/TWBinanceSigner.cpp | 23 +- src/proto/Binance.proto | 6 + swift/Podfile.lock | 2 +- swift/Sources/Binance.pb.swift | 43 ++ swift/Sources/BinanceSigner.swift | 25 +- swift/Tests/BinanceSignerTests.swift | 5 +- 14 files changed, 610 insertions(+), 108 deletions(-) diff --git a/JNI/cpp/BinanceSigner.c b/JNI/cpp/BinanceSigner.c index 00d466c02f6..bb697fecc4d 100644 --- a/JNI/cpp/BinanceSigner.c +++ b/JNI/cpp/BinanceSigner.c @@ -16,30 +16,19 @@ #include "TWJNI.h" #include "BinanceSigner.h" -jlong JNICALL Java_wallet_core_jni_BinanceSigner_nativeCreate(JNIEnv *env, jclass thisClass, jobject input) { +jobject JNICALL Java_wallet_core_jni_BinanceSigner_sign(JNIEnv *env, jclass thisClass, jobject input) { jclass inputClass = (*env)->GetObjectClass(env, input); jmethodID inputToByteArrayMethodID = (*env)->GetMethodID(env, inputClass, "toByteArray", "()[B"); jbyteArray inputByteArray = (*env)->CallObjectMethod(env, input, inputToByteArrayMethodID); TWData *inputData = TWDataCreateWithJByteArray(env, inputByteArray); - struct TWBinanceSigner *instance = TWBinanceSignerCreate(inputData); + jbyteArray resultData = TWDataJByteArray(TWBinanceSignerSign(inputData), env); + jclass resultClass = (*env)->FindClass(env, "wallet/core/jni/proto/Binance$SigningOutput"); + jmethodID parseFromMethodID = (*env)->GetStaticMethodID(env, resultClass, "parseFrom", "([B)Lwallet/core/jni/proto/Binance$SigningOutput;"); + jobject result = (*env)->CallStaticObjectMethod(env, resultClass, parseFromMethodID, resultData); + + (*env)->DeleteLocalRef(env, resultClass); (*env)->DeleteLocalRef(env, inputByteArray); (*env)->DeleteLocalRef(env, inputClass); - return (jlong) instance; -} - -void JNICALL Java_wallet_core_jni_BinanceSigner_nativeDelete(JNIEnv *env, jclass thisClass, jlong handle) { - TWBinanceSignerDelete((struct TWBinanceSigner *) handle); -} - -jbyteArray JNICALL Java_wallet_core_jni_BinanceSigner_build(JNIEnv *env, jobject thisObject) { - jclass thisClass = (*env)->GetObjectClass(env, thisObject); - jfieldID handleFieldID = (*env)->GetFieldID(env, thisClass, "nativeHandle", "J"); - struct TWBinanceSigner *instance = (struct TWBinanceSigner *) (*env)->GetLongField(env, thisObject, handleFieldID); - - jbyteArray result = TWDataJByteArray(TWBinanceSignerBuild(instance), env); - - - (*env)->DeleteLocalRef(env, thisClass); return result; } diff --git a/JNI/cpp/BinanceSigner.h b/JNI/cpp/BinanceSigner.h index c96c24bcd57..64ec462e8ae 100644 --- a/JNI/cpp/BinanceSigner.h +++ b/JNI/cpp/BinanceSigner.h @@ -16,13 +16,7 @@ TW_EXTERN_C_BEGIN JNIEXPORT -jlong JNICALL Java_wallet_core_jni_BinanceSigner_nativeCreate(JNIEnv *env, jclass thisClass, jobject input); - -JNIEXPORT -void JNICALL Java_wallet_core_jni_BinanceSigner_nativeDelete(JNIEnv *env, jclass thisClass, jlong handle); - -JNIEXPORT -jbyteArray JNICALL Java_wallet_core_jni_BinanceSigner_build(JNIEnv *env, jobject thisObject); +jobject JNICALL Java_wallet_core_jni_BinanceSigner_sign(JNIEnv *env, jclass thisClass, jobject input); TW_EXTERN_C_END diff --git a/JNI/java/wallet/core/jni/BinanceSigner.java b/JNI/java/wallet/core/jni/BinanceSigner.java index b2ab1c1ba4e..af8366f4b95 100644 --- a/JNI/java/wallet/core/jni/BinanceSigner.java +++ b/JNI/java/wallet/core/jni/BinanceSigner.java @@ -22,45 +22,11 @@ private BinanceSigner() { static BinanceSigner createFromNative(long nativeHandle) { BinanceSigner instance = new BinanceSigner(); instance.nativeHandle = nativeHandle; - BinanceSignerPhantomReference.register(instance, nativeHandle); return instance; } - static native long nativeCreate(wallet.core.jni.proto.Binance.SigningInput input); - static native void nativeDelete(long handle); - public native byte[] build(); - - public BinanceSigner(wallet.core.jni.proto.Binance.SigningInput input) { - nativeHandle = nativeCreate(input); - if (nativeHandle == 0) { - throw new InvalidParameterException(); - } - - BinanceSignerPhantomReference.register(this, nativeHandle); - } + public static native wallet.core.jni.proto.Binance.SigningOutput sign(wallet.core.jni.proto.Binance.SigningInput input); } -class BinanceSignerPhantomReference extends java.lang.ref.PhantomReference { - private static java.util.Set references = new HashSet(); - private static java.lang.ref.ReferenceQueue queue = new java.lang.ref.ReferenceQueue(); - private long nativeHandle; - - private BinanceSignerPhantomReference(BinanceSigner referent, long nativeHandle) { - super(referent, queue); - this.nativeHandle = nativeHandle; - } - - static void register(BinanceSigner referent, long nativeHandle) { - references.add(new BinanceSignerPhantomReference(referent, nativeHandle)); - } - - public static void doDeletes() { - BinanceSignerPhantomReference ref = (BinanceSignerPhantomReference) queue.poll(); - for (; ref != null; ref = (BinanceSignerPhantomReference) queue.poll()) { - BinanceSigner.nativeDelete(ref.nativeHandle); - references.remove(ref); - } - } -} diff --git a/JNI/java/wallet/core/jni/proto/Binance.java b/JNI/java/wallet/core/jni/proto/Binance.java index 63794682a5e..dc9c72cffcf 100644 --- a/JNI/java/wallet/core/jni/proto/Binance.java +++ b/JNI/java/wallet/core/jni/proto/Binance.java @@ -11615,6 +11615,512 @@ public wallet.core.jni.proto.Binance.SigningInput getDefaultInstanceForType() { } + public interface SigningOutputOrBuilder extends + // @@protoc_insertion_point(interface_extends:TW.Binance.Proto.SigningOutput) + com.google.protobuf.MessageOrBuilder { + + /** + *
+     * Signed and encoded transaction bytes.
+     * 
+ * + * bytes encoded = 1; + */ + com.google.protobuf.ByteString getEncoded(); + } + /** + *
+   * Transaction signing output.
+   * 
+ * + * Protobuf type {@code TW.Binance.Proto.SigningOutput} + */ + public static final class SigningOutput extends + com.google.protobuf.GeneratedMessageV3 implements + // @@protoc_insertion_point(message_implements:TW.Binance.Proto.SigningOutput) + SigningOutputOrBuilder { + private static final long serialVersionUID = 0L; + // Use SigningOutput.newBuilder() to construct. + private SigningOutput(com.google.protobuf.GeneratedMessageV3.Builder builder) { + super(builder); + } + private SigningOutput() { + encoded_ = com.google.protobuf.ByteString.EMPTY; + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private SigningOutput( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + this(); + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: { + + encoded_ = input.readBytes(); + break; + } + default: { + if (!parseUnknownField( + input, unknownFields, extensionRegistry, tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException( + e).setUnfinishedMessage(this); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return wallet.core.jni.proto.Binance.internal_static_TW_Binance_Proto_SigningOutput_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return wallet.core.jni.proto.Binance.internal_static_TW_Binance_Proto_SigningOutput_fieldAccessorTable + .ensureFieldAccessorsInitialized( + wallet.core.jni.proto.Binance.SigningOutput.class, wallet.core.jni.proto.Binance.SigningOutput.Builder.class); + } + + public static final int ENCODED_FIELD_NUMBER = 1; + private com.google.protobuf.ByteString encoded_; + /** + *
+     * Signed and encoded transaction bytes.
+     * 
+ * + * bytes encoded = 1; + */ + public com.google.protobuf.ByteString getEncoded() { + return encoded_; + } + + private byte memoizedIsInitialized = -1; + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!encoded_.isEmpty()) { + output.writeBytes(1, encoded_); + } + unknownFields.writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!encoded_.isEmpty()) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(1, encoded_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof wallet.core.jni.proto.Binance.SigningOutput)) { + return super.equals(obj); + } + wallet.core.jni.proto.Binance.SigningOutput other = (wallet.core.jni.proto.Binance.SigningOutput) obj; + + if (!getEncoded() + .equals(other.getEncoded())) return false; + if (!unknownFields.equals(other.unknownFields)) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + ENCODED_FIELD_NUMBER; + hash = (53 * hash) + getEncoded().hashCode(); + hash = (29 * hash) + unknownFields.hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static wallet.core.jni.proto.Binance.SigningOutput parseFrom( + java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static wallet.core.jni.proto.Binance.SigningOutput parseFrom( + java.nio.ByteBuffer data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static wallet.core.jni.proto.Binance.SigningOutput parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static wallet.core.jni.proto.Binance.SigningOutput parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static wallet.core.jni.proto.Binance.SigningOutput parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static wallet.core.jni.proto.Binance.SigningOutput parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static wallet.core.jni.proto.Binance.SigningOutput parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static wallet.core.jni.proto.Binance.SigningOutput parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + public static wallet.core.jni.proto.Binance.SigningOutput parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input); + } + public static wallet.core.jni.proto.Binance.SigningOutput parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseDelimitedWithIOException(PARSER, input, extensionRegistry); + } + public static wallet.core.jni.proto.Binance.SigningOutput parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input); + } + public static wallet.core.jni.proto.Binance.SigningOutput parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessageV3 + .parseWithIOException(PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(wallet.core.jni.proto.Binance.SigningOutput prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + *
+     * Transaction signing output.
+     * 
+ * + * Protobuf type {@code TW.Binance.Proto.SigningOutput} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessageV3.Builder implements + // @@protoc_insertion_point(builder_implements:TW.Binance.Proto.SigningOutput) + wallet.core.jni.proto.Binance.SigningOutputOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return wallet.core.jni.proto.Binance.internal_static_TW_Binance_Proto_SigningOutput_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internalGetFieldAccessorTable() { + return wallet.core.jni.proto.Binance.internal_static_TW_Binance_Proto_SigningOutput_fieldAccessorTable + .ensureFieldAccessorsInitialized( + wallet.core.jni.proto.Binance.SigningOutput.class, wallet.core.jni.proto.Binance.SigningOutput.Builder.class); + } + + // Construct using wallet.core.jni.proto.Binance.SigningOutput.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessageV3 + .alwaysUseFieldBuilders) { + } + } + @java.lang.Override + public Builder clear() { + super.clear(); + encoded_ = com.google.protobuf.ByteString.EMPTY; + + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return wallet.core.jni.proto.Binance.internal_static_TW_Binance_Proto_SigningOutput_descriptor; + } + + @java.lang.Override + public wallet.core.jni.proto.Binance.SigningOutput getDefaultInstanceForType() { + return wallet.core.jni.proto.Binance.SigningOutput.getDefaultInstance(); + } + + @java.lang.Override + public wallet.core.jni.proto.Binance.SigningOutput build() { + wallet.core.jni.proto.Binance.SigningOutput result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public wallet.core.jni.proto.Binance.SigningOutput buildPartial() { + wallet.core.jni.proto.Binance.SigningOutput result = new wallet.core.jni.proto.Binance.SigningOutput(this); + result.encoded_ = encoded_; + onBuilt(); + return result; + } + + @java.lang.Override + public Builder clone() { + return super.clone(); + } + @java.lang.Override + public Builder setField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.setField(field, value); + } + @java.lang.Override + public Builder clearField( + com.google.protobuf.Descriptors.FieldDescriptor field) { + return super.clearField(field); + } + @java.lang.Override + public Builder clearOneof( + com.google.protobuf.Descriptors.OneofDescriptor oneof) { + return super.clearOneof(oneof); + } + @java.lang.Override + public Builder setRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + int index, java.lang.Object value) { + return super.setRepeatedField(field, index, value); + } + @java.lang.Override + public Builder addRepeatedField( + com.google.protobuf.Descriptors.FieldDescriptor field, + java.lang.Object value) { + return super.addRepeatedField(field, value); + } + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof wallet.core.jni.proto.Binance.SigningOutput) { + return mergeFrom((wallet.core.jni.proto.Binance.SigningOutput)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(wallet.core.jni.proto.Binance.SigningOutput other) { + if (other == wallet.core.jni.proto.Binance.SigningOutput.getDefaultInstance()) return this; + if (other.getEncoded() != com.google.protobuf.ByteString.EMPTY) { + setEncoded(other.getEncoded()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + wallet.core.jni.proto.Binance.SigningOutput parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (wallet.core.jni.proto.Binance.SigningOutput) e.getUnfinishedMessage(); + throw e.unwrapIOException(); + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private com.google.protobuf.ByteString encoded_ = com.google.protobuf.ByteString.EMPTY; + /** + *
+       * Signed and encoded transaction bytes.
+       * 
+ * + * bytes encoded = 1; + */ + public com.google.protobuf.ByteString getEncoded() { + return encoded_; + } + /** + *
+       * Signed and encoded transaction bytes.
+       * 
+ * + * bytes encoded = 1; + */ + public Builder setEncoded(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + + encoded_ = value; + onChanged(); + return this; + } + /** + *
+       * Signed and encoded transaction bytes.
+       * 
+ * + * bytes encoded = 1; + */ + public Builder clearEncoded() { + + encoded_ = getDefaultInstance().getEncoded(); + onChanged(); + return this; + } + @java.lang.Override + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.setUnknownFields(unknownFields); + } + + @java.lang.Override + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return super.mergeUnknownFields(unknownFields); + } + + + // @@protoc_insertion_point(builder_scope:TW.Binance.Proto.SigningOutput) + } + + // @@protoc_insertion_point(class_scope:TW.Binance.Proto.SigningOutput) + private static final wallet.core.jni.proto.Binance.SigningOutput DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new wallet.core.jni.proto.Binance.SigningOutput(); + } + + public static wallet.core.jni.proto.Binance.SigningOutput getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + @java.lang.Override + public SigningOutput parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return new SigningOutput(input, extensionRegistry); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public wallet.core.jni.proto.Binance.SigningOutput getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + private static final com.google.protobuf.Descriptors.Descriptor internal_static_TW_Binance_Proto_Transaction_descriptor; private static final @@ -11675,6 +12181,11 @@ public wallet.core.jni.proto.Binance.SigningInput getDefaultInstanceForType() { private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_TW_Binance_Proto_SigningInput_fieldAccessorTable; + private static final com.google.protobuf.Descriptors.Descriptor + internal_static_TW_Binance_Proto_SigningOutput_descriptor; + private static final + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable + internal_static_TW_Binance_Proto_SigningOutput_fieldAccessorTable; public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { @@ -11717,8 +12228,9 @@ public wallet.core.jni.proto.Binance.SigningInput getDefaultInstanceForType() { "\000\022:\n\014freeze_order\030\013 \001(\0132\".TW.Binance.Pro" + "to.TokenFreezeOrderH\000\022>\n\016unfreeze_order\030" + "\014 \001(\0132$.TW.Binance.Proto.TokenUnfreezeOr" + - "derH\000B\r\n\013order_oneofB\027\n\025wallet.core.jni." + - "protob\006proto3" + "derH\000B\r\n\013order_oneof\" \n\rSigningOutput\022\017\n" + + "\007encoded\030\001 \001(\014B\027\n\025wallet.core.jni.protob" + + "\006proto3" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { @@ -11804,6 +12316,12 @@ public com.google.protobuf.ExtensionRegistry assignDescriptors( com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_TW_Binance_Proto_SigningInput_descriptor, new java.lang.String[] { "ChainId", "AccountNumber", "Sequence", "Source", "Memo", "PrivateKey", "TestNet", "TradeOrder", "CancelTradeOrder", "SendOrder", "FreezeOrder", "UnfreezeOrder", "OrderOneof", }); + internal_static_TW_Binance_Proto_SigningOutput_descriptor = + getDescriptor().getMessageTypes().get(8); + internal_static_TW_Binance_Proto_SigningOutput_fieldAccessorTable = new + com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( + internal_static_TW_Binance_Proto_SigningOutput_descriptor, + new java.lang.String[] { "Encoded", }); } // @@protoc_insertion_point(outer_class_scope) diff --git a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/binance/TestBinanceTransactionSigning.kt b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/binance/TestBinanceTransactionSigning.kt index bd95ee22ecc..83788d0674b 100644 --- a/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/binance/TestBinanceTransactionSigning.kt +++ b/android/app/src/androidTest/java/com/trustwallet/core/app/blockchains/binance/TestBinanceTransactionSigning.kt @@ -48,7 +48,8 @@ class TestBinanceTransactionSigning { signingInput.sendOrder = sendOrder.build() - val data = BinanceSigner(signingInput.build()).build() - assertEquals(data.toHex(), "0xb801f0625dee0a462a2c87fa0a1f0a1440c2979694bbc961023d1d27be6fc4d21a9febe612070a03424e421001121f0a14bffe47abfaede50419c577f1074fee6dd1535cd112070a03424e421001126a0a26eb5ae98721026a35920088d98c3888ca68c53dfc93f4564602606cbb87f0fe5ee533db38e5021240376f64070fdb621a4cf24e24da350476260efaf4bae799cacca19b31bc0d1ce4054f09fcffe9cfabef6a8d6a24bc1814bd444720a35f035f3c26409ffad2a9e2") + val sign: Binance.SigningOutput = BinanceSigner.sign(signingInput.build()) + val signBytes = sign.encoded.toByteArray() + assertEquals(signBytes.toHex(), "0xb801f0625dee0a462a2c87fa0a1f0a1440c2979694bbc961023d1d27be6fc4d21a9febe612070a03424e421001121f0a14bffe47abfaede50419c577f1074fee6dd1535cd112070a03424e421001126a0a26eb5ae98721026a35920088d98c3888ca68c53dfc93f4564602606cbb87f0fe5ee533db38e5021240376f64070fdb621a4cf24e24da350476260efaf4bae799cacca19b31bc0d1ce4054f09fcffe9cfabef6a8d6a24bc1814bd444720a35f035f3c26409ffad2a9e2") } } \ No newline at end of file diff --git a/include/TrustWalletCore/TWBinanceProto.h b/include/TrustWalletCore/TWBinanceProto.h index 5df698d2ab8..255cda77500 100644 --- a/include/TrustWalletCore/TWBinanceProto.h +++ b/include/TrustWalletCore/TWBinanceProto.h @@ -16,3 +16,4 @@ typedef TWData *_Nonnull TW_Binance_Proto_SendOrder; typedef TWData *_Nonnull TW_Binance_Proto_TokenFreezeOrder; typedef TWData *_Nonnull TW_Binance_Proto_TokenUnfreezeOrder; typedef TWData *_Nonnull TW_Binance_Proto_SigningInput; +typedef TWData *_Nonnull TW_Binance_Proto_SigningOutput; diff --git a/include/TrustWalletCore/TWBinanceSigner.h b/include/TrustWalletCore/TWBinanceSigner.h index d29f1b877e0..fa18216fb83 100644 --- a/include/TrustWalletCore/TWBinanceSigner.h +++ b/include/TrustWalletCore/TWBinanceSigner.h @@ -12,19 +12,12 @@ TW_EXTERN_C_BEGIN -/// Helper class to sign Binance DEX orders. +/// Helper class to sign Binance transactions. TW_EXPORT_CLASS struct TWBinanceSigner; -/// Creates a signer with input data (serialized from BinanceSigningInput) +/// Signs a transaction. TW_EXPORT_STATIC_METHOD -struct TWBinanceSigner *_Nonnull TWBinanceSignerCreate(TW_Binance_Proto_SigningInput input); +TW_Binance_Proto_SigningOutput TWBinanceSignerSign(TW_Binance_Proto_SigningInput input); -TW_EXPORT_METHOD -void TWBinanceSignerDelete(struct TWBinanceSigner *_Nonnull signer); - -/// Builds a signed transaction. -TW_EXPORT_METHOD -TWData *_Nullable TWBinanceSignerBuild(struct TWBinanceSigner *_Nonnull signer); - -TW_EXTERN_C_END +TW_EXTERN_C_END \ No newline at end of file diff --git a/include/TrustWalletCore/TWRippleSigner.h b/include/TrustWalletCore/TWRippleSigner.h index de28b700f49..872d23eb63c 100644 --- a/include/TrustWalletCore/TWRippleSigner.h +++ b/include/TrustWalletCore/TWRippleSigner.h @@ -12,7 +12,7 @@ TW_EXTERN_C_BEGIN -/// Helper class to sign Wanchain transactions. +/// Helper class to sign Ripple transactions. TW_EXPORT_CLASS struct TWRippleSigner; diff --git a/src/interface/TWBinanceSigner.cpp b/src/interface/TWBinanceSigner.cpp index 6fb017b0b8f..aa6db7b94ef 100644 --- a/src/interface/TWBinanceSigner.cpp +++ b/src/interface/TWBinanceSigner.cpp @@ -9,22 +9,19 @@ #include "../Binance/Signer.h" #include "../proto/Binance.pb.h" +using namespace TW; using namespace TW::Binance; -struct TWBinanceSigner *_Nonnull TWBinanceSignerCreate(TW_Binance_Proto_SigningInput data) { +TW_Binance_Proto_SigningOutput TWBinanceSignerSign(TW_Binance_Proto_SigningInput data) { Proto::SigningInput input; input.ParseFromArray(TWDataBytes(data), TWDataSize(data)); - return new TWBinanceSigner{ Signer(std::move(input)) }; -} -void TWBinanceSignerDelete(struct TWBinanceSigner *_Nonnull signer) { - delete signer; -} + auto signer = new TWBinanceSigner{ Signer(std::move(input)) }; + auto encoded = signer->impl.build(); -TWData *_Nullable TWBinanceSignerBuild(struct TWBinanceSigner *_Nonnull signer) { - auto data = signer->impl.build(); - if (data.empty()) { - return nullptr; - } - return TWDataCreateWithBytes(data.data(), data.size()); -} + auto protoOutput = Proto::SigningOutput(); + protoOutput.set_encoded(encoded.data(), encoded.size()); + + auto serialized = protoOutput.SerializeAsString(); + return TWDataCreateWithBytes(reinterpret_cast(serialized.data()), serialized.size()); +} \ No newline at end of file diff --git a/src/proto/Binance.proto b/src/proto/Binance.proto index 6b55e5300b6..fc1863c9bff 100644 --- a/src/proto/Binance.proto +++ b/src/proto/Binance.proto @@ -93,3 +93,9 @@ message SigningInput { TokenUnfreezeOrder unfreeze_order = 12; } } + +// Transaction signing output. +message SigningOutput { + // Signed and encoded transaction bytes. + bytes encoded = 1; +} diff --git a/swift/Podfile.lock b/swift/Podfile.lock index 5cd0f736844..c2496319dfd 100644 --- a/swift/Podfile.lock +++ b/swift/Podfile.lock @@ -13,4 +13,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: bcab653390ccf2f8e377a439713b531df60e7b01 -COCOAPODS: 1.6.1 +COCOAPODS: 1.6.0 diff --git a/swift/Sources/Binance.pb.swift b/swift/Sources/Binance.pb.swift index 2b0635f01e3..dbfc4b0b0d7 100644 --- a/swift/Sources/Binance.pb.swift +++ b/swift/Sources/Binance.pb.swift @@ -341,6 +341,20 @@ public struct TW_Binance_Proto_SigningInput { fileprivate var _storage = _StorageClass.defaultInstance } +/// Transaction signing output. +public struct TW_Binance_Proto_SigningOutput { + // SwiftProtobuf.Message conformance is added in an extension below. See the + // `Message` and `Message+*Additions` files in the SwiftProtobuf library for + // methods supported on all messages. + + /// Signed and encoded transaction bytes. + public var encoded: Data = SwiftProtobuf.Internal.emptyData + + public var unknownFields = SwiftProtobuf.UnknownStorage() + + public init() {} +} + // MARK: - Code below here is support for the SwiftProtobuf runtime. fileprivate let _protobuf_package = "TW.Binance.Proto" @@ -967,3 +981,32 @@ extension TW_Binance_Proto_SigningInput: SwiftProtobuf.Message, SwiftProtobuf._M return true } } + +extension TW_Binance_Proto_SigningOutput: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + public static let protoMessageName: String = _protobuf_package + ".SigningOutput" + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 1: .same(proto: "encoded"), + ] + + public mutating func decodeMessage(decoder: inout D) throws { + while let fieldNumber = try decoder.nextFieldNumber() { + switch fieldNumber { + case 1: try decoder.decodeSingularBytesField(value: &self.encoded) + default: break + } + } + } + + public func traverse(visitor: inout V) throws { + if !self.encoded.isEmpty { + try visitor.visitSingularBytesField(value: self.encoded, fieldNumber: 1) + } + try unknownFields.traverse(visitor: &visitor) + } + + public static func ==(lhs: TW_Binance_Proto_SigningOutput, rhs: TW_Binance_Proto_SigningOutput) -> Bool { + if lhs.encoded != rhs.encoded {return false} + if lhs.unknownFields != rhs.unknownFields {return false} + return true + } +} diff --git a/swift/Sources/BinanceSigner.swift b/swift/Sources/BinanceSigner.swift index 903ed4e85f2..aa995e4ead6 100644 --- a/swift/Sources/BinanceSigner.swift +++ b/swift/Sources/BinanceSigner.swift @@ -11,29 +11,22 @@ import Foundation public final class BinanceSigner { - let rawValue: OpaquePointer - - init(rawValue: OpaquePointer) { - self.rawValue = rawValue - } - - public init(input: TW_Binance_Proto_SigningInput) { + public static func sign(input: TW_Binance_Proto_SigningInput) -> TW_Binance_Proto_SigningOutput { let inputData = TWDataCreateWithNSData(try! input.serializedData()) defer { TWDataDelete(inputData) } - rawValue = TWBinanceSignerCreate(inputData) + let resultData = TWDataNSData(TWBinanceSignerSign(inputData)) + return try! TW_Binance_Proto_SigningOutput(serializedData: resultData) } - deinit { - TWBinanceSignerDelete(rawValue) - } + let rawValue: OpaquePointer - public func build() -> Data? { - guard let result = TWBinanceSignerBuild(rawValue) else { - return nil - } - return TWDataNSData(result) + init(rawValue: OpaquePointer) { + self.rawValue = rawValue } + } + + diff --git a/swift/Tests/BinanceSignerTests.swift b/swift/Tests/BinanceSignerTests.swift index c97e2320726..16760a1846c 100644 --- a/swift/Tests/BinanceSignerTests.swift +++ b/swift/Tests/BinanceSignerTests.swift @@ -38,7 +38,8 @@ class BinanceSignerTests: XCTestCase { signingInput.sendOrder = sendOrder - let data = BinanceSigner(input: signingInput).build() - XCTAssertEqual(data?.hexString, "b801f0625dee0a462a2c87fa0a1f0a1440c2979694bbc961023d1d27be6fc4d21a9febe612070a03424e421001121f0a14bffe47abfaede50419c577f1074fee6dd1535cd112070a03424e421001126a0a26eb5ae98721026a35920088d98c3888ca68c53dfc93f4564602606cbb87f0fe5ee533db38e5021240376f64070fdb621a4cf24e24da350476260efaf4bae799cacca19b31bc0d1ce4054f09fcffe9cfabef6a8d6a24bc1814bd444720a35f035f3c26409ffad2a9e2") + let data = BinanceSigner.sign(input: signingInput) + + XCTAssertEqual(data.encoded.hexString, "b801f0625dee0a462a2c87fa0a1f0a1440c2979694bbc961023d1d27be6fc4d21a9febe612070a03424e421001121f0a14bffe47abfaede50419c577f1074fee6dd1535cd112070a03424e421001126a0a26eb5ae98721026a35920088d98c3888ca68c53dfc93f4564602606cbb87f0fe5ee533db38e5021240376f64070fdb621a4cf24e24da350476260efaf4bae799cacca19b31bc0d1ce4054f09fcffe9cfabef6a8d6a24bc1814bd444720a35f035f3c26409ffad2a9e2") } }