Commit 915dd554 authored by Marek Kotewicz's avatar Marek Kotewicz
Browse files

rust -> c -> swift -> objc -> js bridge works

parent 183b8117
# rust output file
*.a
# OSX
#
.DS_Store
......
//
// EthkeyBridge.swift
// NativeSigner
//
// Created by Marek Kotewicz on 19/02/2017.
// Copyright © 2017 Facebook. All rights reserved.
//
import Foundation
@objc(EthkeyBridge)
class EthkeyBridge: NSObject {
@objc func show(_ name: String) {
NSLog("%@", name);
}
@objc func brainWallet(_ seed: NSString, callback: RCTResponseSenderBlock) -> Void {
let s = tmp_string()
let tmp_s = String.fromStringPtr(ptr: s!.pointee)
callback([tmp_s as NSString])
}
}
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import <React/RCTBridgeModule.h>
#import "signer.h"
......@@ -26,6 +26,10 @@
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
8E82ABE6A351418899C5974A /* libRCTCamera.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0462DF64F1D24C8E8B6E90B1 /* libRCTCamera.a */; };
AA0792CD4D7F417B8C8D17CF /* libRNRandomBytes.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 24A2115276994AD5AED9321A /* libRNRandomBytes.a */; };
EA529FD21E5A00B2004DF471 /* EthkeyBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = EA529FD11E5A00B2004DF471 /* EthkeyBridge.m */; };
EA529FF31E5A4261004DF471 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA529FF21E5A4261004DF471 /* String.swift */; };
EA529FF51E5A4EF2004DF471 /* EthkeyBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA529FF41E5A4EF2004DF471 /* EthkeyBridge.swift */; };
EA529FFA1E5A52AD004DF471 /* libsigner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EA529FF91E5A52AD004DF471 /* libsigner.a */; };
EAB49CE81E482E090066C283 /* libRNRandomBytes.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EAB49CE71E482DBF0066C283 /* libRNRandomBytes.a */; };
/* End PBXBuildFile section */
......@@ -255,6 +259,13 @@
78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = "<group>"; };
821AED75338B40468A2A8B7A /* RCTCamera.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RCTCamera.xcodeproj; path = "../node_modules/react-native-camera/ios/RCTCamera.xcodeproj"; sourceTree = "<group>"; };
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = "<group>"; };
EA529FD11E5A00B2004DF471 /* EthkeyBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = EthkeyBridge.m; path = NativeSigner/EthkeyBridge.m; sourceTree = "<group>"; };
EA529FF01E5A3FAB004DF471 /* signer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = signer.h; sourceTree = "<group>"; };
EA529FF11E5A4260004DF471 /* NativeSigner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NativeSigner-Bridging-Header.h"; sourceTree = "<group>"; };
EA529FF21E5A4261004DF471 /* String.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = String.swift; path = NativeSigner/String.swift; sourceTree = "<group>"; };
EA529FF41E5A4EF2004DF471 /* EthkeyBridge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EthkeyBridge.swift; sourceTree = "<group>"; };
EA529FF71E5A525F004DF471 /* libsigner.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsigner.a; path = ../rust/signer/libsigner.a; sourceTree = "<group>"; };
EA529FF91E5A52AD004DF471 /* libsigner.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsigner.a; path = ../rust/signer/libsigner.a; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
......@@ -277,6 +288,7 @@
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */,
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */,
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */,
EA529FFA1E5A52AD004DF471 /* libsigner.a in Frameworks */,
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */,
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */,
832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
......@@ -370,13 +382,19 @@
13B07FAE1A68108700A75B9A /* NativeSigner */ = {
isa = PBXGroup;
children = (
EA529FF91E5A52AD004DF471 /* libsigner.a */,
008F07F21AC5B25A0029DE68 /* main.jsbundle */,
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
13B07FB01A68108700A75B9A /* AppDelegate.m */,
EA529FD11E5A00B2004DF471 /* EthkeyBridge.m */,
EA529FF21E5A4261004DF471 /* String.swift */,
EA529FF41E5A4EF2004DF471 /* EthkeyBridge.swift */,
EA529FF01E5A3FAB004DF471 /* signer.h */,
13B07FB51A68108700A75B9A /* Images.xcassets */,
13B07FB61A68108700A75B9A /* Info.plist */,
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
13B07FB71A68108700A75B9A /* main.m */,
EA529FF11E5A4260004DF471 /* NativeSigner-Bridging-Header.h */,
);
name = NativeSigner;
sourceTree = "<group>";
......@@ -450,6 +468,7 @@
832341AE1AAA6A7D00B99B32 /* Libraries */,
00E356EF1AD99517003FC87E /* NativeSignerTests */,
83CBBA001A601CBA00E9B192 /* Products */,
EA529FF61E5A525F004DF471 /* Frameworks */,
);
indentWidth = 2;
sourceTree = "<group>";
......@@ -464,6 +483,14 @@
name = Products;
sourceTree = "<group>";
};
EA529FF61E5A525F004DF471 /* Frameworks */ = {
isa = PBXGroup;
children = (
EA529FF71E5A525F004DF471 /* libsigner.a */,
);
name = Frameworks;
sourceTree = "<group>";
};
EA75C33B1E3F45880098CCC9 /* Products */ = {
isa = PBXGroup;
children = (
......@@ -535,6 +562,7 @@
};
13B07F861A680F5B00A75B9A = {
DevelopmentTeam = T4ZYEBHX9P;
LastSwiftMigration = 0810;
};
};
};
......@@ -853,7 +881,10 @@
buildActionMask = 2147483647;
files = (
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
EA529FF31E5A4261004DF471 /* String.swift in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
EA529FD21E5A00B2004DF471 /* EthkeyBridge.m in Sources */,
EA529FF51E5A4EF2004DF471 /* EthkeyBridge.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -883,6 +914,7 @@
00E356F61AD99517003FC87E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
DEVELOPMENT_TEAM = T4ZYEBHX9P;
GCC_PREPROCESSOR_DEFINITIONS = (
......@@ -906,6 +938,7 @@
00E356F71AD99517003FC87E /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
COPY_PHASE_STRIP = NO;
DEVELOPMENT_TEAM = T4ZYEBHX9P;
......@@ -927,17 +960,23 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = NO;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = T4ZYEBHX9P;
INFOPLIST_FILE = NativeSigner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = ../rust/signer;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
"-lc++",
);
PRODUCT_NAME = NativeSigner;
SWIFT_OBJC_BRIDGING_HEADER = "NativeSigner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 3.0.1;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
......@@ -946,16 +985,21 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = T4ZYEBHX9P;
INFOPLIST_FILE = NativeSigner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = ../rust/signer;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
"-lc++",
);
PRODUCT_NAME = NativeSigner;
SWIFT_OBJC_BRIDGING_HEADER = "NativeSigner-Bridging-Header.h";
SWIFT_VERSION = 3.0.1;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
......
......@@ -8,7 +8,7 @@
*/
#import "AppDelegate.h"
#import "NativeSigner-Swift.h"
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
......@@ -16,6 +16,10 @@
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
EthkeyBridge* bridge;
[bridge brainWallet:@[] callback:^(NSArray *cb) {
}];
NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
......
//
// EthkeyBridge.m
// NativeSigner
//
// Created by Marek Kotewicz on 19/02/2017.
// Copyright © 2017 Facebook. All rights reserved.
//
#import <React/RCTBridgeModule.h>
@interface RCT_EXTERN_MODULE(EthkeyBridge, NSObject)
RCT_EXTERN_METHOD(show:(NSString *)name)
RCT_EXTERN_METHOD(brainWallet:(NSString*)seed callback:(RCTResponseSenderBlock)callback)
@end
//
// String.swift
// NativeSigner
//
// Created by Marek Kotewicz on 19/02/2017.
// Copyright © 2017 Facebook. All rights reserved.
//
import Foundation
extension String {
static func fromStringPtr(ptr: string_ptr) -> String {
let data = NSData(bytes: UnsafeRawPointer(ptr.ptr), length: ptr.len)
return String(data: data as Data, encoding: String.Encoding.utf8)!
}
func asPtr() -> string_ptr {
let data = self.data(using: String.Encoding.utf8, allowLossyConversion: false)!
return string_ptr(ptr: (data as NSData).bytes.bindMemory(to: UInt8.self, capacity: data.count), len: data.count)
}
}
#pragma once
#include <stdint.h>
// string
struct string_ptr {
const uint8_t* ptr;
size_t len;
};
// removes string pointer
void ethstore_string_destroy(struct string_ptr* s);
// keypair pointer
struct keypair_ptr;
// creates new brainwallet keypair from seed
struct keypair_ptr* ethstore_keypair_brainwallet(const struct string_ptr* seed);
// removes keypair pointer
void ethstore_keypair_destroy(struct keypair_ptr* keypair);
struct string_ptr* ethstore_keypair_address(const struct keypair_ptr* keypair);
// test
struct string_ptr* tmp_string();
......@@ -4,6 +4,8 @@ version = "0.1.0"
authors = ["debris <marek.kotewicz@gmail.com>"]
[dependencies]
libc = "0.2"
ethkey = { git = "https://github.com/ethcore/parity" }
[lib]
name = "signer"
......
#pragma once
#include <stdint.h>
// string
struct string_ptr {
const uint8_t* ptr;
size_t len;
};
// removes string pointer
void ethkey_string_destroy(struct string_ptr* s);
// keypair pointer
struct keypair_ptr;
// creates new brainwallet keypair from seed
struct keypair_ptr* ethkey_keypair_brainwallet(const struct string_ptr* seed);
// removes keypair pointer
void ethkey_keypair_destroy(struct keypair_ptr* keypair);
struct string_ptr* ethkey_keypair_address(const struct keypair_ptr* keypair);
// test
struct string_ptr* tmp_string();
extern crate libc;
mod string;
use string::StringPtr;
#[no_mangle]
pub extern fn tmp_string() -> *mut StringPtr {
let hello: StringPtr = "hello from rust".into();
// let's put it on the heap
let boxed_hello = Box::new(hello);
// let's make a pointer to the heap, return it and forget about it
Box::into_raw(boxed_hello)
}
#[no_mangle]
pub extern fn simple() -> i32 {
1234
12345
}
#[cfg(test)]
......
use libc::size_t;
// Helper struct that we'll use to give strings to C.
#[repr(C)]
pub struct StringPtr {
pub ptr: *const u8,
pub len: size_t,
}
impl<'a> From<&'a str> for StringPtr {
fn from(s: &'a str) -> Self {
StringPtr{
ptr: s.as_ptr(),
len: s.len() as size_t,
}
}
}
impl StringPtr {
pub fn as_str(&self) -> &str {
use std::slice;
use std::str;
unsafe {
let slice = slice::from_raw_parts(self.ptr, self.len);
str::from_utf8(slice).unwrap()
}
}
}
......@@ -20,13 +20,13 @@ export default class AccountDetails extends Component {
<Text style={styles.text}>Address</Text>
<Text style={styles.props}>{this.props.account.address}</Text>
<View style={styles.buttonContainer}>
<Button
{/*<Button
style={styles.button}
onPress={this.props.onSendTransactionPressed}
title='Send Transaction'
color='green'
accessibilityLabel='Press to send new transaction'
/>
/>*/}
<Button
style={styles.button}
onPress={() => this.props.onDeleteAccountPressed(this.props.account)}
......
......@@ -34,7 +34,7 @@ const scenes = Actions.create(
<Scene key='root'>
<Scene key='tabs' tabs style={styles.tabbar}>
<Scene key='left' title='Scan QR' initial icon={TabIcon} navigationBarStyle={styles.navibar} titleStyle={styles.navibarTitle}>
<Scene key='scan' component={QrScanner} title='Scan QR' rightTitle="confirmX"
<Scene key='scan' component={QrScanner} title='Scan QR' rightTitle="skip :)"
onRight={() => Actions.confirm()} rightButtonTextStyle={styles.navibarTitle}/>
<Scene key='confirm' component={ConfirmTransaction} title='Sign Tx'/>
<Scene key='select' title='Select Account' component={SelectAccount}/>
......
......@@ -4,8 +4,8 @@ import { connect } from 'react-redux'
import { Actions } from 'react-native-router-flux'
import debounce from 'debounce'
import NewAccountInput from '../components/NewAccountInput'
import { words } from '../actions/random'
import { keypairFromPhrase, toAddress } from '../actions/crypto'
import { words } from '../util/random'
import { keypairFromPhrase, toAddress, toAddressAsync } from '../util/crypto'
import { selectAccount } from '../actions/accounts'
const mapDispatchToProps = (dispatch) => {
......@@ -30,6 +30,7 @@ export class NewAccount extends Component {
this.state = {
seed: seed,
keypair: keypairFromPhrase(seed),
address: '',
name: '',
}
}
......@@ -53,9 +54,17 @@ export class NewAccount extends Component {
/>
<Text style={styles.hint}>brain wallet seed</Text>
<NewAccountInput seed={this.state.seed} onChangeText={
debounce((text) => self.setState({keypair: keypairFromPhrase(text)}), 100)
}/>
<Text style={styles.hint} adjustsFontSizeToFit={true}>0x{toAddress(this.state.keypair)}</Text>
debounce((text) => {
var keypair = keypairFromPhrase(text)
toAddressAsync(keypair, (address) => {
self.setState({
keypair: keypairFromPhrase(text),
address: address,
})
})
}, 100)}
/>
<Text style={styles.hint} adjustsFontSizeToFit={true}>0x{this.state.address}</Text>
<Button
onPress={() => this.props.addAccount({
keypair: this.state.keypair,
......
......@@ -4,9 +4,11 @@ const initialAccounts = {
all: [{
address: 'mock',
name: 'dupa',
pin: '',
}, {
address: 'mock',
name: 'Katar',
pin: '',
}],
selected: {},
}
......
import { ec } from 'elliptic'
import { keccak_256 } from 'js-sha3'
var secp = new ec('secp256k1')
import { EthkeyBridge } from 'NativeModules'
export function keypairFromPhrase(phrase) {
var seed = keccak_256.array(phrase);
var kp;
for (var i = 0; i <= 16384 || !toAddress(kp = secp.keyFromPrivate(seed)).startsWith('00'); ++i)
seed = keccak_256.array(seed)
return kp
var seed = keccak_256.array(phrase);
var kp;
for (var i = 0; i <= 16384 || !toAddress(kp = secp.keyFromPrivate(seed)).startsWith('00'); ++i)
seed = keccak_256.array(seed)
return kp
}
export function toAddress(kp) { return keccak_256(kp.getPublic('buffer').slice(1)).substr(24); }
export function toAddressAsync(kp, callback) {
//EthkeyBridge.show("hello")
EthkeyBridge.brainWallet("" + 1, callback)
//return
}
......@@ -6,7 +6,3 @@ export function words() {
return Array.from(buf).map(n => dictionary[n]).join(' ')
}
// this should be later replaced with random keypair
export function address() {
return '0xb794f5ea0ba39494ce839613fffba74279579268'
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment