Skip to content

Commit c3ace29

Browse files
vikmeupalejandro-isaza
authored andcommitted
Add Ripple Address (trustwallet#18)
1 parent 590c4d7 commit c3ace29

24 files changed

Lines changed: 841 additions & 11 deletions

File tree

JNI/cpp/RippleAddress.c

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Copyright © 2017-2019 Trust.
2+
//
3+
// This file is part of Trust. The full Trust copyright notice, including
4+
// terms governing use, modification, and redistribution, is contained in the
5+
// file LICENSE at the root of the source code distribution tree.
6+
//
7+
// This is a GENERATED FILE, changes made here WILL BE LOST.
8+
//
9+
10+
#include <jni.h>
11+
#include <stdio.h>
12+
#include <string.h>
13+
14+
#include <TrustWalletCore/TWPublicKey.h>
15+
#include <TrustWalletCore/TWRippleAddress.h>
16+
17+
#include "TWJNI.h"
18+
#include "RippleAddress.h"
19+
20+
jlong JNICALL Java_com_wallet_crypto_trustapp_jni_RippleAddress_nativeCreateWithString(JNIEnv *env, jclass thisClass, jstring string) {
21+
TWString *stringString = TWStringCreateWithJString(env, string);
22+
struct TWRippleAddress *instance = TWRippleAddressCreateWithString(stringString);
23+
TWStringDelete(stringString);
24+
return (jlong) instance;
25+
}
26+
27+
jlong JNICALL Java_com_wallet_crypto_trustapp_jni_RippleAddress_nativeCreateWithData(JNIEnv *env, jclass thisClass, jbyteArray data) {
28+
TWData *dataData = TWDataCreateWithJByteArray(env, data);
29+
struct TWRippleAddress *instance = TWRippleAddressCreateWithData(dataData);
30+
TWDataDelete(dataData);
31+
return (jlong) instance;
32+
}
33+
34+
jlong JNICALL Java_com_wallet_crypto_trustapp_jni_RippleAddress_nativeCreateWithPublicKey(JNIEnv *env, jclass thisClass, jobject publicKey) {
35+
jclass publicKeyClass = (*env)->GetObjectClass(env, publicKey);
36+
jfieldID publicKeyBytesFieldID = (*env)->GetFieldID(env, publicKeyClass, "bytes", "[B");
37+
jbyteArray publicKeyBytesArray = (*env)->GetObjectField(env, publicKey, publicKeyBytesFieldID);
38+
jbyte* publicKeyBytesBuffer = (*env)->GetByteArrayElements(env, publicKeyBytesArray, NULL);
39+
struct TWPublicKey *publicKeyInstance = (struct TWPublicKey *) publicKeyBytesBuffer;
40+
struct TWRippleAddress *instance = TWRippleAddressCreateWithPublicKey(*publicKeyInstance);
41+
(*env)->ReleaseByteArrayElements(env, publicKeyBytesArray, publicKeyBytesBuffer, JNI_ABORT);
42+
(*env)->DeleteLocalRef(env, publicKeyBytesArray);
43+
(*env)->DeleteLocalRef(env, publicKeyClass);
44+
return (jlong) instance;
45+
}
46+
47+
void JNICALL Java_com_wallet_crypto_trustapp_jni_RippleAddress_nativeDelete(JNIEnv *env, jclass thisClass, jlong handle) {
48+
TWRippleAddressDelete((struct TWRippleAddress *) handle);
49+
}
50+
51+
jboolean JNICALL Java_com_wallet_crypto_trustapp_jni_RippleAddress_equals(JNIEnv *env, jclass thisClass, jobject lhs, jobject rhs) {
52+
jclass lhsClass = (*env)->GetObjectClass(env, lhs);
53+
jfieldID lhsHandleFieldID = (*env)->GetFieldID(env, lhsClass, "nativeHandle", "J");
54+
struct TWRippleAddress *lhsInstance = (struct TWRippleAddress *) (*env)->GetLongField(env, lhs, lhsHandleFieldID);
55+
jclass rhsClass = (*env)->GetObjectClass(env, rhs);
56+
jfieldID rhsHandleFieldID = (*env)->GetFieldID(env, rhsClass, "nativeHandle", "J");
57+
struct TWRippleAddress *rhsInstance = (struct TWRippleAddress *) (*env)->GetLongField(env, rhs, rhsHandleFieldID);
58+
jboolean resultValue = (jboolean) TWRippleAddressEqual(lhsInstance, rhsInstance);
59+
60+
(*env)->DeleteLocalRef(env, lhsClass);
61+
(*env)->DeleteLocalRef(env, rhsClass);
62+
63+
return resultValue;
64+
}
65+
66+
jboolean JNICALL Java_com_wallet_crypto_trustapp_jni_RippleAddress_isValidString(JNIEnv *env, jclass thisClass, jstring string) {
67+
TWString *stringString = TWStringCreateWithJString(env, string);
68+
jboolean resultValue = (jboolean) TWRippleAddressIsValidString(stringString);
69+
70+
TWStringDelete(stringString);
71+
72+
return resultValue;
73+
}
74+
75+
jstring JNICALL Java_com_wallet_crypto_trustapp_jni_RippleAddress_description(JNIEnv *env, jobject thisObject) {
76+
jclass thisClass = (*env)->GetObjectClass(env, thisObject);
77+
jfieldID handleFieldID = (*env)->GetFieldID(env, thisClass, "nativeHandle", "J");
78+
struct TWRippleAddress *instance = (struct TWRippleAddress *) (*env)->GetLongField(env, thisObject, handleFieldID);
79+
80+
jstring result = TWStringJString(TWRippleAddressDescription(instance), env);
81+
82+
83+
(*env)->DeleteLocalRef(env, thisClass);
84+
85+
return result;
86+
}
87+

JNI/cpp/RippleAddress.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright © 2017-2019 Trust.
2+
//
3+
// This file is part of Trust. The full Trust copyright notice, including
4+
// terms governing use, modification, and redistribution, is contained in the
5+
// file LICENSE at the root of the source code distribution tree.
6+
//
7+
// This is a GENERATED FILE, changes made here WILL BE LOST.
8+
//
9+
10+
#ifndef JNI_TW_RIPPLEADDRESS_H
11+
#define JNI_TW_RIPPLEADDRESS_H
12+
13+
#include <jni.h>
14+
#include <TrustWalletCore/TWBase.h>
15+
16+
TW_EXTERN_C_BEGIN
17+
18+
JNIEXPORT
19+
jlong JNICALL Java_com_wallet_crypto_trustapp_jni_RippleAddress_nativeCreateWithString(JNIEnv *env, jclass thisClass, jstring string);
20+
21+
JNIEXPORT
22+
jlong JNICALL Java_com_wallet_crypto_trustapp_jni_RippleAddress_nativeCreateWithData(JNIEnv *env, jclass thisClass, jbyteArray data);
23+
24+
JNIEXPORT
25+
jlong JNICALL Java_com_wallet_crypto_trustapp_jni_RippleAddress_nativeCreateWithPublicKey(JNIEnv *env, jclass thisClass, jobject publicKey);
26+
27+
JNIEXPORT
28+
void JNICALL Java_com_wallet_crypto_trustapp_jni_RippleAddress_nativeDelete(JNIEnv *env, jclass thisClass, jlong handle);
29+
30+
JNIEXPORT
31+
jboolean JNICALL Java_com_wallet_crypto_trustapp_jni_RippleAddress_equals(JNIEnv *env, jclass thisClass, jobject lhs, jobject rhs);
32+
33+
JNIEXPORT
34+
jboolean JNICALL Java_com_wallet_crypto_trustapp_jni_RippleAddress_isValidString(JNIEnv *env, jclass thisClass, jstring string);
35+
36+
JNIEXPORT
37+
jstring JNICALL Java_com_wallet_crypto_trustapp_jni_RippleAddress_description(JNIEnv *env, jobject thisObject);
38+
39+
40+
TW_EXTERN_C_END
41+
42+
#endif // JNI_TW_RIPPLEADDRESS_H

JNI/java/com/wallet/crypto/trustapp/jni/CoinType.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ public enum CoinType {
3030
VECHAIN (818),
3131
WANCHAIN (5718350),
3232
ZCOIN (136),
33-
ZCASH (133);
33+
ZCASH (133),
34+
RIPPLE (144);
3435

3536
private final int value;
3637
CoinType(int value) {
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Copyright © 2017-2019 Trust.
2+
//
3+
// This file is part of Trust. The full Trust copyright notice, including
4+
// terms governing use, modification, and redistribution, is contained in the
5+
// file LICENSE at the root of the source code distribution tree.
6+
//
7+
// This is a GENERATED FILE, changes made here WILL BE LOST.
8+
//
9+
10+
package com.wallet.crypto.trustapp.jni;
11+
12+
import java.security.InvalidParameterException;
13+
import java.util.HashSet;
14+
15+
public class RippleAddress {
16+
private long nativeHandle;
17+
18+
private RippleAddress() {
19+
nativeHandle = 0;
20+
}
21+
22+
static RippleAddress createFromNative(long nativeHandle) {
23+
RippleAddress instance = new RippleAddress();
24+
instance.nativeHandle = nativeHandle;
25+
RippleAddressPhantomReference.register(instance, nativeHandle);
26+
return instance;
27+
}
28+
29+
static native long nativeCreateWithString(String string);
30+
static native long nativeCreateWithData(byte[] data);
31+
static native long nativeCreateWithPublicKey(PublicKey publicKey);
32+
static native void nativeDelete(long handle);
33+
34+
public static native boolean equals(RippleAddress lhs, RippleAddress rhs);
35+
public static native boolean isValidString(String string);
36+
public native String description();
37+
38+
public RippleAddress(String string) {
39+
nativeHandle = nativeCreateWithString(string);
40+
if (nativeHandle == 0) {
41+
throw new InvalidParameterException();
42+
}
43+
44+
RippleAddressPhantomReference.register(this, nativeHandle);
45+
}
46+
47+
public RippleAddress(byte[] data) {
48+
nativeHandle = nativeCreateWithData(data);
49+
if (nativeHandle == 0) {
50+
throw new InvalidParameterException();
51+
}
52+
53+
RippleAddressPhantomReference.register(this, nativeHandle);
54+
}
55+
56+
public RippleAddress(PublicKey publicKey) {
57+
nativeHandle = nativeCreateWithPublicKey(publicKey);
58+
if (nativeHandle == 0) {
59+
throw new InvalidParameterException();
60+
}
61+
62+
RippleAddressPhantomReference.register(this, nativeHandle);
63+
}
64+
65+
}
66+
67+
class RippleAddressPhantomReference extends java.lang.ref.PhantomReference<RippleAddress> {
68+
private static java.util.Set<RippleAddressPhantomReference> references = new HashSet<RippleAddressPhantomReference>();
69+
private static java.lang.ref.ReferenceQueue<RippleAddress> queue = new java.lang.ref.ReferenceQueue<RippleAddress>();
70+
private long nativeHandle;
71+
72+
private RippleAddressPhantomReference(RippleAddress referent, long nativeHandle) {
73+
super(referent, queue);
74+
this.nativeHandle = nativeHandle;
75+
}
76+
77+
static void register(RippleAddress referent, long nativeHandle) {
78+
references.add(new RippleAddressPhantomReference(referent, nativeHandle));
79+
}
80+
81+
public static void doDeletes() {
82+
RippleAddressPhantomReference ref = (RippleAddressPhantomReference) queue.poll();
83+
for (; ref != null; ref = (RippleAddressPhantomReference) queue.poll()) {
84+
RippleAddress.nativeDelete(ref.nativeHandle);
85+
references.remove(ref);
86+
}
87+
}
88+
}

include/TrustWalletCore/TWCoinType.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ enum TWCoinType {
3434
TWCoinTypeWanChain = 5718350,
3535
TWCoinTypeZcoin = 136,
3636
TWCoinTypeZcash = 133,
37+
TWCoinTypeRipple = 144,
3738
};
3839

3940
TW_EXTERN_C_END
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright © 2017-2019 Trust.
2+
//
3+
// This file is part of Trust. The full Trust copyright notice, including
4+
// terms governing use, modification, and redistribution, is contained in the
5+
// file LICENSE at the root of the source code distribution tree.
6+
7+
#pragma once
8+
9+
#include "TWBase.h"
10+
#include "TWData.h"
11+
#include "TWHRP.h"
12+
#include "TWString.h"
13+
14+
TW_EXTERN_C_BEGIN
15+
16+
struct TWPublicKey;
17+
18+
/// Represents a Ripple address.
19+
TW_EXPORT_CLASS
20+
struct TWRippleAddress;
21+
22+
/// Compares two addresses for equality.
23+
TW_EXPORT_STATIC_METHOD
24+
bool TWRippleAddressEqual(struct TWRippleAddress *_Nonnull lhs, struct TWRippleAddress *_Nonnull rhs);
25+
26+
/// Determines if the string is a valid Ripple address.
27+
TW_EXPORT_STATIC_METHOD
28+
bool TWRippleAddressIsValidString(TWString *_Nonnull string);
29+
30+
/// Creates an address from a string representaion.
31+
TW_EXPORT_STATIC_METHOD
32+
struct TWRippleAddress *_Nullable TWRippleAddressCreateWithString(TWString *_Nonnull string);
33+
34+
/// Creates an address from a raw data representaion.
35+
TW_EXPORT_STATIC_METHOD
36+
struct TWRippleAddress *_Nullable TWRippleAddressCreateWithData(TWData *_Nonnull data);
37+
38+
/// Creates an address from a public key.
39+
TW_EXPORT_STATIC_METHOD
40+
struct TWRippleAddress *_Nullable TWRippleAddressCreateWithPublicKey(struct TWPublicKey publicKey);
41+
42+
TW_EXPORT_METHOD
43+
void TWRippleAddressDelete(struct TWRippleAddress *_Nonnull address);
44+
45+
/// Returns the address string representation.
46+
TW_EXPORT_PROPERTY
47+
TWString *_Nonnull TWRippleAddressDescription(struct TWRippleAddress *_Nonnull address);
48+
49+
TW_EXTERN_C_END

src/HDWallet.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "Bitcoin/Bech32Address.h"
1010
#include "Bitcoin/CashAddress.h"
1111
#include "Zcash/TAddress.h"
12+
#include "Ripple/Address.h"
1213

1314
#include <TrezorCrypto/base58.h>
1415
#include <TrezorCrypto/bip32.h>
@@ -131,6 +132,10 @@ std::optional<std::string> HDWallet::getAddressFromExtended(const std::string& e
131132
auto address = Zcash::TAddress(reinterpret_cast<PublicKey&>(publicKey), TWP2PKHPrefixZcashT);
132133
string = address.string();
133134
} break;
135+
case TWCoinTypeRipple: {
136+
auto address = Ripple::Address(reinterpret_cast<PublicKey&>(publicKey));
137+
string = address.string();
138+
} break;
134139
default:
135140
// Unknown coin
136141
return nullptr;

src/Ripple/Address.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright © 2017-2019 Trust.
2+
//
3+
// This file is part of Trust. The full Trust copyright notice, including
4+
// terms governing use, modification, and redistribution, is contained in the
5+
// file LICENSE at the root of the source code distribution tree.
6+
7+
#include "Address.h"
8+
9+
#include <TrezorCrypto/base58.h>
10+
#include <TrezorCrypto/ripple/base58.h>
11+
#include <TrezorCrypto/ecdsa.h>
12+
#include "../HexCoding.h"
13+
14+
using namespace TW::Ripple;
15+
16+
bool Address::isValid(const std::string& string) {
17+
size_t capacity = 128;
18+
uint8_t buffer[capacity];
19+
20+
int size = xrp_base58_decode_check(string.data(), HASHER_SHA2D, buffer, (int)capacity);
21+
if (size != Address::size) {
22+
return false;
23+
}
24+
25+
return true;
26+
}
27+
28+
Address::Address(const std::string& string) {
29+
size_t capacity = 128;
30+
uint8_t buffer[capacity];
31+
int size = xrp_base58_decode_check(string.data(), HASHER_SHA2D, buffer, (int)capacity);
32+
assert(size == Address::size);
33+
std::vector<uint8_t> vec(&buffer[0], &buffer[128]);
34+
auto str = TW::hex(vec);
35+
memcpy(bytes, buffer, Address::size);
36+
}
37+
38+
Address::Address(const std::vector<uint8_t>& data) {
39+
assert(isValid(data));
40+
std::copy(data.begin(), data.end(), bytes);
41+
}
42+
43+
Address::Address(const PublicKey& publicKey) {
44+
/// see type prefix: https://developers.ripple.com/base58-encodings.html
45+
bytes[0] = 0x00;
46+
ecdsa_get_pubkeyhash(publicKey.bytes.data(), HASHER_SHA2_RIPEMD, bytes + 1);
47+
}
48+
49+
std::string Address::string() const {
50+
size_t size = 0;
51+
base58_encode(nullptr, &size, bytes, Address::size, xrp_b58digits);
52+
size += 16;
53+
54+
std::string str(size, ' ');
55+
xrp_base58_encode_check(bytes, Address::size, HASHER_SHA2D, &str[0], size);
56+
57+
return std::string(str.c_str());
58+
}

0 commit comments

Comments
 (0)