Skip to content
This repository has been archived by the owner on Nov 15, 2021. It is now read-only.

Commit

Permalink
added ability to deploy smart contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
localhuman committed Sep 10, 2017
1 parent 7c858e8 commit 93f127f
Show file tree
Hide file tree
Showing 13 changed files with 385 additions and 80 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -9,6 +9,7 @@ UnitTestChain
# C extensions
*.so

Contracts

# Distribution / packaging
.Python
Expand Down
14 changes: 11 additions & 3 deletions neo/Core/FunctionCode.py
Expand Up @@ -18,11 +18,19 @@ class FunctionCode(SerializableMixin):
_scriptHash = None


def __init__(self, script=None, param_list=[], return_type=None):
NeedsStorage = False

def __init__(self, script=None, param_list=None, return_type=None, needs_storage=False):
self.Script = script
self.ParameterList = param_list
if param_list is None:
self.ParameterList = []
else:
self.ParameterList = param_list

self.ReturnType = return_type

self.NeedsStorage = needs_storage

def ScriptHash(self):
if self._scriptHash is None:
self._scriptHash = Crypto.ToScriptHash(self.Script, unhex=False)
Expand All @@ -49,5 +57,5 @@ def ToJson(self):
'hash': self.ScriptHash().ToString(),
'script': self.Script.hex(),
'parameters': self.ParameterList.hex(),
'returntype': self.ReturnType if type(self.ReturnType) is int else self.ReturnType.decode('utf-8')
'returntype': self.ReturnType if type(self.ReturnType) is int else self.ReturnType.hex()
}
6 changes: 3 additions & 3 deletions neo/Core/TX/InvocationTransaction.py
Expand Up @@ -7,16 +7,16 @@
class InvocationTransaction(Transaction):


Script = bytearray(0)
Gas = Fixed8(0)
Script = None
Gas = None

def SystemFee(self):
return self.Gas



def __init__(self, *args, **kwargs):
super(InvocationTransaction, self).__init__(*args, **kwargs)
self.Gas = Fixed8(0)
self.Type = TransactionType.InvocationTransaction

def Size(self):
Expand Down
8 changes: 2 additions & 6 deletions neo/Core/TX/Transaction.py
Expand Up @@ -25,7 +25,7 @@
import sys
from itertools import groupby
from neo.Core.AssetType import AssetType

import pdb

class TransactionResult():
AssetId=None
Expand Down Expand Up @@ -214,11 +214,7 @@ def Height(self):
return self.__height

def SystemFee(self):
if self.__system_fee is None:
self.__system_fee = Fixed8(0)


return self.__system_fee
return Fixed8(0)

def NetworkFee(self):

Expand Down
1 change: 0 additions & 1 deletion neo/Core/TX/test_transactions.py
Expand Up @@ -106,7 +106,6 @@ def test_invocation_transaction(self):
self.assertEqual(tx.ToArray(), self.ir)
self.assertEqual(tx.Hash.ToBytes(), self.ir_id)


mr = b'00006666654200000000'
mrn = 1113941606
mrh = b'4c68669a54fa247d02545cff9d78352cb4a5059de7b3cd6ba82efad13953c9b9'
Expand Down
43 changes: 13 additions & 30 deletions neo/Prompt/Commands/Invoke.py
Expand Up @@ -2,6 +2,8 @@
from neo.SmartContract.ContractParameterType import ContractParameterType, ToName
from neo.VM.ScriptBuilder import ScriptBuilder
from neo.Network.NodeLeader import NodeLeader
from neo.Prompt.Utils import parse_param

import binascii


Expand Down Expand Up @@ -74,8 +76,7 @@ def TestInvokeContract(wallet, args):
verbose = True
args.remove('verbose')

print("VERBOSE %s " % verbose)

#
params = args[1:] if len(args) > 1 else []

if len(params) > 0 and params[0] == 'describe':
Expand Down Expand Up @@ -105,7 +106,10 @@ def TestInvokeContract(wallet, args):
return None,None




def test_invoke(script, wallet):

bc = GetBlockchain()

sn = bc._db.snapshot()
Expand All @@ -117,7 +121,9 @@ def test_invoke(script, wallet):
storages = DBCollection(bc._db, sn, DBPrefix.ST_Storage, StorageItem)

tx = InvocationTransaction()
tx.Version = 0
tx.Version = 1
tx.outputs = []
tx.inputs = []
tx.scripts = []
tx.Script = binascii.unhexlify(script)

Expand All @@ -141,6 +147,7 @@ def test_invoke(script, wallet):

engine.LoadScript(tx.Script, False)


try:
# drum roll?
success = engine.Execute()
Expand All @@ -149,20 +156,21 @@ def test_invoke(script, wallet):

service.TestCommit()


consumed = engine.GasConsumed() - Fixed8.FromDecimal(10)
consumed.value = int(consumed.value)

if consumed < Fixed8.One():
consumed = Fixed8.One()

#set the amount of gas the tx will need
tx.Gas = consumed


#remove the attributes that are used to add a verification script to the tx
tx.Attributes = []

return tx, engine.EvaluationStack.Items
else:
print("error executing contract.....")

except Exception as e:
print("COULD NOT EXECUTE %s " % e)
Expand All @@ -184,28 +192,3 @@ def descripe_contract(contract):
print("method signature %s --> %s" % (' '.join(method_signature), rettype))



def parse_param(p):


try:
val = int(p)
out = BigInteger(val)
return out
except Exception as e:
pass

try:
val = eval(p)

if type(val) is bytearray:
return val.hex()

return val
except Exception as e:
pass

if type(p) is str:
return binascii.hexlify( p.encode('utf-8'))

return p
130 changes: 130 additions & 0 deletions neo/Prompt/Commands/LoadSmartContract.py
@@ -0,0 +1,130 @@

import os
import binascii
from neo.Prompt.Utils import parse_param
from neo.Core.FunctionCode import FunctionCode
from prompt_toolkit import prompt
import json
from neo.VM.ScriptBuilder import ScriptBuilder
from neo.Core.TX.InvocationTransaction import InvocationTransaction
from neo.VM import OpCode

def LoadContract(args):

if len(args) < 4:
print("please specify contract to load like such: 'import contract {path} {params} {return_type} {needs_storage}'")
return

path = args[0]
params = parse_param(args[1], ignore_int=True, prefer_hex=False)

if type(params) is str:
params = params.encode('utf-8')

return_type = parse_param(args[2], ignore_int=True, prefer_hex=False)

if type(return_type) is str:
return_type = return_type.encode('utf-8')

needs_storage = bool(parse_param(args[3]))

script = None

with open(path, 'rb') as f:

content = f.read()

try:
content = binascii.unhexlify(content)
except Exception as e:
pass

script = content


if script is not None:

function_code = FunctionCode(script=script,param_list=bytearray(binascii.unhexlify(params)), return_type=binascii.unhexlify(return_type), needs_storage=needs_storage)

return function_code


print("error loading contract for path %s" % path)
return None


def GatherContractDetails(function_code, prompter):

name = None
version = None
author = None
email = None
description = None

print("Please fill out the following contract details:")
name = prompt("[Contract Name] > ",
completer=prompter.completer,
history=prompter.history,
get_bottom_toolbar_tokens=prompter.get_bottom_toolbar,
style=prompter.token_style)


version = prompt("[Contract Version] > ",
completer=prompter.completer,
history=prompter.history,
get_bottom_toolbar_tokens=prompter.get_bottom_toolbar,
style=prompter.token_style)


author = prompt("[Contract Author] > ",
completer=prompter.completer,
history=prompter.history,
get_bottom_toolbar_tokens=prompter.get_bottom_toolbar,
style=prompter.token_style)



email = prompt("[Contract Email] > ",
completer=prompter.completer,
history=prompter.history,
get_bottom_toolbar_tokens=prompter.get_bottom_toolbar,
style=prompter.token_style)


description = prompt("[Contract Description] > ",
completer=prompter.completer,
history=prompter.history,
get_bottom_toolbar_tokens=prompter.get_bottom_toolbar,
style=prompter.token_style)


print("Creating smart contract....")
print(" Name: %s " % name)
print(" Version: %s" % version)
print(" Author: %s " % author)
print(" Email: %s " % email)
print(" Description: %s " % description)
print("Needs Storage: %s " % function_code.NeedsStorage)
print(json.dumps(function_code.ToJson(), indent=4))

return generate_deploy_script(name, version, author, email, description,
function_code.NeedsStorage, function_code.ReturnType,
function_code.ParameterList, function_code.Script)

def generate_deploy_script(name, version, author, email, description, needs_storage, return_type, parameter_list, script):
sb = ScriptBuilder()

sb.push(binascii.hexlify(description.encode('utf-8')))
sb.push(binascii.hexlify(email.encode('utf-8')))
sb.push(binascii.hexlify(author.encode('utf-8')))
sb.push(binascii.hexlify(version.encode('utf-8')))
sb.push(binascii.hexlify(name.encode('utf-8')))
sb.WriteBool(needs_storage)
sb.push(ord(return_type))
sb.push(binascii.hexlify(parameter_list))
sb.WriteVarData(script)
sb.EmitSysCall("Neo.Contract.Create")

script = sb.ToArray()

return script
32 changes: 32 additions & 0 deletions neo/Prompt/Utils.py
@@ -0,0 +1,32 @@
import binascii
from neo.BigInteger import BigInteger


def parse_param(p, ignore_int=False, prefer_hex=True):

if not ignore_int:
try:
val = int(p)
out = BigInteger(val)
return out
except Exception as e:
pass

try:
val = eval(p)

if type(val) is bytearray:
return val.hex()

return val
except Exception as e:
pass

if type(p) is str:
if prefer_hex:
return binascii.hexlify( p.encode('utf-8'))
else:
return p.encode('utf-8')


return p
12 changes: 7 additions & 5 deletions neo/SmartContract/ApplicationEngine.py
Expand Up @@ -163,6 +163,7 @@ def Execute(self):
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
self.__log.debug(exc_type, fname, exc_tb.tb_lineno)
self.__log.debug("exception calculating gas consumed %s " % e)
print("Exception calculating gas consumbed %s " % e)
return False

if not self.testMode and self.gas_consumed > self.gas_amount:
Expand Down Expand Up @@ -267,16 +268,17 @@ def GetPriceForSysCall(self):
return 1000

elif api == "Neo.Validator.Register":
return 1000 * 100000000 / self.ratio
return int(1000 * 100000000 / self.ratio)

elif api == "Neo.Asset.Create":
return 5000 * 100000000 / self.ratio
return int(5000 * 100000000 / self.ratio)

elif api == "Neo.Asset.Renew":
return self.EvaluationStack.Peek(1).GetBigInteger() * 5000 * 100000000 / self.ratio
return int(self.EvaluationStack.Peek(1).GetBigInteger() * 5000 * 100000000 / self.ratio)

elif api == "Neo.Contract.Create" or api == "Neo.Contract.Migrate":
return 500 * 100000000 / self.ratio
amount = int(500 * 100000000 / self.ratio)
return amount

elif api == "Neo.Storage.Get":
return 100
Expand All @@ -285,7 +287,7 @@ def GetPriceForSysCall(self):
l1 = len(self.EvaluationStack.Peek(1).GetByteArray())
l2 = len(self.EvaluationStack.Peek(2).GetByteArray())

return ((l1 + l2 - 1) / 1024 + 1) * 1000
return int(((l1 + l2 - 1) / 1024 + 1) * 1000)

elif api == "Neo.Storage.Delete":
return 100
Expand Down

0 comments on commit 93f127f

Please sign in to comment.