This commit is contained in:
Jennifer Muenk 2018-01-25 00:46:01 +01:00
commit 6cb3842798
38 changed files with 1536 additions and 1001 deletions

View File

@ -0,0 +1,20 @@
package com.flashwifi.wifip2p;
/**
* Created by daniel on 23.01.18.
*/
public class Constants {
public interface ACTION {
public static String MAIN_ACTION = "com.flashwifi.wifip2p.service.main";
public static String PREV_ACTION = "com.flashwifi.wifip2p.service.prev";
public static String PLAY_ACTION = "com.flashwifi.wifip2p.service.play";
public static String NEXT_ACTION = "com.flashwifi.wifip2p.service.next";
public static String STARTFOREGROUND_ACTION = "com.flashwifi.wifip2p.start_foreground_service";
public static String STOPFOREGROUND_ACTION = "com.flashwifi.wifip2p.sop_foreground_service";
}
public interface NOTIFICATION_ID {
public static int FOREGROUND_SERVICE = 101;
}
}

View File

@ -85,7 +85,7 @@ public class FundWalletFragment extends Fragment {
transactionInProgress = false;
if(returnStatus.equals("noError")){
balanceTextView.setText(balance + " i");
balanceTextView.setText(balance);
addressTextView.setText(depositAddress);
createAddressQRCode(depositAddress);
makeToastFundWalletFragment("Balance and address updated");

View File

@ -23,10 +23,8 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.flashwifi.wifip2p.iotaFlashWrapper.Example;
import com.flashwifi.wifip2p.iotaFlashWrapper.IotaFlashBridge;
import com.flashwifi.wifip2p.iotaFlashWrapper.Main;
import com.google.common.base.Charsets;
import com.google.common.io.CharStreams;
import com.pddstudio.preferences.encrypted.EncryptedPreferences;
import java.io.BufferedReader;
@ -102,14 +100,16 @@ public class HomeActivity extends AppCompatActivity {
String iotaflash = readFile("iotaflash");
String iotaflashhelper = readFile("iotaflashhelper");
/*try {
try {
IotaFlashBridge.boot(iotaflash, iotaflashhelper);
Main.runExample();
Example.setup();
Example.transaction(Example.one, Example.two);
Example.close(Example.one, Example.two);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}*/
}
}
@Override

View File

@ -34,8 +34,6 @@ public class HotspotFragment extends Fragment {
private int numberConnectedPeers = 0;
WiFiDirectBroadcastService mService;
boolean mBound = false;
BroadcastReceiver updateUIReceiver;
public HotspotFragment() {
@ -73,7 +71,7 @@ public class HotspotFragment extends Fragment {
private void updateUi(Intent intent) {
Log.d(TAG, "updateUi: Got some network data into the hotspot fragment");
String numberAvailableDevices = Integer.toString(mService.getArrayList().size());
String numberAvailableDevices = Integer.toString(getmService().getArrayList().size());
TextView text = (TextView) getActivity().findViewById(R.id.numberPeers);
text.setVisibility(View.VISIBLE);
text.setText(String.format("%s peers", numberAvailableDevices));
@ -81,9 +79,9 @@ public class HotspotFragment extends Fragment {
//if (intent.hasExtra("what") && intent.getExtras().getString("what", "").equals("connectivity_changed")) {
NetworkInfo network_info = mService.getNetwork_info();
WifiP2pInfo p2p_info = mService.getP2p_info();
WifiP2pGroup wifiP2pGroup = mService.getP2p_group();
NetworkInfo network_info = getmService().getNetwork_info();
WifiP2pInfo p2p_info = getmService().getP2p_info();
WifiP2pGroup wifiP2pGroup = getmService().getP2p_group();
if (intent.hasExtra("currentDeviceConnected")) {
//String macAddress = intent.getExtras().getString("currentDeviceConnected");
@ -92,11 +90,11 @@ public class HotspotFragment extends Fragment {
if (p2p_info.isGroupOwner) {
Snackbar.make(activity_view, "You are the group owner", Snackbar.LENGTH_LONG).setAction("Action", null).show();
mService.startNegotiationServer(false, null);
getmService().startNegotiationServer(false, null);
} else {
InetAddress groupOwnerAddress = p2p_info.groupOwnerAddress;
Snackbar.make(activity_view, "You are only a member of the group", Snackbar.LENGTH_LONG).setAction("Action", null).show();
mService.startNegotiationClient(groupOwnerAddress, false, null);
getmService().startNegotiationClient(groupOwnerAddress, false, null);
}
}
@ -111,9 +109,7 @@ public class HotspotFragment extends Fragment {
@Override
public void onStop() {
super.onStop();
getActivity().unbindService(mConnection);
getActivity().unregisterReceiver(updateUIReceiver);
mBound = false;
}
@Override
@ -129,6 +125,11 @@ public class HotspotFragment extends Fragment {
initFragment();
}
public WiFiDirectBroadcastService getmService() {
MainActivity act = (MainActivity) getActivity();
return act.getmService();
}
private void initFragment(){
IntentFilter filter = new IntentFilter();
filter.addAction("com.flashwifi.wifip2p.update_ui");
@ -138,6 +139,10 @@ public class HotspotFragment extends Fragment {
updateUIReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (getActivity() == null) {
Log.d(TAG, "onReceive: getActivity is null");
return;
}
if (intent.getAction().equals("com.flashwifi.wifip2p.start_roaming")) {
String mac = intent.getStringExtra("peer_mac_address");
ToggleButton toggle = (ToggleButton) getActivity().findViewById(R.id.startAPButton);
@ -157,10 +162,6 @@ public class HotspotFragment extends Fragment {
getActivity().registerReceiver(updateUIReceiver, filter);
// Bind to Service
Intent intent = new Intent(getActivity(), WiFiDirectBroadcastService.class);
getActivity().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
initUI();
testInternetConnection();
@ -185,29 +186,13 @@ public class HotspotFragment extends Fragment {
// ToDo: Move this to a async task
//boolean status = (isNetworkConnected() && isInternetAvailable());
}
private boolean isNetworkConnected() {
ConnectivityManager cm = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
return cm.getActiveNetworkInfo() != null;
}
public boolean isInternetAvailable() {
try {
InetAddress ipAddr = InetAddress.getByName("google.com");
return !ipAddr.getHostAddress().equals("");
} catch (Exception e) {
return false;
}
}
private void startDiscovery() {
final View activity_view = getActivity().findViewById(R.id.drawer_layout);
if (mBound) {
mService.setInRoleConsumer(false);
mService.setInRoleHotspot(true);
mService.getPeerList(new WifiP2pManager.ActionListener() {
if (getmService() != null) {
getmService().setInRoleConsumer(false);
getmService().setInRoleHotspot(true);
getmService().getPeerList(new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
// show progress wheel
@ -228,12 +213,12 @@ public class HotspotFragment extends Fragment {
private void stopDiscovery() {
final View activity_view = getActivity().findViewById(R.id.drawer_layout);
if (mBound) {
mService.stopDiscovery(new WifiP2pManager.ActionListener() {
if (getmService() != null) {
getmService().stopDiscovery(new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
mService.setInRoleConsumer(false);
mService.setInRoleHotspot(false);
getmService().setInRoleConsumer(false);
getmService().setInRoleHotspot(false);
Snackbar.make(activity_view, "Stopped Hotspot mode", Snackbar.LENGTH_LONG).setAction("Action", null).show();
ProgressBar progressBar = (ProgressBar) getActivity().findViewById(R.id.progressbarAP);
progressBar.setVisibility(View.INVISIBLE);
@ -241,8 +226,8 @@ public class HotspotFragment extends Fragment {
@Override
public void onFailure(int reasonCode) {
mService.setInRoleConsumer(false);
mService.setInRoleHotspot(false);
getmService().setInRoleConsumer(false);
getmService().setInRoleHotspot(false);
Snackbar.make(activity_view, "Aaaargh :( Problem stopping discovery", Snackbar.LENGTH_LONG).setAction("Action", null).show();
ProgressBar progressBar = (ProgressBar) getActivity().findViewById(R.id.progressbarAP);
progressBar.setVisibility(View.INVISIBLE);
@ -255,12 +240,11 @@ public class HotspotFragment extends Fragment {
private void initUI() {
final View activity_view = getActivity().findViewById(R.id.drawer_layout);
final ToggleButton button = (ToggleButton) getActivity().findViewById(R.id.startAPButton);
//button.setChecked(mService.isInRoleHotspot());
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mBound) {
if (!mService.isSetup()) {
if (getmService() != null) {
if (!getmService().isSetup()) {
Snackbar.make(activity_view, "Please enable WiFi P2P", Snackbar.LENGTH_LONG).setAction("Action", null).show();
button.setChecked(false);
return;
@ -276,23 +260,4 @@ public class HotspotFragment extends Fragment {
}
});
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
WiFiDirectBroadcastService.LocalBinder binder = (WiFiDirectBroadcastService.LocalBinder) service;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}

View File

@ -1,5 +1,6 @@
package com.flashwifi.wifip2p;
import android.app.ActivityManager;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.BroadcastReceiver;
@ -13,6 +14,8 @@ import android.net.wifi.p2p.WifiP2pManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.preference.PreferenceManager;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
@ -24,14 +27,13 @@ import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.Switch;
import android.widget.Toast;
import com.flashwifi.wifip2p.billing.Accountant;
import com.flashwifi.wifip2p.broadcast.WiFiDirectBroadcastService;
import com.flashwifi.wifip2p.iotaAPI.Requests.WalletBalanceChecker;
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener
@ -40,6 +42,9 @@ public class MainActivity extends AppCompatActivity
private static final String TAG = "MainAct";
private String password;
private String seed;
private static final int PREF_UPDATE = 2;
private static final int BALANCE_RETRIEVE_TASK_COMPLETE = 1;
private Handler balanceHandler;
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
@ -71,15 +76,27 @@ public class MainActivity extends AppCompatActivity
intent.getStringExtra("key"));
} else if (intent.getAction().equals("com.flashwifi.wifip2p.stop_roaming")) {
Log.d(TAG, "onReceive: Reset billing state");
mService.resetBillingState();
mService.setInRoleConsumer(false);
mService.setInRoleHotspot(false);
}
}
};
registerReceiver(updateUIReceiver, filter);
}
public boolean isTheServiceRunning() {
return isMyServiceRunning(WiFiDirectBroadcastService.class);
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
@Override
protected void onPause() {
super.onPause();
@ -110,7 +127,7 @@ public class MainActivity extends AppCompatActivity
}
private void initUi() {
final Switch switch_ = (Switch) findViewById(R.id.wifiSwitch);
/*final Switch switch_ = (Switch) findViewById(R.id.wifiSwitch);
switch_.setOnCheckedChangeListener(new Switch.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
@ -124,7 +141,7 @@ public class MainActivity extends AppCompatActivity
mService.disableService();
}
}
});
});*/
}
@Override
@ -140,6 +157,9 @@ public class MainActivity extends AppCompatActivity
password = intent.getStringExtra("password");
seed = intent.getStringExtra("seed");
setBalanceHandler();
updateBalance();
Accountant.getInstance().setSeed(seed);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
@ -153,10 +173,29 @@ public class MainActivity extends AppCompatActivity
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
beginForegroundService();
Intent intent2 = new Intent(this, WiFiDirectBroadcastService.class);
bindService(intent2, mConnection, Context.BIND_AUTO_CREATE);
}
public WiFiDirectBroadcastService getmService() {
if (mBound) {
return mService;
}
return null;
}
private void beginForegroundService() {
if (!isTheServiceRunning()) {
Intent startIntent = new Intent(MainActivity.this, WiFiDirectBroadcastService.class);
startIntent.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
startService(startIntent);
} else {
Log.d(TAG, "beginForegroundService: Service is already running");
}
}
private void initEverything() {
subscribeToBroadcasts();
initUi();
@ -245,6 +284,11 @@ public class MainActivity extends AppCompatActivity
return true;
}
private void updateBalance() {
WalletBalanceChecker balanceChecker = new WalletBalanceChecker(this,this.getString(R.string.preference_file_key),seed, balanceHandler,PREF_UPDATE,true);
balanceChecker.execute();
}
public void startSearchFragment() {
if (mBound && mService.isInRoleHotspot()) {
Toast.makeText(this, "Can't start search because you are hotspot", Toast.LENGTH_SHORT).show();
@ -381,6 +425,7 @@ public class MainActivity extends AppCompatActivity
WiFiDirectBroadcastService.LocalBinder binder = (WiFiDirectBroadcastService.LocalBinder) service;
mService = binder.getService();
mBound = true;
mService.enableService();
}
@Override
@ -388,4 +433,34 @@ public class MainActivity extends AppCompatActivity
mBound = false;
}
};
private void setBalanceHandler() {
//Handle post-asynctask activities
balanceHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message inputMessage) {
switch (inputMessage.what) {
case BALANCE_RETRIEVE_TASK_COMPLETE:
AddressBalanceTransfer addressBalanceTransfer = (AddressBalanceTransfer) inputMessage.obj;
String returnStatus = addressBalanceTransfer.getMessage();
if (returnStatus.equals("noError")) {
makeToastBalance("Balance updated");
} else if (returnStatus.equals("hostError")) {
makeToastBalance("Unable to reach host (node)");
} else if (returnStatus.equals("addressError")) {
makeToastBalance("Error getting address");
} else if (returnStatus.equals("balanceError")) {
makeToastBalance("Error getting balance. May not be able to resolve host/node");
} else {
makeToastBalance("Unknown error");
}
}
}
};
}
private void makeToastBalance(String message) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
}

View File

@ -232,50 +232,7 @@ public class RoamingActivity extends AppCompatActivity {
}
private void cancelNotification() {
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.cancel(1);
}
private void showNotification() {
// The id of the channel.
String CHANNEL_ID = "com.flashwifi.wifip2p.roaming_1";
String contentText = mService.isInRoleHotspot() ? "You are providing" : "You are consuming";
// ToDo: make this work on high API version
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.icon_tethering_on)
.setContentTitle("IOTA HOTSPOT")
.setContentText(contentText);
// Creates an explicit intent for an Activity in your app
Intent resultIntent = new Intent(this, RoamingActivity.class);
// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your app to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack for the Intent (but not the Intent itself)
stackBuilder.addParentStack(RoamingActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent =
stackBuilder.getPendingIntent(
0,
PendingIntent.FLAG_UPDATE_CURRENT
);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// mNotificationId is a unique integer your app uses to identify the
// notification. For example, to cancel the notification, you can pass its ID
// number to NotificationManager.cancel().
mNotificationManager.notify(1, mBuilder.build());
}
@ -326,7 +283,8 @@ public class RoamingActivity extends AppCompatActivity {
updateBillingCard();
showNotification();
// ToDo: update notification
//showNotification();
}
private void endRoaming() {
@ -350,6 +308,12 @@ public class RoamingActivity extends AppCompatActivity {
mService.disconnectAP();
}
mService.setRoaming(false);
mService.resetBillingState();
mService.setInRoleConsumer(false);
mService.setInRoleHotspot(false);
PeerStore.getInstance().clear();
// hide the spinner and the stop button
ProgressBar stopProgressBar = (ProgressBar) findViewById(R.id.stopProgressBar);
stopProgressBar.setVisibility(View.GONE);

View File

@ -33,6 +33,7 @@ import java.net.InetAddress;
import java.util.ArrayList;
import com.flashwifi.wifip2p.broadcast.WiFiDirectBroadcastService;
import com.flashwifi.wifip2p.iotaFlashWrapper.Main;
/**
* Fragment that appears in the "content_frame", shows a planet
@ -41,8 +42,6 @@ public class SearchFragment extends Fragment {
public final static String TAG = "SearchActivity";
WiFiDirectBroadcastService mService;
boolean mBound = false;
BroadcastReceiver updateUIReceiver = null;
ArrayList<String> arrayList;
@ -64,6 +63,14 @@ public class SearchFragment extends Fragment {
return rootView;
}
public WiFiDirectBroadcastService getmService() {
MainActivity act = (MainActivity) getActivity();
if (act != null) {
return act.getmService();
}
return null;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -112,7 +119,7 @@ public class SearchFragment extends Fragment {
}
private void startNegotiationProtocol(String macAddress){
WifiP2pInfo p2p_info = mService.getP2p_info();
WifiP2pInfo p2p_info = getmService().getP2p_info();
if (p2p_info.isGroupOwner) {
startNegotiationProtocolServer(macAddress);
@ -123,13 +130,13 @@ public class SearchFragment extends Fragment {
private void startNegotiationProtocolServer(String macAddress) {
// starts the server if necessary
WifiP2pInfo p2p_info = mService.getP2p_info();
NetworkInfo network_info = mService.getNetwork_info();
WifiP2pInfo p2p_info = getmService().getP2p_info();
NetworkInfo network_info = getmService().getNetwork_info();
if (network_info.getState() == NetworkInfo.State.CONNECTED) {
if (p2p_info.isGroupOwner) {
Log.d(TAG, "You are the group owner");
mService.startNegotiationServer(true, macAddress);
getmService().startNegotiationServer(true, macAddress);
Log.d(TAG, "SocketServer started");
}
}
@ -137,8 +144,8 @@ public class SearchFragment extends Fragment {
private void startNegotiationProtocolClient(String macAddress){
// starts the server if necessary
WifiP2pInfo p2p_info = mService.getP2p_info();
NetworkInfo network_info = mService.getNetwork_info();
WifiP2pInfo p2p_info = getmService().getP2p_info();
NetworkInfo network_info = getmService().getNetwork_info();
if (network_info.getState() == NetworkInfo.State.CONNECTED) {
if (!p2p_info.isGroupOwner) {
@ -146,7 +153,7 @@ public class SearchFragment extends Fragment {
// groupOwnerAddress = p2p_info.groupOwnerAddress;
InetAddress groupOwnerAddress = p2p_info.groupOwnerAddress;
Log.d(TAG, "Group owner address: " + p2p_info.groupOwnerAddress.getHostAddress());
mService.startNegotiationClient(groupOwnerAddress, true, macAddress);
getmService().startNegotiationClient(groupOwnerAddress, true, macAddress);
Log.d(TAG, "Client Socket started");
}
}
@ -155,10 +162,6 @@ public class SearchFragment extends Fragment {
@Override
public void onPause() {
super.onPause();
if (mBound) {
getActivity().unbindService(mConnection);
mBound = false;
}
if (updateUIReceiver != null) {
getActivity().unregisterReceiver(updateUIReceiver);
updateUIReceiver = null;
@ -168,10 +171,6 @@ public class SearchFragment extends Fragment {
@Override
public void onStop() {
super.onStop();
if (mBound) {
getActivity().unbindService(mConnection);
mBound = false;
}
if (updateUIReceiver != null) {
getActivity().unregisterReceiver(updateUIReceiver);
updateUIReceiver = null;
@ -200,6 +199,10 @@ public class SearchFragment extends Fragment {
updateUIReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (getActivity() == null) {
Log.d(TAG, "onReceive: getActivity is null");
return;
}
Log.d("", "onReceive: FRAGMENT HAT WAS");
if (intent.getAction().equals("com.flashwifi.wifip2p.start_roaming")) {
String mac = intent.getStringExtra("peer_mac_address");
@ -217,10 +220,6 @@ public class SearchFragment extends Fragment {
};
getActivity().registerReceiver(updateUIReceiver, filter);
// Bind to Service
Intent intent = new Intent(getActivity(), WiFiDirectBroadcastService.class);
getActivity().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
view = getActivity().findViewById(R.id.fragment_view);
initUI();
@ -235,26 +234,20 @@ public class SearchFragment extends Fragment {
toggle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View view) {
if (mBound) {
if (!mService.isSetup()) {
Snackbar.make(view, "Please enable WiFi P2P", Snackbar.LENGTH_LONG).setAction("Action", null).show();
toggle.setChecked(false);
return;
}
if (!getmService().isSetup()) {
Snackbar.make(view, "Please enable WiFi P2P", Snackbar.LENGTH_LONG).setAction("Action", null).show();
toggle.setChecked(false);
return;
}
updateList();
if (toggle.isChecked()) {
if (mBound) {
mService.setInRoleHotspot(false);
mService.setInRoleConsumer(true);
startSearching();
}
getmService().setInRoleHotspot(false);
getmService().setInRoleConsumer(true);
startSearching();
} else {
if (mBound) {
mService.setInRoleHotspot(false);
mService.setInRoleConsumer(false);
stopSearching();
}
getmService().setInRoleHotspot(false);
getmService().setInRoleConsumer(false);
stopSearching();
}
}
});
@ -298,7 +291,7 @@ public class SearchFragment extends Fragment {
public void startChat(final String address, String name) {
mService.connect(address, new WifiP2pManager.ActionListener() {
getmService().connect(address, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Toast.makeText(view.getContext(), "Connected to peer", Toast.LENGTH_SHORT).show();
@ -315,53 +308,31 @@ public class SearchFragment extends Fragment {
}
private void stopSearching() {
if (mBound) {
mService.stopDiscovery(new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Snackbar.make(view, "Stopped search", Snackbar.LENGTH_LONG).setAction("Action", null).show();
}
getmService().stopDiscovery(new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Snackbar.make(view, "Stopped search", Snackbar.LENGTH_LONG).setAction("Action", null).show();
}
@Override
public void onFailure(int reasonCode) {
Snackbar.make(view, "Aaaargh :( problem stopping search!", Snackbar.LENGTH_LONG).setAction("Action", null).show();
}
});
}
@Override
public void onFailure(int reasonCode) {
Snackbar.make(view, "Aaaargh :( problem stopping search!", Snackbar.LENGTH_LONG).setAction("Action", null).show();
}
});
}
public void startSearching() {
getmService().getPeerList(new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Snackbar.make(view, "Successfully searched for peers", Snackbar.LENGTH_LONG).setAction("Action", null).show();
}
if (mBound) {
mService.getPeerList(new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Snackbar.make(view, "Successfully searched for peers", Snackbar.LENGTH_LONG).setAction("Action", null).show();
}
@Override
public void onFailure(int reasonCode) {
Snackbar.make(view, "Aaaargh :( Peering problem!", Snackbar.LENGTH_LONG).setAction("Action", null).show();
}
});
@Override
public void onFailure(int reasonCode) {
Snackbar.make(view, "Aaaargh :( Peering problem!", Snackbar.LENGTH_LONG).setAction("Action", null).show();
}
});
}
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
WiFiDirectBroadcastService.LocalBinder binder = (WiFiDirectBroadcastService.LocalBinder) service;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}

View File

@ -103,13 +103,14 @@ public class SettingsFragment extends PreferenceFragment implements SharedPrefer
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
switch(key){
case "pref_key_security":
makeToastSettingsFragment("Security Changed");
//makeToastSettingsFragment("Security Changed");
break;
case "pref_key_network_timeout":
makeToastSettingsFragment("Network Timeout Changed");
//makeToastSettingsFragment("Network Timeout Changed");
break;
case "pref_key_units":
makeToastSettingsFragment("Units Changed");
//makeToastSettingsFragment("Units Changed");
break;
case "pref_key_switch_testnet":
makeToastSettingsFragment("Testnet on/off Changed");

View File

@ -95,11 +95,11 @@ public class WithdrawWalletFragment extends Fragment {
transactionInProgress = false;
if(returnStatus.equals("noError")){
balanceTextView.setText(appWalletBalance + " i");
balanceTextView.setText(appWalletBalance);
makeToastFundWalletFragment("Balance updated");
}
else if (returnStatus.equals("noErrorNoUpdateMessage")){
balanceTextView.setText(appWalletBalance + " i");
balanceTextView.setText(appWalletBalance);
clearAllTransferValues();
makeFieldsEditable();
}

View File

@ -197,6 +197,7 @@ public class BillingClient {
if (error_count >= maxErrorCount) {
// stop trying to connect
Log.d(TAG, "start: error count too high");
state = State.ERROR;
sendUpdateUIBroadcastWithMessage("Exit");
}

View File

@ -244,13 +244,17 @@ public class BillingServer {
e.printStackTrace();
} finally {
try {
socketWrapper.close();
} catch (IOException e) {
if (socketWrapper != null) {
socketWrapper.close();
}
} catch (Exception e) {
}
try {
serverSocket.close();
} catch (IOException e) {
if (serverSocket != null) {
serverSocket.close();
}
} catch (Exception e) {
}
}

View File

@ -1,11 +1,16 @@
package com.flashwifi.wifip2p.broadcast;
import android.app.Activity;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.DhcpInfo;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.p2p.WifiP2pConfig;
@ -20,9 +25,14 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.text.format.Formatter;
import android.util.Log;
import com.flashwifi.wifip2p.AddressBalanceTransfer;
import com.flashwifi.wifip2p.Constants;
import com.flashwifi.wifip2p.MainActivity;
import com.flashwifi.wifip2p.R;
import com.flashwifi.wifip2p.accesspoint.AccessPointTask;
import com.flashwifi.wifip2p.accesspoint.ConnectTask;
import com.flashwifi.wifip2p.accesspoint.StopAccessPointTask;
@ -38,10 +48,14 @@ import com.flashwifi.wifip2p.protocol.NegotiationFinalization;
import com.flashwifi.wifip2p.protocol.NegotiationOffer;
import com.flashwifi.wifip2p.protocol.NegotiationOfferAnswer;
import org.apache.commons.lang3.ArrayUtils;
import java.io.IOException;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -96,6 +110,57 @@ public class WiFiDirectBroadcastService extends Service {
ConnectTask connectTask;
private boolean negotiatorRunning = false;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals(Constants.ACTION.STARTFOREGROUND_ACTION)) {
Log.i(TAG, "Received Start Foreground Intent ");
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setAction(Constants.ACTION.MAIN_ACTION);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
/*
Intent previousIntent = new Intent(this, WiFiDirectBroadcastService.class);
previousIntent.setAction(Constants.ACTION.PREV_ACTION);
PendingIntent ppreviousIntent = PendingIntent.getService(this, 0,
previousIntent, 0);
Intent playIntent = new Intent(this, WiFiDirectBroadcastService.class);
playIntent.setAction(Constants.ACTION.PLAY_ACTION);
PendingIntent pplayIntent = PendingIntent.getService(this, 0,
playIntent, 0);*/
Intent stopIntent = new Intent(this, WiFiDirectBroadcastService.class);
stopIntent.setAction(Constants.ACTION.STOPFOREGROUND_ACTION);
PendingIntent pstopIntent = PendingIntent.getService(this, 0,
stopIntent, 0);
Bitmap icon = BitmapFactory.decodeResource(getResources(),
R.drawable.icon_tethering_on);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle(getString(R.string.app_name))
.setTicker(getString(R.string.app_name))
.setContentText(getString(R.string.notification_doing_nothing))
.setSmallIcon(R.drawable.icon_tethering_on)
.setLargeIcon(
Bitmap.createScaledBitmap(icon, 128, 128, false))
.setContentIntent(pendingIntent)
.setOngoing(true)
.addAction(R.drawable.icon_tethering_off, "Stop",
pstopIntent).build();
startForeground(Constants.NOTIFICATION_ID.FOREGROUND_SERVICE,
notification);
} else if (intent.getAction().equals(
Constants.ACTION.STOPFOREGROUND_ACTION)) {
Log.i(TAG, "Received Stop Foreground Intent");
stopForeground(true);
stopSelf();
}
return START_STICKY;
}
public boolean isSetup() {
return setup;
}
@ -165,9 +230,23 @@ public class WiFiDirectBroadcastService extends Service {
@Override
public void run() {
BillingClient billingClient = new BillingClient(mac, getApplicationContext());
// ToDo: get the AP gateway ip address
// Gget the AP gateway ip address
// https://stackoverflow.com/questions/9035784/how-to-know-ip-address-of-the-router-from-code-in-android
billingClient.start("192.168.43.1");
final WifiManager manager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
final DhcpInfo dhcp = manager.getDhcpInfo();
byte[] myIPAddress = BigInteger.valueOf(dhcp.gateway).toByteArray();
ArrayUtils.reverse(myIPAddress);
InetAddress myInetIP = null;
String routerIP = null;
try {
myInetIP = InetAddress.getByAddress(myIPAddress);
routerIP = myInetIP.getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
routerIP = "192.168.43.1";
}
Log.d(TAG, "DHCP gateway: " + routerIP);
billingClient.start(routerIP);
// ToDo: handle billingServer EXIT CODES
// -> close the roaming etc.
}
@ -379,7 +458,7 @@ public class WiFiDirectBroadcastService extends Service {
stopAllTasks();
thread.start();
} else {
Log.d(TAG, "startNegotiationClient: BLOCKED due to roaming state");
Log.d(TAG, "startNegotiationClient: BLOCKED due to roaming state or negotiator running");
}

View File

@ -76,14 +76,13 @@ public class WalletAddressChecker {
SharedPreferences prefManager = PreferenceManager.getDefaultSharedPreferences(context);
String security = prefManager.getString("pref_key_security","2");
int securityInt = Integer.parseInt(security);
System.out.println("securityInt: "+securityInt);
addressResponse = api.getNewAddress(seed, securityInt, keyIndex, true, 1, false);
} catch (ArgumentException e) {
e.printStackTrace();
return addressList;
}
if(addressResponse != null) {
System.out.println("WalletAddressChecker - Address: "+addressResponse.getAddresses().get(0));
addressList.add(addressResponse.getAddresses().get(0));
String[] addressesCheckArray = new String[1];
@ -101,7 +100,7 @@ public class WalletAddressChecker {
}
}
if(transactionsForAddress.isEmpty() || (transactionsForAddress.size() == 0 || transactionsForAddress.equals(null))){
if(transactionsForAddress == null || transactionsForAddress.isEmpty() || (transactionsForAddress.size() == 0)){
//Transactions not found, use this address
foundAddress = true;
}
@ -110,11 +109,6 @@ public class WalletAddressChecker {
String curHash = transactionsForAddress.get(0).getHash();
hashStringList.add(curHash);
System.out.println("WalletAddressChecker value: "+transactionsForAddress.get(0).getValue());
System.out.println("WalletAddressChecker time: "+transactionsForAddress.get(0).getAttachmentTimestamp());
System.out.println("WalletAddressChecker address: "+transactionsForAddress.get(0).getAddress());
keyIndex = keyIndex + 1;
}
}
@ -130,34 +124,27 @@ public class WalletAddressChecker {
//Check whether pending transactions exist
containsPendingTransaction = false;
keyIndexChanged = false;
GetInclusionStateResponse inclusionResponse;
try {
GetInclusionStateResponse inclusionResponse = api.getLatestInclusion(hashStringArray);
boolean[] states = inclusionResponse.getStates();
for (boolean state : states) {
if(!state){
containsPendingTransaction = true;
}
}
} catch (ArgumentException e) {
inclusionResponse = api.getLatestInclusion(hashStringArray);
} catch (ArgumentException | IllegalStateException e) {
e.printStackTrace();
return addressList;
}
System.out.println("containsPendingTransaction: "+containsPendingTransaction);
boolean[] states = inclusionResponse.getStates();
for (boolean state : states) {
if(!state){
containsPendingTransaction = true;
}
}
if(!containsPendingTransaction){
//all confirmed transactions, ok to change keyIndex
if(keyIndex != getKeyIndex()){
keyIndexChanged = true;
if(keyIndex == 0){
//Put the initial address to search. No transactions for the seed yet.
putKeyIndex(keyIndex);
}
else{
//Put the second last address to search
putKeyIndex(keyIndex-1);
}
putKeyIndex(keyIndex);
}
}

View File

@ -10,6 +10,8 @@ import android.preference.PreferenceManager;
import com.flashwifi.wifip2p.AddressBalanceTransfer;
import com.flashwifi.wifip2p.R;
import java.text.DateFormat;
import java.util.Date;
import java.util.List;
import jota.IotaAPI;
@ -24,6 +26,7 @@ public class WalletBalanceChecker extends AsyncTask<Void, Void, Void> {
private static final int FUND_WALLET = 0;
private static final int WITHDRAW_WALLET = 1;
private static final int PREF_UPDATE = 2;
private static IotaAPI api;
private static Context context;
@ -76,6 +79,7 @@ public class WalletBalanceChecker extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... voids) {
if(context != null){
WalletAddressChecker addressChecker = new WalletAddressChecker(context,prefFile);
@ -83,8 +87,6 @@ public class WalletBalanceChecker extends AsyncTask<Void, Void, Void> {
boolean containsPendingTransactions = addressChecker.getContainsPendingTransaction();
boolean keyIndexChanged = addressChecker.getkeyIndexChanged();
System.out.println("seed: "+seed);
if(addressList != null && addressList.get(0).equals("Unable to resolve host")){
AddressBalanceTransfer addressBalanceTransfer = new AddressBalanceTransfer(null,null,"hostError");
Message completeMessage = mHandler.obtainMessage(BALANCE_RETRIEVE_TASK_COMPLETE, addressBalanceTransfer);
@ -126,10 +128,6 @@ public class WalletBalanceChecker extends AsyncTask<Void, Void, Void> {
public String getBalance(List<String> inAddresses, boolean containsPendingTransactions, boolean keyIndexChanged){
for (String inAddress : inAddresses) {
System.out.println("addressGetBalance: "+inAddress);
}
String updatedBalanceString;
try {
StopWatch stopWatch = new StopWatch();
@ -140,11 +138,7 @@ public class WalletBalanceChecker extends AsyncTask<Void, Void, Void> {
GetBalancesAndFormatResponse balanceResponse = api.getBalanceAndFormat(inAddresses, 0, 0, stopWatch, securityInt);
long total = balanceResponse.getTotalBalance();
System.out.println("getTotalBalance: "+total);
long storedBaseBalance = Long.parseLong(getBaseSharedPrefKeyBalance());
System.out.println("getBaseSharedPreKeyBalance: "+storedBaseBalance);
long updatedBaseBalance = storedBaseBalance + total;
updatedBalanceString = Long.toString(updatedBaseBalance);
@ -163,26 +157,35 @@ public class WalletBalanceChecker extends AsyncTask<Void, Void, Void> {
//No Pending Transactions, new confirmed transactions
else if(!containsPendingTransactions && keyIndexChanged){
putBaseSharedPrefBalance(updatedBalanceString);
System.out.println("Store new base balance");
System.out.println("updated balance: "+updatedBaseBalance);
updatedBalanceString = Long.toString(updatedBaseBalance);
putSharedPrefBalance(updatedBalanceString);
}
} catch (ArgumentException | IllegalStateException e) {
e.printStackTrace();
return null;
return getSharedPrefKeyBalance()+"i (cached: "+getSharedPrefKeyBalanceDateUpdate()+")";
}
return updatedBalanceString;
String currentDateTimeString = DateFormat.getDateTimeInstance().format(new Date());
putSharedPrefBalanceDateUpdate(currentDateTimeString);
return updatedBalanceString+"i";
}
private void putSharedPrefBalanceDateUpdate(String currentDateTimeString) {
SharedPreferences sharedPref = context.getSharedPreferences(
prefFile, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("balanceDateUpdate", currentDateTimeString);
editor.apply();
}
private String getSharedPrefKeyBalanceDateUpdate() {
SharedPreferences sharedPref = context.getSharedPreferences(prefFile, Context.MODE_PRIVATE);
String defaultValue = "0";
String storedBalance = sharedPref.getString("balanceDateUpdate",defaultValue);
return storedBalance;
}
private String getSharedPrefKeyBalance() {
SharedPreferences sharedPref = context.getSharedPreferences(prefFile, Context.MODE_PRIVATE);
int keyIndex = sharedPref.getInt("keyIndex",0);
System.out.println("KeyIndex: "+keyIndex);
String defaultValue = "0";
String storedBalance = sharedPref.getString("balance",defaultValue);
return storedBalance;
@ -198,10 +201,6 @@ public class WalletBalanceChecker extends AsyncTask<Void, Void, Void> {
private String getBaseSharedPrefKeyBalance() {
SharedPreferences sharedPref = context.getSharedPreferences(prefFile, Context.MODE_PRIVATE);
int keyIndex = sharedPref.getInt("keyIndex",0);
System.out.println("KeyIndex: "+keyIndex);
String defaultValue = "0";
String storedBalance = sharedPref.getString("baseBalance",defaultValue);
return storedBalance;

View File

@ -148,8 +148,6 @@ public class WalletTestnetTokenGen extends AsyncTask<Void, Void, Void> {
private void transferToWallet(List<String> destAddressses, TokenGenJSONResponse token) {
System.out.println("2000 seed: "+token.getSeed());
if(destAddressses != null && destAddressses.get(0).equals("Unable to resolve host")){
//Host Error
Message completeMessage = settingsFragmentHandler.obtainMessage(TOKEN_TESTNET_RETRIEVE_TASK_COMPLETE, "hostError");
@ -161,9 +159,6 @@ public class WalletTestnetTokenGen extends AsyncTask<Void, Void, Void> {
completeMessage.sendToTarget();
String destAddress = destAddressses.get(destAddressses.size()-1);
System.out.println("DestAddress: "+destAddress);
System.out.println("TokenAmt: "+token.getAmount().toString());
WalletTransferRequest transferRequest = new WalletTransferRequest(destAddress,token.getSeed(),token.getAmount().toString(),"","",context,testnetTokenGenHandler);
transferRequest.execute();
}

View File

@ -107,7 +107,6 @@ public class WalletTransferRequest extends AsyncTask<Void, Void, Void> {
try {
if(testnet) {
//Testnet
System.out.println("WalletTransferRequest: Testnet");
if(testnetPrivate){
sendTransferResponse = api.sendTransfer(appWalletSeed, securityInt, 4, 3, transfers, null, null, false);
}
@ -155,7 +154,6 @@ public class WalletTransferRequest extends AsyncTask<Void, Void, Void> {
else{
transferResult = "Transfer error: Send Response not received";
}
System.out.println("WalletTransferRequest - result: "+transferResult);
return transferResult;
}
}

View File

@ -0,0 +1,198 @@
package com.flashwifi.wifip2p.iotaFlashWrapper;
import android.util.Log;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.Bundle;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.CreateTransactionHelperObject;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.Digest;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.Multisig;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.Signature;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.Transfer;
import java.util.ArrayList;
import java.util.List;
/**
* Created by wlad on 24.01.18.
*/
public class Example {
public static FlashChannelHelper one;
public static FlashChannelHelper two;
public static void setup() {
double[] deposits = new double[]{100,100};
int depth = 4;
// Example of a user setup.
one = FlashChannelHelper.getInstance();
one.setupUser(0, "RDNUSLPNOQUGDIZVOINTYRIRRIJMLODOC9ZTQU9KQSCDXPVSBILXUE9AHEOA9MNYZWNSECAVPQ9QSAHCN", 0, 1);
one.setupFlash(deposits, depth);
// Create a second user
// Here i needed a second instance so I left the public in the constructor of FlashChannelHelper
two = new FlashChannelHelper();
two.setupUser(0, "IUQDBHFDXK9EHKC9VUHCUXDLICLRANNDHYRMDYFCGSZMROWCZBLBNRKXWBSWZYDMLLHIHMP9ZPOPIFUSW", 0, 1);
two.setupFlash(deposits, depth);
// The addresses must be exchanged over the network.
// When done setup the settlementAddresses.
ArrayList<String> settlementAddresses = new ArrayList<>();
settlementAddresses.add("EYUSQTMUVAFUGXMJEJYRHVMSCUBDXXKOEPFWPKVJJIY9DDTQJGJRZJTMPZAVBAICZBRGSTBOGCQR9Y9P9");
settlementAddresses.add("EYUSQTMUVAFUGXMJEJYRHVMSCUBDXXKOEPFWPKVJJIY9DDTQJGJRZJTMPZAVBAICZBRGSTBOGCQR9Y9P9");
// Set the addresses
one.setupSettlementAddresses(settlementAddresses);
two.setupSettlementAddresses(settlementAddresses);
// Now generate the digests for each user.
List<Digest> initialDigestsOne = one.initialChannelDigests();
List<Digest> initialDigestsTwo = two.initialChannelDigests();
// Now the users should exchange the digests over the network
// When the both have the digests create a array with them. make sure the order is kept.
List<List<Digest>> digestPairs = new ArrayList<>();
digestPairs.add(initialDigestsOne);
digestPairs.add(initialDigestsTwo);
// This will create the initial multisig addresses and the root address.
one.setupChannelWithDigests(digestPairs);
two.setupChannelWithDigests(digestPairs);
// After this the root must be set. You can check for it using this call.
Log.d("[ROOT ADDR]", one.getRootAddressWithChecksum());
// Now the setup is ready
}
public static void transaction(FlashChannelHelper sender, FlashChannelHelper reciever) {
// Check if we need to expand the tree
CreateTransactionHelperObject helper = sender.getTransactionHelper();
// If the generate value is larget 0 we need to generate some new addresses
if (helper.getGenerate() > 0) {
// Get digests from the sender
ArrayList<Digest> senderDigests = Helpers.getNewBranchDigests(sender.getUser(), helper.getGenerate());
// Send senderDigests to user two and wait for his digests.
// User two makes digests.
ArrayList<Digest> recieverDigests = Helpers.getNewBranchDigests(reciever.getUser(), helper.getGenerate());
// When you have both you can create a digest array
List<List<Digest>> digestPairs = new ArrayList<>();
digestPairs.add(senderDigests);
digestPairs.add(recieverDigests);
// Now each party must generate the digests.
Multisig updatedAddress = one.updateTreeWithDigests(digestPairs, helper.getAddress());
// Since the other user does not have the address to use (the object reference). We search for it.
Multisig extansionMultisigTwo = two.getMultisigByAddress(helper.getAddress().getAddress());
if (extansionMultisigTwo == null) {
Log.d("[ERROR]", "Could not find attachment address for tree expansion.");
}
two.updateTreeWithDigests(digestPairs, extansionMultisigTwo);
// Now the sender just has to update the helper objects multisig address. I will optimize this in the future.
helper.setAddress(updatedAddress);
}
// Now you can perform a transaction
// Create transfers.
ArrayList<Transfer> transfers = new ArrayList<>();
transfers.add(new Transfer(reciever.getSettlementAddress(), 10));
// Create a transaction from a transfer.
ArrayList<Bundle> senderBundles = Helpers.createTransaction(transfers, helper, sender.getUser());
// Now send the senderBundles to the receiver and wait for the response signatures.
// USER2: check if bundle content is okay. Only the first transaction of the last bundle is interesting.
// But if we want to be sure we need to check both bundles and all transactions.
// User two generates signatures if all is okay.
ArrayList<Signature> receiverSignatures = two.createSignaturesForBundles(senderBundles);
// Now both just have to apply the signatures and check if all is good.
ArrayList<Bundle> senderSignedBundles = IotaFlashBridge.appliedSignatures(senderBundles, receiverSignatures);
ArrayList<Bundle> receiverSignedBundles = IotaFlashBridge.appliedSignatures(senderBundles, receiverSignatures);
// Now if all is good just apply. In future I will throw a error on invalid signing.
one.applyTransfers(senderSignedBundles);
two.applyTransfers(receiverSignedBundles);
}
/**
*
* @param sender
* @param reciever
*/
public static void close(FlashChannelHelper sender, FlashChannelHelper reciever) {
// Close is more or a less just a transaction.
// So the start is exactly the same.
// Check if we need to expand the tree
CreateTransactionHelperObject helper = sender.getTransactionHelper();
// If the generate value is larget 0 we need to generate some new addresses
if (helper.getGenerate() > 0) {
// Get digests from the sender
ArrayList<Digest> senderDigests = Helpers.getNewBranchDigests(sender.getUser(), helper.getGenerate());
// Send senderDigests to user two and wait for his digests.
// User two makes digests.
ArrayList<Digest> recieverDigests = Helpers.getNewBranchDigests(reciever.getUser(), helper.getGenerate());
// When you have both you can create a digest array
List<List<Digest>> digestPairs = new ArrayList<>();
digestPairs.add(senderDigests);
digestPairs.add(recieverDigests);
// Now each party must generate the digests.
Multisig updatedAddress = one.updateTreeWithDigests(digestPairs, helper.getAddress());
// Since the other user does not have the address to use (the object reference). We search for it.
Multisig extansionMultisigTwo = two.getMultisigByAddress(helper.getAddress().getAddress());
if (extansionMultisigTwo == null) {
Log.d("[ERROR]", "Could not find attachment address for tree expansion.");
}
two.updateTreeWithDigests(digestPairs, extansionMultisigTwo);
// Now the sender just has to update the helper objects multisig address. I will optimize this in the future.
helper.setAddress(updatedAddress);
}
// Now we create is closing transaction.
ArrayList<Bundle> senderBundles = sender.createCloseTransactions();
// Here the same game as before with the signatures...
// Now send the senderBundles to the receiver and wait for the response signatures.
// USER2: check if bundle content is okay. Only the first transaction of the last bundle is interesting.
// But if we want to be sure we need to check both bundles and all transactions.
// User two generates signatures if all is okay.
ArrayList<Signature> receiverSignatures = two.createSignaturesForBundles(senderBundles);
// Now both just have to apply the signatures and check if all is good.
ArrayList<Bundle> senderSignedBundles = IotaFlashBridge.appliedSignatures(senderBundles, receiverSignatures);
ArrayList<Bundle> receiverSignedBundles = IotaFlashBridge.appliedSignatures(senderBundles, receiverSignatures);
// Now if all is good just apply. In future I will throw a error on invalid signing.
one.applyTransfers(senderSignedBundles);
two.applyTransfers(receiverSignedBundles);
// And here we attach the bundle to the tangle. We can check the response bundles since we may need to rebroadcast them.
// As far as I understand only one needs to send them.
List<Bundle> attachedBundles = Helpers.POWClosedBundle(senderSignedBundles, 4, 13);
}
}

View File

@ -0,0 +1,171 @@
package com.flashwifi.wifip2p.iotaFlashWrapper;
import android.util.Log;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.Bundle;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.CreateTransactionHelperObject;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.Digest;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.FlashObject;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.Multisig;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.Signature;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.UserObject;
import java.util.ArrayList;
import java.util.List;
import jota.utils.Checksum;
/**
* Created by wlad on 24.01.18.
*/
public class FlashChannelHelper {
public static FlashChannelHelper getInstance() {
if (instance == null) {
instance = new FlashChannelHelper();
}
return instance;
}
private static FlashChannelHelper instance;
private UserObject user;
/**
* When ready change public to private and only use a singleton.
*/
public FlashChannelHelper() {}
/**
*
* @param userIndex
* @param seed
* @param seedIndex
* @param security
*/
public void setupUser(int userIndex, String seed, int seedIndex, int security) {
this.user = new UserObject(userIndex, seed, seedIndex, security);
}
/**
*
* @param deposits
* @param depth
*/
public void setupFlash(double[] deposits, int depth) {
if (user == null) {
Log.d("[ERROR]", "setupUser must be called before calling setupFlash");
return;
}
this.user.setFlash(new FlashObject(deposits, depth, user.getSecurity()));
}
/**
* Create digests for the depth of the flash channel. Branches will be added when needed.
* @return
*/
public List<Digest> initialChannelDigests() {
return Helpers.getDigestsForUser(this.user, this.user.getFlash().getDepth());
}
/**
* Sets settlement addresses in the flash object, the addresses must be ordered according to the userIndex.
* @param addresses
*/
public void setupSettlementAddresses(ArrayList<String> addresses) {
if (addresses.size() != user.getFlash().getSignersCount()) {
Log.d("[ERROR]", "Not enough addresses found...");
return;
}
user.getFlash().setSettlementAddresses(addresses);
}
/**
* Combine all user digests pairs, create multisig addresses and setup tree structure.
* @param digestPairs
*/
public void setupChannelWithDigests(List<List<Digest>> digestPairs) {
if (digestPairs.size() != user.getFlash().getSignersCount()) {
Log.d("[ERROR]", " Not enough digest pairs found...");
return;
}
// Create multisigs.
List<Multisig> mulitisigs = Helpers.getMultisigsForUser(digestPairs, user);
// Set renainder address.
Multisig oneRemainderAddr = mulitisigs.remove(0); //shiftCopyArray();
user.getFlash().setRemainderAddress(oneRemainderAddr);
// Build flash trees
for (int i = 1; i < mulitisigs.size(); i++) {
System.out.println(mulitisigs.get(i - 1).toString() + " -> " + mulitisigs.get(i).toString());
mulitisigs.get(i - 1).push(mulitisigs.get(i));
}
user.getFlash().setRoot(mulitisigs.remove(0));
}
public String getRootAddressWithChecksum() {
try {
return Checksum.addChecksum(user.getFlash().getRoot().getAddress());
} catch (Exception e) {
Log.d("[ERROR]", "Failed to get root address");
return "";
}
}
/**
* Transfer utils
*/
/**
* Create new multisig and insert it into the flash channel tree of the user.
* @param digestPairs
* @param address address to which the new address will be attached.
*/
public Multisig updateTreeWithDigests(List<List<Digest>> digestPairs, Multisig address) {
Multisig multisig = Helpers.getNewBranch(digestPairs, user, address);
// Find the multisig with the address and append new address to children
return Helpers.updateMultisigChildrenForUser(user, multisig);
}
public Multisig getMultisigByAddress(String address) {
return user.getFlash().getRoot().find(address);
}
public ArrayList<Signature> createSignaturesForBundles(ArrayList<Bundle> bundles) {
return IotaFlashBridge.sign(user.getFlash().getRoot(), user.getSeed(), bundles);
}
public void applyTransfers(ArrayList<Bundle> signedBundles) {
Helpers.applyTransfers(signedBundles, user);
}
/**
* Closing utils
*/
public ArrayList<Bundle> createCloseTransactions() {
return Helpers.closeChannel(user);
}
/**
* Returns a helper with the address to use and the number of new addresses to generate.
* Please create the new addresses before making the transaction.
* @return
*/
public CreateTransactionHelperObject getTransactionHelper() {
return Helpers.getTransactionHelper(user.getFlash().getRoot());
}
public UserObject getUser() {
return user;
}
public String getSettlementAddress() {
return user.getFlash().getSettlementAddresses().get(user.getUserIndex());
}
}

View File

@ -1,95 +1,467 @@
package com.flashwifi.wifip2p.iotaFlashWrapper;
import com.google.gson.Gson;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.*;
import jota.IotaAPI;
import jota.dto.response.GetBalancesResponse;
import jota.model.Transaction;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Helpers {
public static ArrayList<Bundle> createTransaction(UserObject user, ArrayList<Transfer> transfers, boolean shouldClose) {
CreateTransactionHelperObject toUse = IotaFlashBridge.updateLeafToRoot(user.getFlash().getRoot());
if (toUse.getGenerate() != 0) {
// TODO: tell the server to gen new address.
System.out.println("No more addresses in channel.");
}
private static boolean useTestnet = true;
private static String seedGeneratorURL = "http://87.118.96.200:3000"; //"https://seeedy.tangle.works";
private static String testNetNodeURL = "https://testnet140.tangle.works:443";
private static String netNodeURL = "http://node.iotawallet.info:14265"; // "http://87.118.96.200:14700";//
private static IotaAPI iotaAPI = null;
ArrayList<Transfer> newTransfers;
/**
* Get a transaction object. The object contains the address to use and if required the number of new addresses to generate
* @param root multisig address at the top of the tree
* @return Transaction object with address and number of addresses to create.
*/
public static CreateTransactionHelperObject getTransactionHelper(Multisig root) {
return IotaFlashBridge.updateLeafToRoot(root);
}
if (shouldClose) {
newTransfers = IotaFlashBridge.close(user.getFlash().getSettlementAddresses(), user.getFlash().getDeposits());
} else {
newTransfers = IotaFlashBridge.prepare(
user.getFlash().getSettlementAddresses(),
user.getFlash().getDeposits(),
user.getUserIndex(),
transfers
);
}
/**
*
* @param transfers
* @param toUse Transaction helper object
* @param user
* @return
*/
public static ArrayList<Bundle> createTransaction(ArrayList<Transfer> transfers, CreateTransactionHelperObject toUse, UserObject user) {
// System.out.println("Creating a transaction of" + transfers.getValue() + " to " + transfers.getAddress());
System.out.println("[INFO]: using address " + toUse.getAddress().getAddress() + ", with boundle count" + toUse.getAddress().getBundles().size());
ArrayList<Bundle> bundles = IotaFlashBridge.compose(
user.getFlash().getBalance(),
user.getFlash().getDeposits(),
user.getFlash().getOutputs(),
toUse.getAddress(),
user.getFlash().getRemainderAddress(),
user.getFlash().getTransfers(),
newTransfers,
shouldClose
FlashObject flash = user.getFlash();
ArrayList<Bundle> bundles;
// Prepare a new transaction.
ArrayList<Transfer> newTransfers = IotaFlashBridge.prepare(
flash.getSettlementAddresses(),
flash.getDeposits(),
user.getUserIndex(),
transfers
);
return bundles;
}
public static ArrayList<Signature> signTransaction(UserObject user, ArrayList<Bundle> bundles) {
return IotaFlashBridge.sign(user.getFlash().getRoot(), user.getSeed(), bundles);
}
//
// public static ArrayList<Bundle> appliedSignatures(ArrayList<Bundle> bundles, ArrayList<Signature> signatures) {
// ArrayList<Bundle> clonedBundles = clone(bundles);
// bundles.clone();
//
// for (int i = 0; i < bundles.size(); i++) {
// Signature sig = signatures.get(i);
// Bundle b = bundles.get(i);
// if (sig == null) {
// continue;
// }
//
// ArrayList<Transaction> transactions = b.getBundles();
// String addy = transactions.stream().filter(tx -> tx.getValue() < 0).findFirst().get().getAddress();
// List<Transaction> tmp = transactions.stream()
// .filter(tx -> tx.getAddress().equals(addy))
// .collect(Collectors.toList());
//
// tmp = tmp.subList(sig.getIndex(), sig.getIndex() + sig.getSignatureFragments().size());
//
// for (int j = 0; j < tmp.size(); j++) {
// tmp.get(j).setSignatureFragments(sig.getSignatureFragments().get(j));
// }
// }
//
// return clonedBundles;
// }
public static void applyTransfers(UserObject user, ArrayList<Bundle> bundles) {
FlashObject flash = IotaFlashBridge.applyTransfersToUser(user, bundles);
user.setFlash(flash);
// IotaFlashBridge.applyTransfers(
// user.getFlash().getRoot(),
// user.getFlash().getDeposits(),
// user.getFlash().getOutputs(),
// user.getFlash().getRemainderAddress(),
// user.getFlash().getTransfers(),
// bundles
// );
}
public static ArrayList<Bundle> clone(ArrayList<Bundle> bundles) {
ArrayList<Bundle> clonedBundles = new ArrayList<>();
for (Bundle b : bundles) {
clonedBundles.add(b.clone());
if (newTransfers == null) {
return new ArrayList<>();
}
return clonedBundles;
// Compose the transaction. This may also add some management transactions (moving remainder tokens.)
bundles = IotaFlashBridge.compose(
flash.getBalance(),
flash.getDeposits(),
flash.getOutputs(),
toUse.getAddress(),
flash.getRemainderAddress(),
flash.getTransfers(),
newTransfers,
false
);
System.out.println("[SUCCESS] Created signatures for user" + user.getUserIndex());
// Apply the signature of the transaction creater to the current transactions bundle.
ArrayList<Signature> signatures = IotaFlashBridge.sign(toUse.getAddress(), user.getSeed(), bundles);
System.out.println("[SUCCESS] Parial applied Signature for user" + user.getUserIndex() + " on transfer bundle");
// Sign bundle with your USER ONE'S signatures
return IotaFlashBridge.appliedSignatures(bundles, signatures);
}
public static ArrayList<Bundle> closeChannel(UserObject user) {
FlashObject flash = user.getFlash();
ArrayList<Transfer> closeTransfers = IotaFlashBridge.close(flash.getSettlementAddresses(), flash.getDeposits());
// Compose the transaction. This may also add some management transactions (moving remainder tokens.)
ArrayList<Bundle> bundles = IotaFlashBridge.compose(
flash.getBalance(),
flash.getDeposits(),
flash.getOutputs(),
flash.getRoot(),
flash.getRemainderAddress(),
flash.getTransfers(),
closeTransfers,
true
);
System.out.println("[SUCCESS] Created signatures for user" + user.getUserIndex());
// Apply the signature of the transaction creater to the current transactions bundle.
ArrayList<Signature> signatures = IotaFlashBridge.sign(flash.getRoot(), user.getSeed(), bundles);
System.out.println("[SUCCESS] Parial applied Signature for user" + user.getUserIndex() + " on transfer bundle");
// Sign bundle with your USER ONE'S signatures
return IotaFlashBridge.appliedSignatures(bundles, signatures);
}
/**
*
* Tree management.
*
*/
/**
*
* @param user
* @param toGenerate
* @return
*/
public static ArrayList<Digest> getNewBranchDigests(UserObject user, int toGenerate) {
ArrayList<Digest> digests = new ArrayList<>();
for (int i = 0; i < toGenerate; i++) {
Digest digest = IotaFlashBridge.getDigest(user.getSeed(), user.getSeedIndex(), user.getSecurity());
System.out.println("USING index for digest: " + user.getSeedIndex() );
user.incrementSeedIndex();
digests.add(digest);
}
return digests;
}
/**
*
* @param oneDigests
* @param twoDigests
* @param user
* @param address
* @return
*/
public static Multisig getNewBranch(ArrayList<Digest> oneDigests, ArrayList<Digest> twoDigests, UserObject user, Multisig address) {
List<List<Digest>> userDigestList = new ArrayList<>();
userDigestList.add(oneDigests);
userDigestList.add(twoDigests);
return getNewBranch(userDigestList, user, address);
}
public static Multisig getNewBranch(List<List<Digest>> digestPairs, UserObject user, Multisig address) {
List<Multisig> multisigs = getMultisigsForUser(digestPairs, user);
System.out.println("[INFO]: Adding to address " + address.getAddress());
// Build flash trees
for (int i = 1; i < multisigs.size(); i++) {
multisigs.get(i - 1).push(multisigs.get(i));
}
// Clone the address to avoid overwriting params.
Multisig output = address.clone();
// Add new multisigs to address.
output.push(multisigs.get(0));
return output;
}
/**
*
* Digests and Multisig creation
*
*/
/**
* Creates initial digests for a user. This will only create digests for a given TREE_DEPTH -> Digests.size == TREE_DEPTH + 1
* Other transactions will be generated when required.
* @param user user for which the digests should be generated
* @param TREE_DEPTH number of initial digests to generate
* @return digests for provided user.
*/
public static ArrayList<Digest> getDigestsForUser(UserObject user, int TREE_DEPTH) {
ArrayList<Digest> digests = new ArrayList<>();
// Create digests for the start of the channel
for (int i = 0; i < TREE_DEPTH + 1; i++) {
// Create new digest
Digest digest = IotaFlashBridge.getDigest(
user.getSeed(),
user.getSeedIndex(),
user.getSecurity()
);
user.incrementSeedIndex();
System.out.println("Adding digest (" + digest.toString() + ") to user " + user.getUserIndex());
// Increment key index
digests.add(digest);
}
return digests;
}
/**
*
* @param allDigests
* @param currentUser
* @return
*/
public static List<Multisig> getMultisigsForUser(List<List<Digest>> allDigests, UserObject currentUser) {
// Generate the first addresses
ArrayList<Multisig> multisigs = new ArrayList<Multisig>();
// Loop for all digests.
for (int index = 0; index < allDigests.get(0).size(); index++) {
ArrayList<Digest> alignedDigests = new ArrayList<>();
int securitySum = 0;
// Loop for all users.
for (int userIndex = 0; userIndex < allDigests.size(); userIndex++) {
Digest digest = allDigests.get(userIndex).get(index);
// Get array of digests for all users.
alignedDigests.add(digest);
securitySum += digest.getSecurity();
}
// Create multisgAddr from digests.
Multisig multisig = IotaFlashBridge.composeAddress(alignedDigests);
// Get digests data for current user.
Digest digest = allDigests.get(currentUser.getUserIndex()).get(index);
multisig.setIndex(digest.getIndex());
multisig.setSigningIndex(currentUser.getUserIndex() * digest.getSecurity());
multisig.setSecuritySum(securitySum);
multisig.setSecurity(digest.getSecurity());
System.out.println("Creating address " + multisig.getAddress() + " index" + multisig.getIndex() + " signingIndex: " + multisig.getSigningIndex());
multisigs.add(multisig);
}
return multisigs;
}
/**
*
* @param user
* @param multisig
* @return
*/
public static Multisig updateMultisigChildrenForUser(UserObject user, Multisig multisig) {
FlashObject flash = user.getFlash();
Multisig originAddress = flash.getRoot().find(multisig.getAddress());
if (originAddress != null) {
System.out.println("[INFO]: found address in user" + user.getUserIndex() + " data");
originAddress.setChildren(multisig.getChildren());
originAddress.setBundles(multisig.getBundles());
originAddress.setSecurity(multisig.getSecurity());
return originAddress;
}
return null;
}
/**
* Apply transfers to a user flash state.
* @param signedBundles
* @param user
*/
public static void applyTransfers(ArrayList<Bundle> signedBundles, UserObject user) {
// Apply transfers to User ONE
FlashObject newFlash = IotaFlashBridge.applyTransfersToUser(user, signedBundles);
// Set new flash object to user
user.setFlash(newFlash);
}
/**
* Send trytes array to the node specified in the IotaAPI setup.
* @param trytes
* @param api
* @return returns the transactions applied to the node tangle.
*/
public static List<jota.model.Transaction> sendTrytes(String[] trytes, IotaAPI api, int depth, int minWeightMagnitude) {
try {
System.out.println("[INFO] Sinding close bundle... This can take some time");
List<jota.model.Transaction> txs = api.sendTrytes(trytes, depth, minWeightMagnitude);
return txs;
} catch (IllegalAccessError error) {
System.out.println("[ERROR] " + error.getLocalizedMessage());
} catch (Exception exception) {
System.out.println("[ERROR]: could not send trytes " + exception.getLocalizedMessage());
}
return new ArrayList<jota.model.Transaction>();
}
public static List<Bundle> POWClosedBundle(List<Bundle> bundles, int depth, int minWeightMagnitude) {
List<Bundle> attachedBundles = new ArrayList<>();
for (Bundle b : bundles) {
String[] trytes = b.toTrytesArray();
List<jota.model.Transaction> txs = sendTrytes(trytes, getIotaAPI(), depth, minWeightMagnitude);
if (txs != null && txs.size() > 0) {
Bundle bundle = new Bundle(txs);
attachedBundles.add(bundle);
}
}
return attachedBundles;
}
/**
* creates a new iota instace with the defined url and mode (testnet or not)
* if api instance available the just return it
* @return IotaAPI instance with setup url
*/
public static IotaAPI getIotaAPI() {
if (iotaAPI == null) {
return getNewIotaAPI();
}
return iotaAPI;
}
/**
* Creates a new instance of iota api and override the currently set one.
* Can be used to change url settings.
* @return IotaAPI instance with setup url
*/
public static IotaAPI getNewIotaAPI() {
URL nodeURL;
try {
if (useTestnet) {
nodeURL = new URL(testNetNodeURL);
} else {
nodeURL = new URL(netNodeURL);
}
iotaAPI = new IotaAPI.Builder()
.protocol(nodeURL.getProtocol())
.host(nodeURL.getHost())
.port(String.valueOf(nodeURL.getPort()))
.build();
} catch (Exception e) {
System.out.println("[ERROR] Failed to create IotaAPI instance." + e.getLocalizedMessage());
return null;
}
return iotaAPI;
}
/**
*
* Utilities
*/
/**
* gives a new funded seed from a seedGeneratorURL
* @return
*/
public static GeneratedSeed getNewSeed() {
try {
String seedData = readUrl(seedGeneratorURL);
Gson gson = new Gson();
GeneratedSeed genSeed = gson.fromJson(seedData, GeneratedSeed.class);
return genSeed;
} catch (Exception e) {
System.out.println("[ERROR]: Failed to get new testned seed" + e.getLocalizedMessage());
return null;
}
}
/**
* Get the total left in the flash channel.
* @param user
* @return
*/
public static double getFlashDeposits(UserObject user) {
double sum = 0;
for (double deposit : user.getFlash().getDeposits()) {
sum += deposit;
}
return sum;
}
/**
* get current output of the flash channel. All transactions and remainder.
* @param user UserObject for which to compute amount
* @return amount of IOTA
*/
public static double getBalanceOfUser(UserObject user) {
FlashObject flash = user.getFlash();
double balance = flash.getDeposits().get(user.getUserIndex());
Map<String, Integer> transfers = flash.getOutputs();
for (Map.Entry<String, Integer> transfer : transfers.entrySet()) {
String userSettlementAddr = flash.getSettlementAddresses().get(user.getUserIndex());
if (transfer.getKey().equals(userSettlementAddr)) {
balance += transfer.getValue();
}
}
return balance;
}
/**
* Returns the amount of iota deposited in a selected address
* @param address
* @return
*/
public static long getBalance(String address) {
ArrayList<String> addreses = new ArrayList<>();
addreses.add(address);
IotaAPI api = getIotaAPI();
try {
GetBalancesResponse resp = api.getBalances(100, addreses);
return Long.parseLong(resp.getBalances()[0]);
} catch (Exception e) {
System.out.println("[ERROR]: could not read balance for account " + address + " with error " + e.getLocalizedMessage());
return -1;
}
}
/**
* Utility for reading date from a provided url string.
* @param urlString
* @return
* @throws Exception
*/
private static String readUrl(String urlString) throws Exception {
BufferedReader reader = null;
try {
URL url = new URL(urlString);
reader = new BufferedReader(new InputStreamReader(url.openStream()));
StringBuffer buffer = new StringBuffer();
int read;
char[] chars = new char[1024];
while ((read = reader.read(chars)) != -1)
buffer.append(chars, 0, read);
return buffer.toString();
} finally {
if (reader != null)
reader.close();
}
}
public static Transaction cloneTransaction(jota.model.Transaction transaction) {
return new Transaction(
transaction.getSignatureFragments(),
transaction.getCurrentIndex(),
transaction.getLastIndex(),
transaction.getNonce(),
transaction.getHash(),
transaction.getObsoleteTag(),
transaction.getTimestamp(),
transaction.getTrunkTransaction(),
transaction.getBranchTransaction(),
transaction.getAddress(),
transaction.getValue(),
transaction.getBundle(),
transaction.getTag(),
transaction.getAttachmentTimestamp(),
transaction.getAttachmentTimestampLowerBound(),
transaction.getAttachmentTimestampUpperBound()
);
}
}

View File

@ -1,21 +1,17 @@
package com.flashwifi.wifip2p.iotaFlashWrapper;
import com.eclipsesource.v8.*;
import com.eclipsesource.v8.utils.V8ObjectUtils;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class IotaFlashBridge {
private static V8 engine;
private static V8Object transfer;
@ -45,7 +41,7 @@ public class IotaFlashBridge {
* @param digests
* @return
*/
public static MultisigAddress composeAddress(ArrayList<Digest> digests) {
public static Multisig composeAddress(ArrayList<Digest> digests) {
// Create js object for digest
List<Object> list = new ArrayList<Object>();
for (Digest digest: digests) {
@ -58,17 +54,12 @@ public class IotaFlashBridge {
V8Array params = V8ObjectUtils.toV8Array(engine, paramsList);
V8Object retV8 = multisig.executeObjectFunction("composeAddress", params);
// Parse return values from JS into Java world.
Map<String, ? super Object> resultMap = V8ObjectUtils.toMap(retV8);
// Parse result into Java Obj.
String addr = (String) resultMap.get("address");
int secSum = (Integer) resultMap.get("securitySum");
MultisigAddress ret = new MultisigAddress(addr, secSum);
// Create multisig.
Multisig multisig = V8Converter.multisigAddressFromV8Object(retV8);
params.release();
retV8.release();
return ret;
return multisig;
}
/**
@ -99,7 +90,7 @@ public class IotaFlashBridge {
*
* @param root
*/
public static CreateTransactionHelperObject updateLeafToRoot(MultisigAddress root) {
public static CreateTransactionHelperObject updateLeafToRoot(Multisig root) {
Map<String, Object> map = root.toMap();
// Create param list
List<Object> paramsObj = new ArrayList<Object>();
@ -109,7 +100,7 @@ public class IotaFlashBridge {
V8Object ret = multisig.executeObjectFunction("updateLeafToRoot", params);
int generate = ret.getInteger("generate");
V8Object multisigObject = (V8Object) ret.getObject("multisig");
MultisigAddress multisig = V8Converter.multisigAddressFromV8Object(multisigObject);
Multisig multisig = V8Converter.multisigAddressFromV8Object(multisigObject);
return new CreateTransactionHelperObject(generate, multisig);
}
@ -122,7 +113,7 @@ public class IotaFlashBridge {
* @param transfers array of all transfers (value, address) pairs
* @return
*/
public static ArrayList<Transfer> prepare(ArrayList<String> settlementAddresses, ArrayList<Integer> deposits, int index, ArrayList<Transfer> transfers) {
public static ArrayList<Transfer> prepare(List<String> settlementAddresses, List<Double> deposits, int index, List<Transfer> transfers) {
// Now put all params into JS ready array.
List<Object> params = new ArrayList<>();
@ -132,8 +123,14 @@ public class IotaFlashBridge {
params.add(V8Converter.transferListToV8Array(engine, transfers));
// Call js function.
V8Array ret = transfer.executeArrayFunction("prepare", V8ObjectUtils.toV8Array(engine, params));
return V8Converter.transferListFromV8Array(ret);
try {
V8Array ret = transfer.executeArrayFunction("prepare", V8ObjectUtils.toV8Array(engine, params));
return V8Converter.transferListFromV8Array(ret);
} catch (V8ScriptExecutionException exception) {
return null;
}
}
@ -143,7 +140,7 @@ public class IotaFlashBridge {
* @param deposits
* @return
*/
public static ArrayList<Transfer> close(ArrayList<String> settlementAddresses, ArrayList<Integer> deposits) {
public static ArrayList<Transfer> close(List<String> settlementAddresses, List<Double> deposits) {
V8Array saJS = V8ObjectUtils.toV8Array(engine, settlementAddresses);
// Deposits
V8Array depositsJS = V8ObjectUtils.toV8Array(engine, deposits);
@ -170,27 +167,24 @@ public class IotaFlashBridge {
* @return
*/
public static ArrayList<Bundle> compose(int balance,
List<Integer> deposits,
ArrayList<Bundle> outputs,
MultisigAddress root,
MultisigAddress remainderAddress,
ArrayList<Bundle> history,
ArrayList<Transfer> transfers,
List<Double> deposits,
Map<String, Integer> outputs,
Multisig root,
Multisig remainderAddress,
List<Bundle> history,
List<Transfer> transfers,
boolean close) {
// Create params.
// Now put all params into JS ready array.
List<Object> params = new ArrayList<Object>();
params.add(balance);
params.add(V8ObjectUtils.toV8Array(engine, deposits));
params.add(V8Converter.bundleListToV8Array(engine, outputs));
params.add(V8ObjectUtils.toV8Object(engine, outputs));
params.add(V8Converter.multisigToV8Object(engine, root));
params.add(V8Converter.multisigToV8Object(engine, remainderAddress));
params.add(V8Converter.bundleListToV8Array(engine, history));
params.add(V8Converter.transferListToV8Array(engine, transfers));
params.add(close);
// Call js function.
V8Array ret = transfer.executeArrayFunction("compose", V8ObjectUtils.toV8Array(engine, params));
@ -204,7 +198,7 @@ public class IotaFlashBridge {
* @param bundles
* @return
*/
public static ArrayList<Signature> sign(MultisigAddress root, String seed, ArrayList<Bundle> bundles) {
public static ArrayList<Signature> sign(Multisig root, String seed, ArrayList<Bundle> bundles) {
// Create params.
// Now put all params into JS ready array.
@ -257,10 +251,10 @@ public class IotaFlashBridge {
* @param signedBundles
* @return
*/
public static void applyTransfers(MultisigAddress root,
public static void applyTransfers(Multisig root,
ArrayList<Integer> deposits,
ArrayList<Bundle> outputs,
MultisigAddress remainderAddress,
Multisig remainderAddress,
ArrayList<Bundle> transfers,
ArrayList<Bundle> signedBundles) {
// Construct Java params
@ -288,4 +282,25 @@ public class IotaFlashBridge {
ret.release();
return flash;
}
/// Utils
/**
*
* @param path
* @param encoding
* @return
* @throws IOException
*/
static String readFile(String path, Charset encoding)
throws IOException
{
File file = new File(IotaFlashBridge.class.getClassLoader().getResource(path).getFile());
FileInputStream fis = new FileInputStream(file);
byte[] data = new byte[(int) file.length()];
fis.read(data);
fis.close();
return new String(data, "UTF-8");
}
}

View File

@ -1,245 +0,0 @@
package com.flashwifi.wifip2p.iotaFlashWrapper;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.stream.Collectors;
public class Main {
public static void runExample() throws Exception {
// Run a test based on the flash example
// Link: https://github.com/iotaledger/iota.flash.js/blob/master/examples/flash.js
String oneSeed = "USERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSER";
String oneSettlement = "USERONE9ADDRESS9USERONE9ADDRESS9USERONE9ADDRESS9USERONE9ADDRESS9USERONE9ADDRESS9U";
String twoSeed = "USERTWOUSERTWOUSERTWOUSERTWOUSERTWOUSERTWOUSERTWOUSERTWOUSERTWOUSERTWOUSERTWOUSER";
String twoSettlement = "USERTWO9ADDRESS9USERTWO9ADDRESS9USERTWO9ADDRESS9USERTWO9ADDRESS9USERTWO9ADDRESS9U";
//////////////////////////////////
// INITIAL CHANNEL CONDITIONS
// Security level
int SECURITY = 2;
// Number of parties taking signing part in the channel
int SIGNERS_COUNT = 2;
// Flash tree depth
int TREE_DEPTH = 4;
// Total channel Balance
int CHANNEL_BALANCE = 2000;
// Users deposits
ArrayList<Integer> DEPOSITS = new ArrayList<>();
DEPOSITS.add(1000);
DEPOSITS.add(1000);
// Setup users.
FlashObject oneFlashObj = new FlashObject(SIGNERS_COUNT, CHANNEL_BALANCE, DEPOSITS);
UserObject oneFlash = new UserObject(0, oneSeed, TREE_DEPTH, oneFlashObj);
FlashObject twoFlashObj = new FlashObject(SIGNERS_COUNT, CHANNEL_BALANCE, DEPOSITS);
UserObject twoFlash = new UserObject(1, twoSeed, TREE_DEPTH, twoFlashObj);
// USER ONE
setupUser(oneFlash, TREE_DEPTH);
// USER TWO
setupUser(twoFlash, TREE_DEPTH);
//////////////////////////////////
// INITAL MULTISIG
// Make an array of digests
ArrayList<UserObject> allUsers = new ArrayList<UserObject>();
allUsers.add(oneFlash);
allUsers.add(twoFlash);
// Create partial digests for users.
createInitialPartialDigests(allUsers, oneFlash);
createInitialPartialDigests(allUsers, twoFlash);
ArrayList<MultisigAddress> oneMultisigs = oneFlash.getMultisigDigests();
ArrayList<MultisigAddress> twoMultisigs = twoFlash.getMultisigDigests();
// Set renainder address.
MultisigAddress oneRemainderAddr = oneMultisigs.remove(0); //shiftCopyArray();
oneFlash.getFlash().setRemainderAddress(oneRemainderAddr);
MultisigAddress twoRemainderAddr = twoMultisigs.remove(0);
twoFlash.getFlash().setRemainderAddress(twoRemainderAddr);
// Build flash trees
for (int i = 1; i < oneMultisigs.size(); i++) {
System.out.println(oneMultisigs.get(i - 1).toString() + " -> " + oneMultisigs.get(i).toString());
oneMultisigs.get(i - 1).push(oneMultisigs.get(i));
}
// Build flash trees
for (int i = 1; i < twoMultisigs.size(); i++) {
twoMultisigs.get(i - 1).push(twoMultisigs.get(i));
}
oneFlash.getFlash().setRoot(oneMultisigs.remove(0));
twoFlash.getFlash().setRoot(twoMultisigs.remove(0));
ArrayList<String> settlementAddresses = new ArrayList<>();
settlementAddresses.add(oneSettlement);
settlementAddresses.add(twoSettlement);
oneFlash.getFlash().setSettlementAddresses(settlementAddresses);
twoFlash.getFlash().setSettlementAddresses(settlementAddresses);
// Set digest/key index
oneFlash.setIndex(oneFlash.getPartialDigests().size());
twoFlash.setIndex(twoFlash.getPartialDigests().size());
System.out.println("Channel Setup!");
ArrayList<Transfer> transfers = new ArrayList<>();
transfers.add(new Transfer(twoSettlement, 1));
transfers.add(new Transfer(twoSettlement, 400));
System.out.println(oneFlash);
System.out.println("Creating a transaction: 200 to " + twoSettlement);
ArrayList<Bundle> bundles = Helpers.createTransaction(oneFlash, transfers, false);
ArrayList<Bundle> partialSignedBundles = signTransfer(bundles, oneFlash);
ArrayList<Bundle> signedBundles = signTransfer(partialSignedBundles, twoFlash);
/////////////////////////////////
/// APPLY SIGNED BUNDLES
// Apply transfers to User ONE
Helpers.applyTransfers(oneFlash, signedBundles);
// Save latest channel bundles
oneFlash.setBundles(signedBundles);
// Apply transfers to User TWO
Helpers.applyTransfers(twoFlash, signedBundles);
// Save latest channel bundles
twoFlash.setBundles(signedBundles);
System.out.println("[SUCCESS] Apply Transfer to flash channel.");
System.out.println("Transaction Applied!");
// System.out.println(
// "Transactable tokens: " +
// oneFlash.getFlash().getDeposits().stream().mapToInt(v -> v.intValue()).sum()
// );
System.out.println("Closing channel... not yet working...");
}
private static ArrayList<Bundle> signTransfer(ArrayList<Bundle> bundles, UserObject user) {
System.out.println("[SUCCESS] Created signatures for users.");
ArrayList<Signature> oneSignatures = Helpers.signTransaction(user, bundles);
System.out.println("[SUCCESS] Parial applied Signature for User one on transfer bundle");
// Sign bundle with your USER ONE'S signatures
ArrayList<Bundle> signedBundles = IotaFlashBridge.appliedSignatures(bundles, oneSignatures);
return signedBundles;
}
private static void setupUser(UserObject user, int TREE_DEPTH) {
// Create digests for the start of the channel
for (int i = 0; i < TREE_DEPTH + 1; i++) {
// Create new digest
Digest digest = IotaFlashBridge.getDigest(
user.getSeed(),
user.getIndex(),
user.getSecurity()
);
System.out.println("Adding digest (" + digest.toString() + ") to user " + user.getUserIndex());
// Increment key index
user.incrementIndex();
user.add(digest);
}
}
private static void createInitialPartialDigests(ArrayList<UserObject> allUsers, UserObject currentUser) {
// Generate the first addresses
ArrayList<MultisigAddress> oneMultisigs = new ArrayList<MultisigAddress>();
System.out.println("_________________________________________________________________");
System.out.println("Creating multisigs on user: " + currentUser.getUserIndex());
int index = 0;
// Create address
for (Digest digest: allUsers.get(index).getPartialDigests()) {
int i = index;
ArrayList<Digest> currentDigests = new ArrayList<>();
int securitySum = 0;
for (int j = 0; j < allUsers.size(); j++) {
Digest currentDigest = allUsers.get(j).getPartialDigests().get(i);
currentDigests.add(currentDigest);
securitySum += currentDigest.getSecurity();
}
MultisigAddress addy = IotaFlashBridge.composeAddress(currentDigests);
System.out.println("Multisig: " + addy.toString());
// Add key index in
addy.setIndex(digest.getIndex());
// Add the signing index to the object IMPORTANT
addy.setSigningIndex(currentUser.getUserIndex() * digest.getSecurity());
// Get the sum of all digest security to get address security sum
addy.setSecuritySum(securitySum);
addy.setSecurity(digest.getSecurity());
oneMultisigs.add(addy);
index++;
}
currentUser.setMultisigDigests(oneMultisigs);
}
private static ArrayList<MultisigAddress> shiftCopyArray(ArrayList<MultisigAddress> input) {
ArrayList<MultisigAddress> output = new ArrayList<>();
for (int i = 1; i < input.size(); i++) {
output.add(input.get(i));
}
return output;
}
private static void test() throws IOException {
System.out.println("IOTA Flash channel tester");
String pathToLib = "res/iotaflash.js";
System.out.println("Loading lib into V8 engine");
System.out.println("Lib imported");
System.out.println("Testing getDigest(seed, index, security):");
Digest digest1 = IotaFlashBridge.getDigest("USERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSER", 0, 2);
Digest digest2 = IotaFlashBridge.getDigest("USERTWOUSERTWOUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSERONEUSER", 0, 2);
System.out.println("Digest1: " + digest1.toString());
System.out.println("Testing composeAddress(digests):");
ArrayList<Digest> digests = new ArrayList<Digest>();
digests.add(digest1);
digests.add(digest2);
MultisigAddress composedAddr = IotaFlashBridge.composeAddress(digests);
System.out.println("Got multisig addr for digests: " + composedAddr.getAddress() + ", securitySum: " + composedAddr.getSecuritySum());
testPrepare();
}
private static void testPrepare() {
System.out.println("Testing prepare()");
ArrayList<String> settlementAddr = new ArrayList<String>();
settlementAddr.add("RCZHCRDWMGJPHKROKEGVADVJXPGKEKNJRNLZZFPITUVEWNPGIWNUMKTYKMNB9DCNLWGMJZDNKYQDQKDLC");
ArrayList<Integer> depositsPrep = new ArrayList<Integer>();
ArrayList<Transfer> transfers = new ArrayList<Transfer>();
IotaFlashBridge.prepare(settlementAddr, depositsPrep, 0, transfers);
}
}

View File

@ -1,50 +1,63 @@
package com.flashwifi.wifip2p.iotaFlashWrapper.Model;
import com.flashwifi.wifip2p.iotaFlashWrapper.V8Converter;
import com.flashwifi.wifip2p.iotaFlashWrapper.Helpers;
import jota.model.Transaction;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Bundle extends jota.model.Bundle {
public class Bundle {
private ArrayList<Transaction> bundles;
public Bundle(ArrayList<Transaction> bundles) {
this.bundles = bundles;
public Bundle(List<Transaction> transactions) {
super(transactions, transactions.size());
}
public Bundle() {
this.bundles = new ArrayList<>();
super();
}
@Override
public String toString() {
String out = "";
for (Transaction t: bundles) {
for (Transaction t: getTransactions()) {
out += t.toString();
out += "\n";
}
return out;
}
public String[] toTrytesArray() {
String[] bundleTrytes = new String[getTransactions().size()];
List<jota.model.Transaction> transactions = getTransactions();
for (int i = 0; i < bundleTrytes.length; i++) {
bundleTrytes[(bundleTrytes.length - 1) - i] = transactions.get(i).toTrytes();
}
return bundleTrytes;
}
public Map<String, Object> toMap() {
Map<String, Object> map = new HashMap<String, Object>();
List<Object> bundleList = new ArrayList<Object>();
for (Transaction b: bundles) {
bundleList.add(b.toMap());
}
map.put("bundles", bundleList);
map.put("bundles", toArrayList());
return map;
}
public ArrayList<Transaction> getBundles() {
return bundles;
public List<Object> toArrayList() {
List<Object> bundleList = new ArrayList<Object>();
for (Transaction tx: getTransactions()) {
bundleList.add(V8Converter.transactionToMap(tx));
}
return bundleList;
}
public Bundle clone() {
public Bundle clone() {
ArrayList<Transaction> clonedTransactions = new ArrayList<>();
for (Transaction t: bundles) {
clonedTransactions.add(t.clone());
for (Transaction tx: getTransactions()) {
clonedTransactions.add(Helpers.cloneTransaction(tx));
}
return new Bundle(clonedTransactions);
}

View File

@ -1,11 +1,10 @@
package com.flashwifi.wifip2p.iotaFlashWrapper.Model;
public class CreateTransactionHelperObject {
private int generate = 0;
private MultisigAddress address;
private Multisig address;
public CreateTransactionHelperObject(int gen, MultisigAddress addr) {
public CreateTransactionHelperObject(int gen, Multisig addr) {
this.generate = gen;
this.address = addr;
}
@ -14,7 +13,11 @@ public class CreateTransactionHelperObject {
return generate;
}
public MultisigAddress getAddress() {
public Multisig getAddress() {
return address;
}
public void setAddress(Multisig address) {
this.address = address;
}
}

View File

@ -1,5 +1,4 @@
package com.flashwifi.wifip2p.iotaFlashWrapper.Model;
import java.util.HashMap;
import java.util.Map;
@ -17,7 +16,6 @@ public class Digest {
public int getIndex() {
return index;
}
public String getDigest() {
return digest;
}

View File

@ -0,0 +1,21 @@
package com.flashwifi.wifip2p.iotaFlashWrapper.Model;
public class FlashLibJSException extends Exception {
public enum FlashLibJSExceptionType {
INSUFFICIENT_FUNDS, UNKNOWN
}
private FlashLibJSExceptionType type = FlashLibJSExceptionType.UNKNOWN;
public FlashLibJSException(String string) {
if (string.contains(FlashLibJSExceptionType.INSUFFICIENT_FUNDS.name())) {
this.type = FlashLibJSExceptionType.INSUFFICIENT_FUNDS;
}
}
public FlashLibJSExceptionType getType() {
return type;
}
}

View File

@ -1,28 +1,36 @@
package com.flashwifi.wifip2p.iotaFlashWrapper.Model;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.*;
import com.eclipsesource.v8.utils.V8ObjectUtils;
import java.util.*;
public class FlashObject {
int signersCount = 2;
int balance;
ArrayList<String> settlementAddresses;
ArrayList<Integer> deposits; // Clone correctly
ArrayList<Bundle> outputs = new ArrayList<Bundle>();
ArrayList<Bundle> transfers = new ArrayList<Bundle>();
MultisigAddress root;
MultisigAddress remainderAddress;
private int signersCount = 2;
private int balance;
private List<String> settlementAddresses;
private List<Double> deposits;
private Map<String, Integer> outputs = new HashMap<>();
private List<Bundle> transfers = new ArrayList<Bundle>();
private Multisig root;
private Multisig remainderAddress;
private int depth;
private int security;
public FlashObject(double[] deposits, int depth, int security) {
public FlashObject(int signersCount, int balance, ArrayList<Integer> deposits) {
this.signersCount = signersCount;
this.balance = balance;
this.deposits = deposits;
this.signersCount = deposits.length;
for (double dep : deposits) {
this.balance += dep;
}
this.deposits = new ArrayList<>();
for (double deposit : deposits){
this.deposits.add(deposit);
}
this.depth = depth;
this.security = security;
}
public FlashObject(int signersCount, int balance, ArrayList<String> settlementAddresses, ArrayList<Integer> deposits, ArrayList<Bundle> outputs, ArrayList<Bundle> transfers, MultisigAddress root, MultisigAddress remainderAddress) {
public FlashObject(int signersCount, int balance, List<String> settlementAddresses, List<Double> deposits, Map<String, Integer> outputs, List<Bundle> transfers, Multisig root, Multisig remainderAddress, int depth, int security) {
this.signersCount = signersCount;
this.balance = balance;
this.settlementAddresses = settlementAddresses;
@ -31,35 +39,8 @@ public class FlashObject {
this.transfers = transfers;
this.root = root;
this.remainderAddress = remainderAddress;
}
@Override
public String toString() {
String out = "";
out += "signersCount: " + signersCount + "\n";
out += "balance: " + balance + "\n";
out += "settlementAddresses: " + "\n";
for (String b: settlementAddresses) {
out += "\t" + b + "\n";
}
out += "deposits: " + "\n";
for (Integer b: deposits) {
out += "\t" + b + "\n";
}
out += "outputs: " + "\n";
for (Bundle b: outputs) {
out += "\t" + b.toString() + "\n";
}
out += "transfers: " + "\n";
for (Bundle b: transfers) {
out += "\t" + b.toString() + "\n";
}
out += "remainderAddress: " + remainderAddress.toString() + "\n";
out += "root: " + root.toString() + "\n";
return out;
this.depth = depth;
this.security = security;
}
public Map<String, Object> toMap() {
@ -69,57 +50,62 @@ public class FlashObject {
objectMap.put("root", root.toMap());
objectMap.put("remainderAddress", remainderAddress.toMap());
objectMap.put("settlementAddresses", getSettlementAddresses());
ArrayList<Object> outputMap = new ArrayList<>();
for (Bundle b: outputs) {
outputMap.add(b.toMap());
}
objectMap.put("outputs", outputMap);
objectMap.put("depth", getDepth());
objectMap.put("security", getSecurity());
// Wrap outputs inside an array.
objectMap.put("outputs", getOutputs());
objectMap.put("deposits", getDeposits());
ArrayList<Object> transfersMap = new ArrayList<>();
for (Bundle b: transfers) {
outputMap.add(b.toMap());
for (Bundle b: getTransfers()) {
transfersMap.add(b.toArrayList());
}
objectMap.put("transfers", transfersMap);
return objectMap;
}
public int getSignersCount() {
return signersCount;
}
public int getBalance() {
return balance;
}
public MultisigAddress getRoot() {
public int getSignersCount() {
return signersCount;
}
public int getDepth() {
return depth;
}
public int getSecurity() {
return security;
}
public Multisig getRoot() {
return root;
}
public ArrayList<Integer> getDeposits() {
public List<Double> getDeposits() {
return deposits;
}
public ArrayList<Bundle> getOutputs() {
public Map<String, Integer> getOutputs() {
return outputs;
}
public ArrayList<Bundle> getTransfers() {
public List<Bundle> getTransfers() {
return transfers;
}
public void setRemainderAddress(MultisigAddress remainderAddress) {
public void setRemainderAddress(Multisig remainderAddress) {
this.remainderAddress = remainderAddress;
}
public MultisigAddress getRemainderAddress() {
public Multisig getRemainderAddress() {
return remainderAddress;
}
public void setRoot(MultisigAddress root) {
public void setRoot(Multisig root) {
this.root = root;
}
@ -127,7 +113,7 @@ public class FlashObject {
this.settlementAddresses = settlementAddresses;
}
public ArrayList<String> getSettlementAddresses() {
public List<String> getSettlementAddresses() {
return settlementAddresses;
}
}

View File

@ -0,0 +1,37 @@
package com.flashwifi.wifip2p.iotaFlashWrapper.Model;
public class GeneratedSeed {
private String address;
private String seed;
private long amount;
public GeneratedSeed(String address, String seed, long amount) {
this.address = address;
this.seed = seed;
this.amount = amount;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getSeed() {
return seed;
}
public void setSeed(String seed) {
this.seed = seed;
}
public long getAmount() {
return amount;
}
public void setAmount(long amount) {
this.amount = amount;
}
}

View File

@ -9,35 +9,71 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MultisigAddress {
public class Multisig {
private String address;
private int securitySum;
private int index;
private int signingIndex;
private int security = 2;
private ArrayList<MultisigAddress> children;
private ArrayList<Multisig> children;
private ArrayList<Bundle> bundles;
public MultisigAddress(String address, int securitySum) {
public Multisig(String address, int securitySum) {
this.address = address;
this.securitySum = securitySum;
this.children = new ArrayList<MultisigAddress>();
this.children = new ArrayList<Multisig>();
this.bundles = new ArrayList<Bundle>();
}
public MultisigAddress(String address, int securitySum, ArrayList<MultisigAddress> children) {
public Multisig(String address, int securitySum, ArrayList<Multisig> children) {
this.address = address;
this.securitySum = securitySum;
this.children = children;
this.bundles = new ArrayList<Bundle>();
}
public void push(MultisigAddress addr) {
public Multisig find(String address) {
if (getAddress().equals(address)) {
return this;
} else {
for (Multisig mult: getChildren()) {
Multisig result = mult.find(address);
if (result != null) {
return result;
}
}
}
return null;
}
public Multisig clone() {
Multisig output = new Multisig(this.getAddress(), this.getSecuritySum());
output.setSecurity(this.getSecurity());
output.setIndex(this.getIndex());
output.setSigningIndex(this.getSigningIndex());
// Copy all bundles
ArrayList<Bundle> bundleCopy = new ArrayList<>();
for (Bundle b : this.getBundles()) {
bundleCopy.add(b.clone());
}
output.setBundles(bundleCopy);
// Copy all children
ArrayList<Multisig> childrenCopy = new ArrayList<>();
for (Multisig child : this.getChildren()) {
childrenCopy.add(child.clone());
}
output.setChildren(childrenCopy);
return output;
}
public void push(Multisig addr) {
children.add(addr);
}
public ArrayList<MultisigAddress> getChildren() {
public ArrayList<Multisig> getChildren() {
return children;
}
@ -52,6 +88,22 @@ public class MultisigAddress {
return index;
}
public void setAddress(String address) {
this.address = address;
}
public void setChildren(ArrayList<Multisig> children) {
this.children = children;
}
public ArrayList<Bundle> getBundles() {
return bundles;
}
public void setBundles(ArrayList<Bundle> bundles) {
this.bundles = bundles;
}
public int getSigningIndex() {
return signingIndex;
}
@ -84,14 +136,14 @@ public class MultisigAddress {
map.put("signingIndex", getSigningIndex());
map.put("security", security);
List<Object> childrenList = new ArrayList<Object>();
for (MultisigAddress ma: children) {
for (Multisig ma: children) {
childrenList.add(ma.toMap());
}
map.put("children", childrenList);
List<Object> bundleList = new ArrayList<Object>();
for (Bundle b: bundles) {
bundleList.add(b.getBundles());
bundleList.add(b.toArrayList());
}
map.put("bundles", bundleList);
@ -105,7 +157,7 @@ public class MultisigAddress {
@Override
public String toString() {
String out = "{ \n address':'" + address + "' \n, securitySum:" + securitySum + "\n, signingIndex: " + signingIndex + " \n";
for (MultisigAddress addr: children) {
for (Multisig addr: children) {
out += addr.toString();
}
return out;

View File

@ -8,56 +8,17 @@ import java.util.List;
*
* @author Adrian
**/
public class Signature {
public class Signature extends jota.model.Signature {
private int index;
private String bundle;
private String address;
private List<String> signatureFragments;
/**
* Initializes a new instance of the Signature class.
*/
public Signature() {
this.signatureFragments = new ArrayList<>();
super();
}
/**
* Get the address.
*
* @return The address.
*/
public String getAddress() {
return address;
}
/**
* Set the address.
*
* @param address The address.
*/
public void setAddress(String address) {
this.address = address;
}
/**
* Get the signatureFragments.
*
* @return The signatureFragments.
*/
public List<String> getSignatureFragments() {
return signatureFragments;
}
/**
* Set the signatureFragments.
*
* @param signatureFragments The signatureFragments.
*/
public void setSignatureFragments(List<String> signatureFragments) {
this.signatureFragments = signatureFragments;
}
public int getIndex() {
return index;
}
@ -79,10 +40,10 @@ public class Signature {
String out = "{ \n" +
" \tindex:" + index + ", " +
" \n\tbundle: " + bundle + ", " +
" \n\taddress:" + address + ",";
" \n\taddress:" + getAddress() + ",";
out += "\n\t[ \n";
for (String sf : signatureFragments) {
for (String sf : getSignatureFragments()) {
out += "\n\t" + sf + ",";
}
out += " ]";

View File

@ -1,128 +0,0 @@
package com.flashwifi.wifip2p.iotaFlashWrapper.Model;
import java.util.HashMap;
import java.util.Map;
public class Transaction {
private String hash;
private String signatureFragments;
private String address;
private long value;
private String obsoleteTag;
private long timestamp;
private long currentIndex;
private long lastIndex;
private String bundle;
private String trunkTransaction;
private String branchTransaction;
private String nonce;
private Boolean persistence;
private long attachmentTimestamp;
private String tag;
private long attachmentTimestampLowerBound;
private long attachmentTimestampUpperBound;
// Unsigned constructor
public Transaction(String address, int value, String obsoleteTag, String tag, Integer timestamp) {
this.address = address;
this.value = value;
this.obsoleteTag = obsoleteTag;
this.tag = tag;
this.timestamp = timestamp;
}
public Transaction(String signatureFragments, Long currentIndex, Long lastIndex, String nonce,
String hash, String obsoleteTag, Long timestamp, String trunkTransaction,
String branchTransaction, String address, Long value, String bundle, String tag,
Long attachmentTimestamp, Long attachmentTimestampLowerBound, Long attachmentTimestampUpperBound) {
this.hash = hash;
this.obsoleteTag = obsoleteTag;
this.signatureFragments = signatureFragments;
this.address = address;
this.value = value;
this.timestamp = timestamp;
this.currentIndex = currentIndex;
this.lastIndex = lastIndex;
this.bundle = bundle;
this.trunkTransaction = trunkTransaction;
this.branchTransaction = branchTransaction;
this.tag = tag;
this.attachmentTimestamp = attachmentTimestamp;
this.attachmentTimestampLowerBound = attachmentTimestampLowerBound;
this.attachmentTimestampUpperBound = attachmentTimestampUpperBound;
this.nonce = nonce;
}
public String getSignatureFragments() {
return signatureFragments;
}
public void setSignatureFragments(String signatureFragments) {
this.signatureFragments = signatureFragments;
}
public long getValue() {
return value;
}
public String getAddress() {
return address;
}
public Map<String, Object> toMap() {
Map<String, Object> map = new HashMap<String, Object>();
if (hash != null && !hash.equals("")) {
map.put("hash", hash);
}
map.put("signatureMessageFragment", signatureFragments);
map.put("address", address);
map.put("value", value);
map.put("obsoleteTag", obsoleteTag);
map.put("currentIndex", currentIndex);
map.put("timestamp", timestamp);
map.put("lastIndex", lastIndex);
map.put("bundle", bundle);
map.put("trunkTransaction", trunkTransaction);
map.put("branchTransaction", branchTransaction);
map.put("nonce", nonce);
map.put("attachmentTimestamp", String.valueOf(attachmentTimestamp));
map.put("tag", tag);
map.put("attachmentTimestampLowerBound", String.valueOf(attachmentTimestampLowerBound));
map.put("attachmentTimestampUpperBound", String.valueOf(attachmentTimestampUpperBound));
return map;
}
public Transaction clone() {
return new Transaction(
this.signatureFragments,
this.currentIndex,
this.lastIndex,
this.nonce,
this.hash,
this.obsoleteTag,
this.timestamp,
this.trunkTransaction,
this.branchTransaction,
this.address,
this.value,
this.bundle,
this.tag,
this.attachmentTimestamp,
this.attachmentTimestampLowerBound,
this.attachmentTimestampUpperBound
);
}
public String toString() {
Map<String, Object> mapObj = toMap();
String value = "{";
for (Map.Entry<String, Object> entry: mapObj.entrySet()) {
value += "'" + entry.getKey() + "':'" + entry.getValue().toString() + "', \n";
}
value += "}";
return value;
}
}

View File

@ -4,31 +4,24 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class UserObject {
private int userIndex = 1;
private int userIndex;
private String seed;
private int index = 0;
private int security = 2;
private int depth = 4;
private ArrayList<Bundle> bundles = new ArrayList<Bundle>();
private ArrayList<Digest> partialDigests = new ArrayList<Digest>();
private ArrayList<MultisigAddress> multisigDigests = new ArrayList<MultisigAddress>();
private int seedIndex;
private int security;
private FlashObject flash;
public UserObject(int userID, String seed, int depth, FlashObject flash) {
public UserObject(int userID, String seed, int seedIndex, int security) {
this.userIndex = userID;
this.seed = seed;
this.depth = depth;
this.flash = flash;
this.seedIndex = seedIndex;
this.security = security;
}
public void incrementIndex() {
index++;
}
public void add(Digest digest) {
partialDigests.add(digest);
public int incrementSeedIndex() {
this.seedIndex = this.seedIndex + 1;
return seedIndex;
}
@Override
@ -36,21 +29,9 @@ public class UserObject {
String out = "";
out += "userIndex: " + userIndex + "\n";
out += "seed: " + seed + "\n";
out += "index: " + index + "\n";
out += "seedIndex: " + seedIndex + "\n";
out += "security: " + getSecurity() + "\n";
out += "depth: " + depth + "\n";
out += "bundles: " + "\n";
for (Bundle b: bundles) {
out += "\t" + b.toString() + "\n";
}
out += "partialDigests: " + "\n";
for (Digest d: partialDigests) {
out += "\t" + d.toString() + "\n";
}
out += "multisigDigests: " + "\n";
for (MultisigAddress m: multisigDigests) {
out += "\t" + m.toString() + "\n";
}
out += "Flash: " + "\n";
out += flash.toString();
@ -61,27 +42,8 @@ public class UserObject {
Map<String, Object> objectMap = new HashMap<>();
objectMap.put("userIndex", getUserIndex());
objectMap.put("seed", getSeed());
objectMap.put("index", getIndex());
objectMap.put("seedIndex", getSeedIndex());
objectMap.put("security", getSecurity());
objectMap.put("depth", depth);
ArrayList<Object> bundleMaps = new ArrayList<>();
for (Bundle b: bundles) {
bundleMaps.add(b.toMap());
}
objectMap.put("bundles", bundleMaps);
ArrayList<Object> partialDigestMaps = new ArrayList<>();
for (Bundle b: bundles) {
partialDigestMaps.add(b.toMap());
}
objectMap.put("partialDigests", partialDigestMaps);
ArrayList<Object> multisigDigestsMaps = new ArrayList<>();
for (Bundle b: bundles) {
partialDigestMaps.add(b.toMap());
}
objectMap.put("multisigDigests", multisigDigestsMaps);
objectMap.put("flash", flash.toMap());
return objectMap;
}
@ -91,24 +53,12 @@ public class UserObject {
* Getters and Setters
*/
public void setMultisigDigests(ArrayList<MultisigAddress> multisigDigests) {
this.multisigDigests = multisigDigests;
}
public void setFlash(FlashObject flash) {
this.flash = flash;
}
public void setIndex(int index) {
this.index = index;
}
public void setBundles(ArrayList<Bundle> bundles) {
this.bundles = bundles;
}
public ArrayList<MultisigAddress> getMultisigDigests() {
return multisigDigests;
public void setSeedIndex(int index) {
this.seedIndex = index;
}
public int getSecurity() {
@ -119,22 +69,14 @@ public class UserObject {
return seed;
}
public int getIndex() {
return index;
public int getSeedIndex() {
return seedIndex;
}
public int getUserIndex() {
return userIndex;
}
public ArrayList<Bundle> getBundles() {
return bundles;
}
public ArrayList<Digest> getPartialDigests() {
return partialDigests;
}
public FlashObject getFlash() {
return flash;
}

View File

@ -5,7 +5,7 @@ import com.eclipsesource.v8.V8Array;
import com.eclipsesource.v8.V8Object;
import com.eclipsesource.v8.utils.V8ObjectUtils;
import com.flashwifi.wifip2p.iotaFlashWrapper.Model.*;
import jota.model.Transaction;
import java.util.ArrayList;
import java.util.HashMap;
@ -36,13 +36,14 @@ public class V8Converter {
return signatures;
}
public static V8Object multisigToV8Object(V8 engine, MultisigAddress multisig) {
public static V8Object multisigToV8Object(V8 engine, Multisig multisig) {
Map<String, Object> sigMapg = multisig.toMap();
return V8ObjectUtils.toV8Object(engine, sigMapg);
}
public static V8Object flashObjectToV8Object(V8 engine, FlashObject flash) {
return V8ObjectUtils.toV8Object(engine, flash.toMap());
Map <String, Object> flashMap = flash.toMap();
return V8ObjectUtils.toV8Object(engine, flashMap);
}
public static FlashObject flashObjectFromV8Object(V8Object input) {
@ -51,22 +52,33 @@ public class V8Converter {
Integer singersCount = (Integer) inputMap.get("signersCount");
Integer balance = (Integer) inputMap.get("balance");
ArrayList<String> settlementAddresses = (ArrayList<String>) inputMap.get("settlementAddresses");
MultisigAddress root = multisigAddressFromPropertyMap((Map<String, Object>) inputMap.get("root"));
MultisigAddress remainderAddress = multisigAddressFromPropertyMap((Map<String, Object>) inputMap.get("remainderAddress"));
ArrayList<Integer> deposits = (ArrayList<Integer>) inputMap.get("deposits");
Multisig root = multisigAddressFromPropertyMap((Map<String, Object>) inputMap.get("root"));
Multisig remainderAddress = multisigAddressFromPropertyMap((Map<String, Object>) inputMap.get("remainderAddress"));
ArrayList<Double> deposits = new ArrayList<>();
if (inputMap.get("deposits") instanceof ArrayList) {
Object depositEntry = inputMap.get("deposits");
if (((ArrayList<Object>) depositEntry).size() > 0 && ((ArrayList<Object>) depositEntry).get(0) instanceof Integer) {
for (int val: (ArrayList<Integer>) depositEntry) {
deposits.add(new Double(val));
}
} else {
deposits = (ArrayList<Double>) depositEntry;
}
}
ArrayList<Bundle> transfers = bundleListFromArrayList((ArrayList<Object>) inputMap.get("transfers"));
ArrayList<Bundle> outputs = bundleListFromArrayList((ArrayList<Object>) inputMap.get("outputs"));
return new FlashObject(singersCount, balance, settlementAddresses, deposits, outputs, transfers, root, remainderAddress);
Map<String, Integer> outputs = (Map<String, Integer>) inputMap.get("outputs");
Integer depth = (Integer) inputMap.get("depth");
Integer security = (Integer) inputMap.get("security");
return new FlashObject(singersCount, balance, settlementAddresses, deposits, outputs, transfers, root, remainderAddress, depth ,security);
}
public static V8Array bundleListToV8Array(V8 engine, ArrayList<Bundle> bundles) {
public static V8Array bundleListToV8Array(V8 engine, List<Bundle> bundles) {
List<Object> bundleTmp = new ArrayList<Object>();
for (Bundle b: bundles) {
List<Object> transactions = new ArrayList<Object>();
for (Transaction t: b.getBundles()) {
transactions.add(t.toMap());
for (jota.model.Transaction tx: b.getTransactions()) {
transactions.add(transactionToMap((Transaction) tx));
}
bundleTmp.add(transactions);
}
@ -85,32 +97,62 @@ public class V8Converter {
ArrayList<Bundle> ret = new ArrayList<>();
for (Object o: input) {
ret.add(bundleFromArrayList((ArrayList<Object>) o));
if (o instanceof Map) {
if (((Map) o).get("bundles") instanceof String) {
ArrayList<Object> bundles = (ArrayList<Object>) ((Map<String, Object>) o).get("bundles");
ret.add(bundleFromArrayList(bundles));
} else {
continue;
}
}
if (o instanceof ArrayList) {
ret.add(bundleFromArrayList((ArrayList<Object>) o));
}
}
return ret;
}
public static MultisigAddress multisigAddressFromV8Object(V8Object input) {
public static Multisig multisigAddressFromV8Object(V8Object input) {
if (input.isUndefined()) {
System.out.println("[ERROR]: could not parse object");
return null;
}
Map<String, ? super Object> multiSigMap = V8ObjectUtils.toMap(input);
return multisigAddressFromPropertyMap(multiSigMap);
}
public static MultisigAddress multisigAddressFromPropertyMap(Map<String, Object> propMap) {
public static Multisig multisigAddressFromPropertyMap(Map<String, Object> propMap) {
// Parse result into Java Obj.
String addr = (String) propMap.get("address");
int secSum = (Integer) propMap.get("securitySum");
ArrayList<MultisigAddress> children = new ArrayList<>();
ArrayList<Multisig> children = new ArrayList<>();
for (Object child: (ArrayList<Object>) propMap.get("children")) {
Map<String, ? super Object> childPropMap = (Map<String, ? super Object>) child;
children.add(multisigAddressFromPropertyMap(childPropMap));
}
MultisigAddress multisig = new MultisigAddress(addr, secSum, children);
Multisig multisig = new Multisig(addr, secSum, children);
if (propMap.get("bundles") instanceof ArrayList) {
ArrayList<Bundle> bundles = new ArrayList<>();
for (Object bundle: (ArrayList<Object>) propMap.get("bundles")) {
Bundle b = new Bundle();
if (!(bundle instanceof ArrayList)) {
continue;
} else {
for (Object transactionMap: (ArrayList<Object>) bundle) {
b.getTransactions().add(transactionFromObject(transactionMap));
}
}
bundles.add(b);
}
multisig.setBundles(bundles);
}
if (propMap.get("index") != null) {
multisig.setIndex((Integer) propMap.get("index"));
@ -119,6 +161,10 @@ public class V8Converter {
multisig.setSigningIndex((Integer) propMap.get("signingIndex"));
}
if (propMap.get("security") instanceof Integer) {
multisig.setSecurity((Integer) propMap.get("security"));
}
return multisig;
}
@ -127,6 +173,10 @@ public class V8Converter {
// Parse return as array of bundles
ArrayList<Bundle> returnBundles = new ArrayList<>();
for (Object bundleItem: inputList) {
if (!(bundleItem instanceof ArrayList)) {
System.out.println("[ERROR]: got undefined for bunle");
continue;
}
ArrayList<Object> bundleContent = (ArrayList<Object>) bundleItem;
ArrayList<Transaction> returnedTransactions = new ArrayList<>();
@ -199,7 +249,7 @@ public class V8Converter {
return null;
}
public static V8Array transferListToV8Array(V8 engine, ArrayList<Transfer> transfers) {
public static V8Array transferListToV8Array(V8 engine, List<Transfer> transfers) {
List<Object> transferObj = new ArrayList<Object>();
for (Transfer t: transfers) {
transferObj.add(t.toMap());
@ -209,12 +259,34 @@ public class V8Converter {
public static V8Array transactionListToV8Array(V8 engine, ArrayList<Transaction> transactions) {
List<Object> transfersObj = new ArrayList<Object>();
for (Transaction t: transactions) {
transfersObj.add(t.toMap());
for (Transaction tx: transactions) {
transfersObj.add(transactionToMap(tx));
}
return V8ObjectUtils.toV8Array(engine, transfersObj);
}
public static Map<String, Object> transactionToMap(jota.model.Transaction transaction) {
Map<String, Object> map = new HashMap<String, Object>();
if (transaction.getHash() != null && !transaction.getHash().equals("")) {
map.put("hash", transaction.getHash());
}
map.put("signatureMessageFragment", transaction.getSignatureFragments());
map.put("address", transaction.getAddress());
map.put("value", transaction.getValue());
map.put("obsoleteTag", transaction.getObsoleteTag());
map.put("currentIndex", transaction.getCurrentIndex());
map.put("timestamp", transaction.getTimestamp());
map.put("lastIndex", transaction.getLastIndex());
map.put("bundle", transaction.getBundle());
map.put("trunkTransaction", transaction.getTrunkTransaction());
map.put("branchTransaction", transaction.getBranchTransaction());
map.put("nonce", transaction.getNonce());
map.put("attachmentTimestamp", String.valueOf(transaction.getAttachmentTimestamp()));
map.put("tag", transaction.getTag());
map.put("attachmentTimestampLowerBound", String.valueOf(transaction.getAttachmentTimestampLowerBound()));
map.put("attachmentTimestampUpperBound", String.valueOf(transaction.getAttachmentTimestampUpperBound()));
return map;
}
public static Transaction transactionFromObject(Object input) {
Map<String, Object> bundleData = (Map<String, Object>) input;

View File

@ -301,11 +301,11 @@ public class Negotiator {
if (iotaPerMegabyte < 0) {
return error(R.string.err_sell_price_bad_setting, false);
}
int minMinutes = Integer.valueOf(prefs.getString("edit_text_min_minutes", "-1"));
int minMinutes = Integer.valueOf(prefs.getString("edit_text_sell_min_minutes", "-1"));
if (minMinutes < 0) {
return error(R.string.err_min_minutes_bad_setting, false);
}
int maxMinutes = Integer.valueOf(prefs.getString("edit_text_max_minutes", "-1"));
int maxMinutes = Integer.valueOf(prefs.getString("edit_text_sell_max_minutes", "-1"));
if (maxMinutes < 0) {
return error(R.string.err_max_minutes_bad_setting, false);
}

View File

@ -102,10 +102,14 @@
<TextView
android:id="@+id/stopText"
android:gravity="center"
android:layout_margin="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/channelClosed"
android:visibility="invisible"/>
android:visibility="gone"/>
</LinearLayout>

View File

@ -19,7 +19,7 @@
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.NoActionBar.PopupOverlay">
<Switch
<!--<Switch
android:layout_width="wrap_content"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="end"
@ -27,7 +27,7 @@
android:checked="false"
android:hint="@string/wifi_p2p_discovery"
android:width="120dp"
android:id="@+id/wifiSwitch"/>
android:id="@+id/wifiSwitch"/>-->
</android.support.v7.widget.Toolbar>

View File

@ -19,7 +19,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/startAP" />
android:textOn="@string/stopAP"
android:textOff="@string/startAPText" />
<ProgressBar
android:id="@+id/progressbarAP"

View File

@ -68,6 +68,9 @@
<string name="channelClosed">The payment channel was closed.</string>
<string name="initRetransfer">Initializing retransfer</string>
<string name="welcome">Welcome to the Wifi Iota Hotspot App</string>
<string name="notification_doing_nothing">Currently doing nothing</string>
<string name="stopAP">Stop Hotspot</string>
<string name="startAPText">Start Hotspot</string>
<!-- Welcome Slideshow -->

View File

@ -44,7 +44,7 @@
<SwitchPreference
android:defaultValue="false"
android:defaultValue="true"
android:key="pref_key_switch_testnet"
android:title="Testnet" />
@ -98,7 +98,7 @@
android:key="pref_key_payment_settings">
<EditTextPreference
android:defaultValue="10"
android:defaultValue="15"
android:key="edit_text_buy_price"
android:inputType="number"
android:selectAllOnFocus="true"