Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Finish block chain #50

Open
wants to merge 31 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
b925945
fix versions
alesiong Apr 29, 2018
e928144
add from dpass-chain
alesiong Apr 29, 2018
0d7058f
add dpass chain utils
alesiong Apr 29, 2018
3e99e3b
add chain storage
alesiong Apr 30, 2018
9e20fed
fix bug leads to negative balance
alesiong Apr 30, 2018
e166a1b
fix strange bugs by unqlite
alesiong Apr 30, 2018
cfe150a
damn it unqlite-python
alesiong Apr 30, 2018
7c1b6f8
add light server
alesiong May 1, 2018
9e21172
bug fixes on windows & sync
alesiong May 1, 2018
77e48e0
finishes lightserver
alesiong May 1, 2018
8e62271
modified search
zymop18 May 1, 2018
3c4622d
minor fix light server
alesiong May 2, 2018
5289ee0
minor fix
alesiong May 2, 2018
fc6e77d
Beatify the Search Box
SlaughteredLamb May 2, 2018
9a65556
fix blocking problem
alesiong May 2, 2018
62b3962
Merge remote-tracking branch 'yang/master' into develop
alesiong May 2, 2018
24a32e9
refine search bar (focus and hidden)
alesiong May 2, 2018
e2ef763
Merge remote-tracking branch 'origin/master' into develop
alesiong May 2, 2018
833e9af
change chain storage implementation
alesiong May 3, 2018
df1cb79
fix coroutine again
alesiong May 3, 2018
a7af77d
add serial to light server
alesiong May 3, 2018
3982cb6
fix
alesiong May 3, 2018
7c7a971
add account to light server
alesiong May 3, 2018
c5539f7
fix transaction signature verify
alesiong May 3, 2018
4b5ccc7
fix transaction sign & modify setting ui
alesiong May 3, 2018
3cc3be7
minor fix
alesiong May 3, 2018
a804017
add account to settings
alesiong May 3, 2018
6b9cb4a
modify search x button
alesiong May 3, 2018
f577d00
add password strength
alesiong May 3, 2018
e3e472f
Settings
SlaughteredLamb May 5, 2018
3d65f01
Merge remote-tracking branch 'yang/master' into develop
alesiong May 5, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -109,4 +109,5 @@ ethereum_private/data/
/db/
/node_modules/

*.sqlite
*.sqlite
/chain-data/
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ Put unit tests under `tests/` folder.
### Python
```
pip install -r requirements.dev.txt

```

### Javascript
12 changes: 11 additions & 1 deletion app/__init__.py
Original file line number Diff line number Diff line change
@@ -6,19 +6,22 @@
from flask_sqlalchemy import SQLAlchemy
from web3 import Web3, IPCProvider

from app.utils.chain_utils import ChainUtils
from app.utils.ethereum_utils import EthereumUtils
from app.utils.local_storage import LocalStorage
from app.utils.misc import get_env, get_ipc
from app.utils.session_key import SessionKey
from app.utils.settings import Settings
from chain.control.controller import Controller
from chain.utils.multiplexer import Multiplexer
from config import configs

# Instantiate Flask extensions
db = SQLAlchemy()
socketio = SocketIO()


def create_app(config_name='development', queue=None, use_storage=None):
def create_app(config_name='development', queue=None, use_storage=None, rq=None, wq=None):
"""
Create a Flask applicaction.
"""
@@ -70,6 +73,8 @@ def dated_url_for(endpoint, **values):
return url_for(endpoint, **values)

app.config['QUEUE'] = queue
app.config['READ_QUEUE'] = rq
app.config['WRITE_QUEUE'] = wq
if use_storage == 'ethereum':
app.config['USE_ETHEREUM'] = True

@@ -83,6 +88,11 @@ def startup():
storage_factory_abi = json.load(open('./ethereum_private/contracts/storage_factory.abi.json'))
storage_abi = json.load(open('./ethereum_private/contracts/storage.abi.json'))
ethereum_utils.init_contracts(get_env()['ETH_STORAGE'], storage_factory_abi, storage_abi)
else:
mx = Multiplexer(app.config['READ_QUEUE'], app.config['WRITE_QUEUE'])
mx.start()
controller = Controller(mx)
ChainUtils(controller)

Settings(app.config['SETTINGS_FILE'])

86 changes: 69 additions & 17 deletions app/api/master_password.py
Original file line number Diff line number Diff line change
@@ -2,15 +2,21 @@
import time
from threading import Thread

import gevent
from coincurve import PrivateKey
from flask import Blueprint, request, current_app, jsonify, abort

from app import socketio
from app.utils import error_respond
from app.utils.chain_storage import ChainStorage
from app.utils.chain_utils import ChainUtils
from app.utils.cipher import salted_hash
from app.utils.decorators import session_verify
from app.utils.ethereum_storage import EthereumStorage
from app.utils.ethereum_utils import initialize_ethereum_account
from app.utils.local_storage import LocalStorage
from app.utils.master_password import MasterPassword
from app.utils.misc import base64_decode
from app.utils.settings import Settings

bp = Blueprint('api.master_password', __name__, url_prefix='/api/master_password')
@@ -44,18 +50,44 @@ def initializing_worker(app):
settings.ethereum_address = ethereum_account
settings.write()
else:
current_app.config['STORAGE'] = LocalStorage('chain')
master_password: MasterPassword = current_app.config['MASTER_PASSWORD']
master_password.check_expire()
account = ChainUtils.new_account(master_password)
current_app.config['STORAGE'] = ChainStorage(account)

dummy_stop = False

def dummy():
while not dummy_stop:
time.sleep(0.01)
gevent.sleep()

# dummy = gevent.spawn(dummy)
# dummy.start()

storage = current_app.config['STORAGE']
storage.add(MASTER_KEY, settings.master_password_hash)
storage.add(MASTER_SALT_KEY, settings.master_password_hash_salt)

if not current_app.config['USE_ETHEREUM']:
ChainUtils().start_mining(account.public_key)
while True:
if storage.get(MASTER_KEY, True)[1] and storage.get(MASTER_SALT_KEY, True)[1]:
break
time.sleep(0.1)
if current_app.config['USE_ETHEREUM']:
time.sleep(0.1)
else:
gevent.sleep(0.1)
current_app.config['INIT_STATE'] = 2
socketio.emit('state change', 2)

Thread(target=initializing_worker, daemon=True, args=(current_app._get_current_object(),)).start()
# if not current_app.config['USE_ETHEREUM']:
# dummy_stop = True
# dummy.join()

if current_app.config['USE_ETHEREUM']:
Thread(target=initializing_worker, daemon=True, args=(current_app._get_current_object(),)).start()
else:
gevent.spawn(initializing_worker, current_app._get_current_object()).start()
return jsonify(message='Success')


@@ -76,33 +108,50 @@ def verify():
settings = Settings()
current_app.config['STORAGE'] = EthereumStorage(settings.ethereum_address, ethereum_pass)
else:
current_app.config['STORAGE'] = LocalStorage('chain')
master_pass.check_expire()
vk_hex = master_pass.decrypt(base64_decode(Settings().chain_private_key), 'private').decode()
account = PrivateKey.from_hex(vk_hex)
current_app.config['STORAGE'] = ChainStorage(account)
return jsonify(message='Success')
error_respond.master_password_wrong()


@bp.route('/verify_with_account/', methods=['POST'])
@session_verify
def verify_with_account():
if not current_app.config['USE_ETHEREUM']:
abort(404)
data = json.loads(request.decrypted_data.decode())
master_password_in_memory = data['password']
account = data['account']
del request.decrypted_data
del data

ethereum_pass = MasterPassword.generate_ethereum_password(master_password_in_memory)

storage = None
try:
storage = EthereumStorage(account, ethereum_pass)
except TypeError:
error_respond.blockchain_account_wrong()
if current_app.config['USE_ETHEREUM']:
ethereum_pass = MasterPassword.generate_ethereum_password(master_password_in_memory)

storage = None
try:
storage = EthereumStorage(account, ethereum_pass)
except TypeError:
error_respond.blockchain_account_wrong()

else:
storage = None
password_hash, salt = salted_hash(master_password_in_memory)
key = MasterPassword.generate_encryption_key(master_password_in_memory)
master_pass = MasterPassword(password_hash, salt, key, None)
master_pass.check_expire()
try:
vk_hex = master_pass.decrypt(base64_decode(account[2:]), 'private').decode()
vk = PrivateKey.from_hex(vk_hex)
storage = ChainStorage(vk)
except ValueError:
error_respond.blockchain_account_wrong()

while not storage.loaded:
time.sleep(0.1)

if current_app.config['USE_ETHEREUM']:
time.sleep(0.1)
else:
gevent.sleep(0.1)
master_pass_hash = storage.get(MASTER_KEY)
master_salt = storage.get(MASTER_SALT_KEY)
if master_pass_hash and master_salt:
@@ -114,7 +163,10 @@ def verify_with_account():
if master_pass:
current_app.config['MASTER_PASSWORD'] = master_pass
current_app.config['STORAGE'] = storage
settings.ethereum_address = account
if current_app.config['USE_ETHEREUM']:
settings.ethereum_address = account
else:
settings.chain_private_key = account[2:]
settings.write()
current_app.config['INIT_STATE'] = 2
socketio.emit('state change', 2)
30 changes: 26 additions & 4 deletions app/api/settings.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
from flask import Blueprint, current_app, jsonify, request, json
from io import BytesIO

import pyqrcode
from flask import Blueprint, current_app, jsonify, request, json, send_file

from app import ChainUtils, Settings
from app.utils.ethereum_utils import EthereumUtils
from app.utils import error_respond
from app.utils.decorators import session_verify
@@ -13,18 +17,26 @@ def get_settings():
if type_ == 'init_state':
return jsonify(state=current_app.config['INIT_STATE'])
elif type_ == 'mining':
ethereum_utils = EthereumUtils()
if current_app.config['USE_ETHEREUM']:
ethereum_utils = EthereumUtils()
else:
ethereum_utils = ChainUtils()
return jsonify(mining=ethereum_utils.is_mining)
elif type_ == 'balance':
return jsonify(balance=current_app.config['STORAGE'].balance())
elif type_ == 'account':
return jsonify(account=Settings().chain_private_key)
else:
error_respond.invalid_arguments()


@bp.route('/', methods=['POST'])
@session_verify
def change_settings():
ethereum_utils = EthereumUtils()
if current_app.config['USE_ETHEREUM']:
ethereum_utils = EthereumUtils()
else:
ethereum_utils = ChainUtils()
data = json.loads(request.decrypted_data.decode())
setting_type = data.get('type')
setting_args = data.get('args')
@@ -39,4 +51,14 @@ def change_settings():
ethereum_utils.stop_mining()
elif setting_type == 'lock':
current_app.config['MASTER_PASSWORD'].lock()
return jsonify(message='Success')
return jsonify(message='Success')


@bp.route('/private_key.png')
def private_key_png():
io = BytesIO()
key_base64 = Settings().chain_private_key
pyqrcode.create(key_base64).png(io, scale=4)
return send_file(BytesIO(io.getvalue()),
attachment_filename='private_key.png',
mimetype='image/png')
60 changes: 54 additions & 6 deletions app/frontend/src/components/AppHeader.vue
Original file line number Diff line number Diff line change
@@ -10,22 +10,33 @@
<a class="mdui-typo-title mdui-text-color-theme-grey-50">DPass</a>

<div class="mdui-toolbar-spacer"></div>

<div class="mdui-textfield search-bar"
v-if="!guard">
<i class="mdui-icon material-icons">search</i>
<i class="mdui-icon material-icons search-icon"
v-on:click="onClickSearchButton">search</i>
<input class="mdui-textfield-input search-text" type="text"
id="search-bar"
placeholder="Search"
v-on:input="onSearchChanged"/>
v-model="search"
v-on:input="onSearchChanged"
v-on:focus="onSearchFocus"
v-on:focusout="onSearchFocusout"/>

</div>

<button class="mdui-btn search-clear-btn"
v-if="!guard"
v-bind:style="search.length || searchFocused > 0 ? '' : 'visibility: hidden'"
v-on:click="onSearchCleared">
<i class="mdui-icon material-icons">close</i>
</button>

<span class="mdui-btn mdui-btn-icon mdui-ripple"
mdui-tooltip="{content: 'Lock DPass'}"
v-if="!guard"
@click="lockDPass">
<i class="mdui-icon material-icons">lock</i>
</span>

</div>
</header>
</template>
@@ -37,10 +48,29 @@
export default {
name: 'app-header',
props: ['guard'],
data() {
return {
search: '',
searchFocused: false
};
},
methods: {
onClickSearchButton() {
document.getElementById('search-bar').focus();
},
onSearchFocus() {
this.searchFocused = true;
},
onSearchFocusout() {
this.searchFocused = false;
},
onSearchChanged(event) {
this.$emit('search', event.target.value);
},
onSearchCleared: function() {
this.$emit('search', '');
this.search = '';
},
lockDPass() {
$$('.mdui-tooltip-open').remove();
ensureSession(this).then(() => {
@@ -71,11 +101,29 @@
<style scoped>
.search-text {
color: white;
padding-left: 42px;
background: rgba(255, 255, 255, 0.2);

}

.search-icon {
padding-left: 66px;
}

.search-clear-btn {
min-width: 36px;
width: 36px;
color: white;
border: none;
padding: 0;
top: 4px;
right: 50px;
background: none;

}

.search-bar {
margin-right: 24px;
width: calc(100% - 400px);
margin-right: 6px;
width: calc(100% - 350px);
}
</style>
12 changes: 6 additions & 6 deletions app/frontend/src/components/AppMenu.vue
Original file line number Diff line number Diff line change
@@ -20,12 +20,12 @@

<li class="mdui-divider"></li>

<li class="mdui-list-item mdui-ripple">
<i class="mdui-icon material-icons mdui-m-r-2">
settings_backup_restore
</i>
Sync & Backup
</li>
<!--<li class="mdui-list-item mdui-ripple">-->
<!--<i class="mdui-icon material-icons mdui-m-r-2">-->
<!--settings_backup_restore-->
<!--</i>-->
<!--Sync & Backup-->
<!--</li>-->
<router-link class="mdui-list-item mdui-ripple"
to="/settings/"
exact-active-class="mdui-list-item-active">
2 changes: 1 addition & 1 deletion app/frontend/src/components/NewPasswordView.vue
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@
</div>
<div id="sign-in">
<div class="mdui-textfield mdui-m-t-2">
<label class="mdui-textfield-label">Ethereum Account</label>
<label class="mdui-textfield-label">Account</label>
<input class="mdui-textfield-input"
v-model="account"/>
</div>
Loading