Skip to content

Commit

Permalink
updates
Browse files Browse the repository at this point in the history
  • Loading branch information
zack-bitcoin committed Dec 16, 2014
1 parent 83bcefc commit f341b24
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 62 deletions.
2 changes: 1 addition & 1 deletion README
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ https://blog.ethereum.org/2014/11/25/proof-stake-learned-love-weak-subjectivity/
1) weak subjectivity (not yet implemented)

https://blog.ethereum.org/2014/07/05/stake/
1) the low influence random number generator
1) the low influence random number generator, with a modification. Signers first reveal Hash(bit+salt) and later reveal bit+salt when they collect their reward.

I use something similar to Daniel Larimer's transactions as proof of stake. Every transaction must reference the hash of one of the 10 most recent blocks. That way forks that start more than 10 blocks ago wont have any tx fees to reward the block creator.

Expand Down
53 changes: 29 additions & 24 deletions api.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,22 @@
"""This is the internal API. These are the words that are used to interact with a local node that you have the password to.
"""
import copy, tools, blockchain, custom, random, transactions, sys, time, networking
def sign_tx(tx, privkey=0):
tx=copy.deepcopy(tx)
if privkey==0:
privkey=tools.local_get('privkey')
tx['signatures']=[tools.sign(tools.det_hash(tx), privkey)]
def sign(tx, privkey):
pubkey=tools.privtopub(privkey)
address=tools.make_address([pubkey], 1)
if 'pubkeys' not in tx:
tx['pubkeys']=[pubkey]
if 'signatures' not in tx:
tx['signatures']=[tools.sign(tools.det_hash(tx), privkey)]
return tx
def easy_add_transaction(tx_orig, DB={}, privkey='default'):
tx = copy.deepcopy(tx_orig)
if privkey in ['default', 'Default']:
privkey=tools.local_get('privkey')
pubkey=tools.privtopub(privkey)
address=tools.make_address([pubkey], 1)
length=tools.local_get('length')
if 'recentHash' not in tx and length>3:
tx['recentHash']=tools.db_get(length-2)['block_hash']
if 'count' not in tx:
try:
tx['count'] = tools.count(address, {})
except:
tx['count'] = 1
if 'pubkeys' not in tx:
tx['pubkeys']=[pubkey]
if 'signatures' not in tx:
tx=sign_tx(tx, privkey)
if privkey in ['default', 'Default']:
privkey=tools.local_get('privkey')
tx=sign(tx_orig, privkey)
custom.DB['suggested_txs'].put(tx)
return('success')#blockchain.add_tx(tx, DB))#this is a mistake. It should append to the queue instead.
def help_(DB, args):
Expand All @@ -34,9 +26,10 @@ def help_(DB, args):
'start':'type \'./cli.py start\' to start a full node',
'new_address':'type \'./cli.py new_address <brain>\' to make a new privkey, pubkey, and address using the brain wallet=<brain>. If you want to use this address, you need to copy/paste the pubkey into the file custom.py',
'DB_print':'prints the database that is shared between threads',
'patty_info':'This is like "info", but it accesses the database that is mirrored accross all the nodes',
'info':'prints the contents of an entree in the hashtable. If you want to know what the first block was: info 0, if you want to know about a particular address <addr>: info <addr>, if you want to know about yourself: info my_address',
'my_address':'tells you your own address',
'spend':'spends money, in satoshis, to an address <addr>. Example: spend 1000 11j9csj9802hc982c2h09ds',
'spend':'spends money, in satoshis, to an address <addr>. Example: spend 1000 11j9csj9802hc982c2h09ds 50',
'blockcount':'returns the number of blocks since the genesis block',
'txs':'returns a list of the zeroth confirmation transactions that are expected to be included in the next block',
'my_balance':'the amount of money that you own',
Expand All @@ -58,20 +51,31 @@ def peers(DB, args):
return(tools.local_get('peers'))
def DB_print(DB, args):
return(DB)
def info(DB, args):
def patty_info(DB, args):
if len(args)<1:
return ('not enough inputs')
if args[0]=='my_address':
address=tools.local_get('address')
else:
address=args[0]
return(tools.db_get(address, DB))
return(tools.db_get(address, DB))
def info(DB, args):
if len(args)<1:
return ('not enough inputs')
address=args[0]
try:
return(tools.local_get(address))
except Exception as exc:
tools.log(exc)
return(address+' is not in the local database. maybe you meant to do the command: "patty_info '+address+'"?')
def my_address(DB, args):
return(tools.local_get('address'))
def spend(DB, args):
if len(args)<2:
return('not enough inputs')
return easy_add_transaction({'type': 'spend', 'amount': int(args[0]), 'to':args[1]}, DB)
if len(args)<3:
args[2]=custom.default_spend_fee#default fee
return easy_add_transaction({'type': 'spend', 'amount': int(args[0]), 'to':args[1], 'fee':args[2]}, DB)
def accumulate_words(l, out=''):
if len(l)>0: return accumulate_words(l[1:], out+' '+l[0])
return out
Expand Down Expand Up @@ -105,13 +109,14 @@ def buy_block(DB, args):
to_hash=''
if length>-1: to_hash={'prev':prev_block['block_hash'], 'txs':block['txs']}
block['block_hash']=tools.det_hash(to_hash)
block=sign_tx(block)
block['patty_root']=tools.db_root()
block=sign(block, tools.local_get('privkey'))
block = tools.unpackage(tools.package(block))
DB['suggested_blocks'].put(block)
return block
def pass_(DB, args): return ' '
def error_(DB, args): return error
Do={'spend':spend, 'help':help_, 'blockcount':blockcount, 'txs':txs, 'balance':balance, 'my_balance':my_balance, 'b':my_balance, 'info':info, '':pass_, 'DB':DB_print, 'my_address':my_address, 'log':log, 'stop':stop_, 'commands':commands, 'pushtx':pushtx, 'peers':peers, 'buy_block':buy_block}
Do={'spend':spend, 'help':help_, 'blockcount':blockcount, 'txs':txs, 'balance':balance, 'my_balance':my_balance, 'b':my_balance, 'info':info, 'patty_info':patty_info, '':pass_, 'DB':DB_print, 'my_address':my_address, 'log':log, 'stop':stop_, 'commands':commands, 'pushtx':pushtx, 'peers':peers, 'buy_block':buy_block}
def main(DB, heart_queue):
def responder(dic):
command=dic['command']
Expand Down
13 changes: 9 additions & 4 deletions auto_signer.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@ def create_sign_tx():
jackpots.append(j)
if len(jackpots)>0:
#proot=get_proof(on_block)
proof=tools.db_proof(address)
a=tools.local_get('balance_proofs')
proof=a[max(on_block-custom.long_time, 0)]
tx={'on_block':on_block, 'proof':proof, 'jackpots':jackpots, 'type':'sign', 'amount':M/3000/3}
#proof=tools.db_proof(address)
tx={'on_block':on_block, 'jackpots':jackpots, 'type':'sign', 'amount':M/3000/3}
if on_block>0:
b=max(on_block-custom.long_time, -1)
proof=tools.local_get('balance_proofs'+str(b))
if proof=='empty':
time.sleep(1)
return {'error':'not ready'}
tx['proof']=proof
secret=str(random.random())+str(random.random())
secrets=tools.local_get('secrets')
secrets[str(on_block)]=secret
Expand Down
22 changes: 19 additions & 3 deletions blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,17 @@ def tx_check(txs):
if int(block['length']) != int(length) + 1:
log_('wrong longth')
return False
block_creator_address=tools.addr(block)
for tx in block['txs']:
a=tools.addr(tx)
if a==block_creator_address:
if tx['type']=='spend':
log_('the block creator cannot have tx fees in his own block:'+str(tx))
return False
block_creator=tools.db_get(block_creator_address)
if block_creator['amount']<tools.block_fee(block['length'])+tools.cost_0(block['txs'], block_creator_address):
log_('you cannot afford to create a block')
return False
txs=filter(lambda x: x['type']=='sign', block['txs'])
txs=map(lambda x: len(x['jackpots']), txs)
if sum(txs)<custom.signers*2/3:
Expand Down Expand Up @@ -162,6 +173,7 @@ def tx_check(txs):
tools.log('add_block: ' + str(block))
tools.db_put(block['length'], block, DB)
tools.local_put('length', block['length'])
#take money from the creator
orphans = tools.local_get('txs')
tools.local_put('txs', [])
for tx in block['txs']:
Expand All @@ -172,9 +184,8 @@ def tx_check(txs):
if peer!=False and peers[peer]['blacklist']>0:
peers[peer]['blacklist']-=1
tools.local_put('peers', peers)
proofs=tools.local_get('balance_proofs')
proofs.append(tools.db_proof(tools.local_get('address')))
tools.local_put('balance_proofs', proofs)
tools.log('balance_proofs'+str(block['length'])+';'+tools.db_proof(tools.local_get('address')))
tools.local_put('balance_proofs'+str(block['length']),tools.db_proof(tools.local_get('address')))
elif not peer==False:
peers=tools.local_get('peers')
if peer not in peers:
Expand Down Expand Up @@ -204,6 +215,11 @@ def delete_block(DB):
orphans.append(tx)
tools.local_put('add_block', False)
transactions.update[tx['type']](tx, DB, False)
block_creator_address=tools.addr(tools.db_get(length))
block_creator=tools.db_get(block_creator_address)
block_creator['amount']+=tools.block_fee(length)
tools.db_put(block_creator_address, block_creator)
#return money to the creator
tools.db_delete(length, DB)
length-=1
tools.local_put('length', length)
Expand Down
4 changes: 2 additions & 2 deletions custom.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""This is to make magic numbers easier to deal with."""
import multiprocessing, os
peers={'192.241.212.114:7900':{'port':7900, 'blacklist':0, 'diffLength':"0", 'length':0, 'lag':40.0}}
max_block_size=10#kilobytes
current_loc=os.path.dirname(os.path.abspath(__file__))
database_name = os.path.join(current_loc, 'DB')
log_file=os.path.join(current_loc, 'log')
Expand All @@ -12,8 +13,8 @@
creator='115nxUddLmxijWskiz5znHxk1KdMZpS'
max_key_length=6**4
block_reward = 10 ** 5
fee = 10 ** 3
signers=64
default_spend_fee=1000
# Lower limits on what the "time" tag in a block can say.
#get rid of decimal.
#for vitalik's slasher, 3000, 1000, 100
Expand All @@ -22,7 +23,6 @@
short_time=2
maximum_deposit=all_money/signers/long_time/2
minimum_deposit=maximum_deposit/100
deposit_fee = 10 ** 3
jackpot_nonces=200
mmm = 100
download_many = 50 # Max number of blocks to request from a peer at the same time.
Expand Down
9 changes: 8 additions & 1 deletion db.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@ def main(heart_queue, database_name, logf, database_port):
import networking
import sys
import patricia as patty
def local_get(args): return json.loads(DB.Get(args[0]))
def local_get(args):
try:
a=json.loads(DB.Get(args[0]))
return a
except Exception as exc:
logf(exc)
logf('local get: '+str(args))
return 'empty'
def local_put(args): return DB.Put(args[0], json.dumps(args[1]))
def get(args):
try:
Expand Down
2 changes: 1 addition & 1 deletion patricia/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
def get(key): return unpackage(rlp.decode(state.get(key)))
def put(key, val): return state.update(key, rlp.encode(package(val)))
def delete(key): return state.delete(key)
def root(key): return state.root_hash.encode('hex')
def root(): return state.root_hash.encode('hex')
def prove(key):
p=state.produce_spv_proof(key)
p=rlp.encode(p).encode('base64')
Expand Down
7 changes: 3 additions & 4 deletions threads.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def main(brainwallet, pubkey_flag=False):
tools.log('starting '+cmd.name)
time.sleep(4)
b=tools.db_existence(0)
def empty_memoized(): return({'blockcount':-3000})
#def empty_memoized(): return({'blockcount':-3000})
if not b:
tools.local_put('length', -1)
tools.local_put('memoized_votes', {})
Expand All @@ -56,8 +56,7 @@ def empty_memoized(): return({'blockcount':-3000})
tools.local_put('targets', {})
tools.local_put('times', {})
tools.local_put('mine', False)
tools.local_put('balance_proofs', empty_memoized())
tools.local_put('my_sign_txs', empty_memoized())
tools.local_put('my_sign_txs', {})#empty_memoized())
tools.local_put('secrets', {})
money=db.default_entry()
money['amount']+=custom.all_money
Expand All @@ -76,7 +75,7 @@ def empty_memoized(): return({'blockcount':-3000})
Address=tools.make_address([pubkey], 1)
tools.local_put('address', Address)
a=tools.db_proof(Address)
tools.local_put('balance_proofs', [a])
tools.local_put('balance_proofs-1', a)
tools.log('stop: ' +str(tools.local_get('stop')))
while not tools.local_get('stop'):
time.sleep(0.5)
Expand Down
16 changes: 16 additions & 0 deletions todo
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
combine the good parts from LIF and old random number generator.

Maybe the blockmaker should be rewarded for each signer he includes. This would disincentivize him from trying to cheat by including less signers.
so say minsigners = 10, maxsigners = 15

say there are 10 signers
reward is 0

11 signers
reward is 20%

12 signers
reward is 40%



write the transaction types for slasher.

Explain all the attack scenarios that you imagined while writing the code, post it on #bitcoin-wizards
Expand Down
24 changes: 10 additions & 14 deletions tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,16 @@ def hash2int(a): return int(str(a), 16)
def cost_0(txs, address):
#cost of the zeroth confirmation transactions
total_cost = []
votecoin_cost = {}
#address=tools.db_get('address')
for Tx in filter(lambda t: address == addr(t), txs):
def spend_(total_cost=total_cost):
total_cost.append(custom.fee)
total_cost += [Tx['amount']]
def buy_shares_(total_cost=total_cost):
cost = cost_to_buy_shares(Tx)
total_cost.append(custom.buy_shares_fee)
total_cost.append(cost)
total_cost.append(int(abs(cost*0.01)))
Do={'spend':spend_,
'mint':(lambda: total_cost.append(-custom.block_reward))}
Do[Tx['type']]()
txs=filter(lambda t: address == addr(t), txs)
txs=filter(lambda t: t['type']=='spend', txs)
for t in txs:
total_cost.append(t['fee'])
total_cost.appnd(t['amount'])
return sum(total_cost)
def block_fee(length): return 10**9#total blocks is all_money divided by this. 21000000 blocks in this case
#assume it takes 0.5 seconds to process each block. If someone with 1% money does DDOS, total_blocks/200 seconds is how long they can. I am aiming for 1% of money to be able to DDOS for 1 day.
#since each block can be 10 kb, total block length is total_blocks*10kB. I am aiming for 210 GB.
#once we apply mini-blockchain proposal, then this number will shrink slowly. The total coins will decrease by a half-life ever 21 million blocks.
def fee_check(tx, txs, DB):
address = addr(tx)
cost=cost_0(txs+[tx], address)
Expand Down Expand Up @@ -202,6 +197,7 @@ def s_to_db(c):
if (type(response)==dict and 'error' in response):
time.sleep(0.001)
log('s to db failed at '+str(c))
log('s to db failed at '+str(response))
#return s_to_db(c)
else:
return response
Expand Down
17 changes: 9 additions & 8 deletions transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,11 @@ def sign_verify(tx, txs, out, DB):
return False
return True
def det_random(length):#this is very slow. we should memoize entropy somewhere.
#returns random seed to elect signers.
def mean(l): return sorted(l)[len(l)/2]
ran=[]
m=custom.long_time-custom.medium_time
for i in range(custom.medium_time/2):
a=length-m-i
a=length-custom.long_time-i
if a<0:
ran.append(a)
else:
Expand Down Expand Up @@ -170,17 +170,18 @@ def spend(tx, DB, add_block):
address = tools.addr(tx)
adjust_int(['amount'], address, -tx['amount'], DB, add_block)
adjust_int(['amount'], tx['to'], tx['amount'], DB, add_block)
adjust_int(['amount'], address, -custom.fee, DB, add_block)
def sign(tx, DB, add_block):
#adjust_int(['amount'], address, -custom.fee, DB, add_block)
adjust_int(['amount'], address, -tx['fee'], DB, add_block)
def sign(tx, DB, add_block):#should include hash(entroy_bit and salt)
address = tools.addr(tx)
adjust_int(['amount'], address, -tx['amount'], DB, add_block)
adjust_int(['amount'], address, -custom.deposit_fee, DB, add_block)
#record somewhere. maybe on the block in the future?
def slasher(tx, DB, add_block):
address = tools.addr(tx)
#destroy the deposit. give a portion of it as a reward to the person who caught the criminal.
adjust_int(['amount'], address, tx['amount']/5, DB, add_block)
adjust_int(['amount'], tools.addr(tx['tx1']), -tx['amount'], DB, add_block)
#tx={'amount':10000, 'tx1': , 'tx2': , 'reward_address': }
#record
def reward(tx, DB, add_block):
def reward(tx, DB, add_block):#should also reveal entropy_bit and salt
address = tools.addr(tx)
#if they successfully signed, then reward them. otherwise punish them by taking 2 times the reward from their deposit, and returning the rest to them.
#record
Expand Down

0 comments on commit f341b24

Please sign in to comment.