Unverified Commit c29b524f authored by cyjseagull's avatar cyjseagull Committed by GitHub
Browse files

ignore cases when using client_config.crypto_type && download solc binary from...

ignore cases when using client_config.crypto_type && download solc binary from fisco-bcos solidity && add mac to check the validition of gm-account password (#107)
parent abb3b5ee
{
"address": "0x64C40b7E82A4A5acFC5acE6422590Ac4Ce5F0BDB",
"encrypt": true,
"private_key": "uCsTcBT5uNUkTz5P752Lur99rplp8hL516cuNJSPn0PTrmYoqr79WptAqxaWssT3jofJHBB0MylEDTsaJuCYOcRrZYLcSJ3PAL3JK4aaL3Q=",
"address": "0xb925aA05369C23ab1b46d9f4FaCa08126536AE85",
"type": "gm"
"private_key": "fJknVt3c7Q7jU/IMuXAtJPqsziI12ayZ6KuTeyrEMiKthfGbiZH8L1rT4FzjTu8zM2tESg1PqKKcZZDaHmoWhyd9iRC+anRerBXAKO3GFUg=",
"type": "gm",
"mac": "3a11d41dd2847c61c575de0dd4e03d46bb0a9e270689d6145dd6b812c3b60ab5"
}
\ No newline at end of file
原理:solc是solidity合约的编译器。采用二进制的solc编译器,对合约进行编译,而不是采用python代码实现的编译器来直接对合约进行编译。
**合约的编译器选择方式包括**
1) 操作系统类型,linux/windows
2) 合约所用的solidity语言版本,如0.4或0.5
3) 是否国密版本
**操作次序:**
1.在以下链接中选择对应的release发布包,下载到python-sdk/bin/solc目录
2.将下载的文件解压(如为压缩包)并将编译器执行文件改名为solc。
3.确认python-sdk/solc.py 文件里对solc名字或路径的定义和这里的solc能完全匹配,总之目的是使得编译命令行一定能找到对应的solc,设置为系统path变量也是可以的。
In English:
1. Download the solc binary according to your OS type (e.g. Linux/Windows) and solidity version.
2. Copy the solc binary to python-sdk/bin/solc/.
3. Make sure that the name of solc binary file is renamed to "solc", or update the solc binary path constant in python-sdk/solcpy.py.
## solc release on github:
https://github.com/FISCO-BCOS/solidity/releases
## linux:
**for solidity 0.5 (<= 0.5.2)**
https://github.com/FISCO-BCOS/solidity/releases/download/v0.5.2/solc-linux
gm version (OSCCA-approved version) :
centos: https://github.com/FISCO-BCOS/solidity/releases/download/v0.5.2/solc-gm-centos
ubuntu: https://github.com/FISCO-BCOS/solidity/releases/download/v0.5.2/solc-gm-ubuntu
**for solidity 0.4 (<= 0.4.25)**
https://github.com/FISCO-BCOS/solidity/releases/download/v0.4.25/solc-static-linux
gm version (OSCCA-approved version):
https://github.com/FISCO-BCOS/solidity/releases/download/v0.4.25/solc-gm-static-linux
## windows
**for solidity 0.5 (<= 0.5.2)**
https://github.com/FISCO-BCOS/solidity/releases/download/v0.5.2/solc-windows.zip
gm version (OSCCA-approved version):
https://github.com/FISCO-BCOS/solidity/releases/download/v0.5.2/solc-gm-windows.exe
**for solidity 0.4 (<= 0.4.25)**
https://github.com/FISCO-BCOS/solidity/releases/download/v0.4.25/solc-windows.zip
gm version (OSCCA-approved version):
https://github.com/FISCO-BCOS/solidity/releases/download/v0.4.25/solc-gm-windows.exe
......@@ -5,7 +5,7 @@ set -e
scan_code_script="python ~/cobra/cobra.py -t "
ignore_files=(ci README.md console.py event_callback.py eth_account eth_abi \
eth_hash eth_keys eth_rlp eth_typing eth_utils tests gmssl \
hexbytes utils rlp client eth_account/account.py)
hexbytes utils rlp client eth_account/account.py bin/accounts/gm_account.json)
LOG_ERROR() {
content=${1}
......
......@@ -82,14 +82,14 @@ class BcosClient:
raise BcosException(("gm account keyfile file {} doesn't exist, "
"please check client_config.py again "
"and make sure this account exist")
.format(self.keystore_file))
.format(self.gm_account_file))
self.gm_account.load_from_file(
self.gm_account_file, client_config.gm_account_password)
self.keypair = self.gm_account.keypair
return
except Exception as e:
raise BcosException("load gm account from {} failed, reason: {}"
.format(self.keystore_file, e))
.format(self.gm_account_file, e))
# 默认的 ecdsa 账号
try:
......@@ -171,7 +171,7 @@ class BcosClient:
if client_config.client_protocol == client_config.PROTOCOL_CHANNEL:
info = "channel {}:{}".format(self.channel_handler.host, self.channel_handler.port)
info += ",groupid :{}".format(self.groupid)
#if self.ecdsa_account is not None:
# if self.ecdsa_account is not None:
if self.keypair is not None:
info += ",from address: {}".format(self.keypair.address)
return info
......@@ -450,6 +450,11 @@ class BcosClient:
params = [client_config.groupid, callmap]
# 发送
response = self.common_request(cmd, params)
# check status
if "status" in response.keys():
status = int(response["status"], 16)
if status != 0:
return response
if "output" in response.keys():
outputdata = response["output"]
# 取得方法的abi,签名,参数 和返回类型,进行call返回值的解析
......
......@@ -27,6 +27,7 @@ from eth_utils.crypto import *
from gmssl.sm4 import CryptSM4, SM4_DECRYPT, SM4_ENCRYPT
from client.bcoskeypair import BcosKeyPair
import json
import hmac
class GM_Account(object):
......@@ -73,24 +74,33 @@ class GM_Account(object):
content["encrypt"] = True
content["private_key"] = key
content["type"] = "gm"
# set mac of the password
passwdBytes = bytes(decode_hex(password))
content["mac"] = sm3.sm3_hash(passwdBytes)
with open(filename, "w") as dump_f:
json.dump(content, dump_f, indent=4)
dump_f.close()
# 从文件加载,格式是json
def load_from_file(self, filename, password=None):
if password is None or len(password) == 0:
return
with open(filename, "r") as dump_f:
content = json.load(dump_f)
dump_f.close()
if content["type"] != "gm":
return
# get and compare mac
expected_mac = content["mac"]
password = self.pwd_ljust(password)
passwdBytes = bytes(decode_hex(password))
mac = sm3.sm3_hash(passwdBytes)
if not hmac.compare_digest(mac, expected_mac):
raise ValueError("MAC mismatch")
key = content["private_key"]
if password is not None and len(password) > 0:
crypt_sm4 = CryptSM4()
password = self.pwd_ljust(password)
crypt_sm4.set_key(bytes(password, "utf-8"), SM4_DECRYPT)
key = base64.b64decode(bytes(key, "utf-8"))
key = str(crypt_sm4.crypt_cbc(self.cbc_iv, key), "utf-8")
crypt_sm4 = CryptSM4()
crypt_sm4.set_key(bytes(password, "utf-8"), SM4_DECRYPT)
key = base64.b64decode(bytes(key, "utf-8"))
key = str(crypt_sm4.crypt_cbc(self.cbc_iv, key), "utf-8")
self.from_key(key)
......@@ -79,7 +79,7 @@ class SignTx():
def sign_transaction_hash(self, transaction_hash, chain_id):
hashbyte = bytes(transaction_hash)
if self.crypto_type is CRYPTO_TYPE_GM:
if self.crypto_type == CRYPTO_TYPE_GM:
# gm sign
public_key = self.gm_account.keypair.public_key
private_key = self.gm_account.keypair.private_key
......@@ -90,7 +90,7 @@ class SignTx():
(r, s) = sm2_crypt.sign(hashbyte)
v_raw = public_key
v = int(v_raw, 16)
elif self.crypto_type is CRYPTO_TYPE_ECDSA:
elif self.crypto_type == CRYPTO_TYPE_ECDSA:
# ecdsa sign
signature = self.ecdsa_account._key_obj.sign_msg_hash(transaction_hash)
(v_raw, r, s) = signature.vrs
......
......@@ -17,6 +17,7 @@ class client_config:
# ---------crypto_type config--------------
# crypto_type : 大小写不敏感:"GM" for 国密, "ECDSA" 或其他是椭圆曲线默认实现。
crypto_type = "ECDSA"
crypto_type = crypto_type.upper()
set_crypto_type(crypto_type) # 使密码算法模式全局生效,切勿删除此行
# --------------------------------------
......@@ -47,7 +48,8 @@ class client_config:
# ---------runtime related--------------
# path of solc compiler
solc_path = os.environ["HOME"] + "/.py-solc/solc-v0.4.25/bin/solc"
solc_path = "./bin/solc/v0.4.25/solc"
#solc_path = "./bin/solc/v0.4.25/solc-gm"
solcjs_path = "./solcjs"
logdir = "bin/logs" # 默认日志输出目录,该目录必须先建立
......@@ -418,7 +418,7 @@ def main(argv):
common.check_param_num(inputparams, 2, True)
name = inputparams[0]
password = inputparams[1]
if client_config.crypto_type is CRYPTO_TYPE_GM:
if client_config.crypto_type == CRYPTO_TYPE_GM:
show_gm_account(name, password)
else:
show_ecdsa_account(name, password)
......@@ -500,8 +500,7 @@ def main(argv):
if len(inputparams) == 3 and inputparams[2] == "save":
forcewrite = True
print("starting : {} {} , if save:{}".format(name, password, forcewrite))
if client_config.crypto_type is CRYPTO_TYPE_GM:
if client_config.crypto_type == CRYPTO_TYPE_GM:
create_gm_account(name, password, forcewrite)
else:
create_ecdsa_account(name, password, forcewrite)
......
pragma solidity ^0.4.24;
import "./Table.sol";
contract KVTableTest {
event SetResult(int256 count);
KVTableFactory tableFactory;
string constant TABLE_NAME = "t_kvtest";
constructor() public {
//The fixed address is 0x1010 for KVTableFactory
tableFactory = KVTableFactory(0x1010);
// the parameters of createTable are tableName,keyField,"vlaueFiled1,vlaueFiled2,vlaueFiled3,..."
tableFactory.createTable(TABLE_NAME, "id", "item_price,item_name");
}
//get record
function get(string id) public view returns (bool, int256, string) {
KVTable table = tableFactory.openTable(TABLE_NAME);
bool ok = false;
Entry entry;
(ok, entry) = table.get(id);
int256 item_price;
string memory item_name;
if (ok) {
item_price = entry.getInt("item_price");
item_name = entry.getString("item_name");
}
return (ok, item_price, item_name);
}
//set record
function set(string id, int256 item_price, string item_name)
public
returns (int256)
{
KVTable table = tableFactory.openTable(TABLE_NAME);
Entry entry = table.newEntry();
// the length of entry's field value should < 16MB
entry.set("id", id);
entry.set("item_price", item_price);
entry.set("item_name", item_name);
// the first parameter length of set should <= 255B
int256 count = table.set(id, entry);
emit SetResult(count);
return count;
}
}
contract TableFactory {
function openTable(string) public constant returns (Table); //open table
function createTable(string,string,string) public constant returns(int); //create table
function openTable(string memory) public view returns (Table); //open table
function createTable(string, string, string) public returns (int256); //create table
}
//select condition
contract Condition {
function EQ(string, int);
function EQ(string, string);
function NE(string, int);
function NE(string, string);
function GT(string, int);
function GE(string, int);
function LT(string, int);
function LE(string, int);
function limit(int);
function limit(int, int);
function EQ(string, int256) public;
function EQ(string, string) public;
function NE(string, int256) public;
function NE(string, string) public;
function GT(string, int256) public;
function GE(string, int256) public;
function LT(string, int256) public;
function LE(string, int256) public;
function limit(int256) public;
function limit(int256, int256) public;
}
//one record
//one record
contract Entry {
function getInt(string) public constant returns(int);
function getAddress(string) public constant returns(address);
function getBytes64(string) public constant returns(byte[64]);
function getBytes32(string) public constant returns(bytes32);
function getString(string) public constant returns(string);
function set(string, int) public;
function getInt(string) public view returns (int256);
function getUInt(string) public view returns (int256);
function getAddress(string) public view returns (address);
function getBytes64(string) public view returns (bytes1[64]);
function getBytes32(string) public view returns (bytes32);
function getString(string) public view returns (string);
function set(string, int256) public;
function set(string, uint256) public;
function set(string, string) public;
function set(string, address) public;
}
//record sets
contract Entries {
function get(int) public constant returns(Entry);
function size() public constant returns(int);
function get(int256) public view returns (Entry);
function size() public view returns (int256);
}
//Table main contract
contract Table {
//select api
function select(string, Condition) public constant returns(Entries);
//insert api
function insert(string, Entry) public returns(int);
//update api
function update(string, Entry, Condition) public returns(int);
//remove api
function remove(string, Condition) public returns(int);
function newEntry() public constant returns(Entry);
function newCondition() public constant returns(Condition);
}
\ No newline at end of file
function select(string, Condition) public view returns (Entries);
function insert(string, Entry) public returns (int256);
function update(string, Entry, Condition) public returns (int256);
function remove(string, Condition) public returns (int256);
function newEntry() public view returns (Entry);
function newCondition() public view returns (Condition);
}
contract KVTableFactory {
function openTable(string) public view returns (KVTable);
function createTable(string, string, string) public returns (int256);
}
//KVTable per permiary key has only one Entry
contract KVTable {
function get(string) public view returns (bool, Entry);
function set(string, Entry) public returns (int256);
function newEntry() public view returns (Entry);
}
......@@ -2,89 +2,96 @@ pragma solidity ^0.4.24;
pragma experimental ABIEncoderV2;
import "./Table.sol";
contract TableTest {
event CreateResult(int count);
event InsertResult(int count);
event UpdateResult(int count);
event RemoveResult(int count);
//create table
function create() public returns(int){
TableFactory tf = TableFactory(0x1001); //The fixed address is 0x1001 for TableFactory
int count = tf.createTable("t_test", "name", "item_id,item_name");
emit CreateResult(count);
return count;
event CreateResult(int256 count);
event InsertResult(int256 count);
event UpdateResult(int256 count);
event RemoveResult(int256 count);
TableFactory tableFactory;
string constant TABLE_NAME = "t_test";
constructor() public {
tableFactory = TableFactory(0x1001); //The fixed address is 0x1001 for TableFactory
// the parameters of createTable are tableName,keyField,"vlaueFiled1,vlaueFiled2,vlaueFiled3,..."
tableFactory.createTable(TABLE_NAME, "name", "item_id,item_name");
}
//select records
function select(string name) public constant returns(string[], int[], string[]){
TableFactory tf = TableFactory(0x1001);
Table table = tf.openTable("t_test");
function select(string name)
public
view
returns (string[], int256[], string[])
{
Table table = tableFactory.openTable(TABLE_NAME);
Condition condition = table.newCondition();
Entries entries = table.select(name, condition);
string[] memory user_name_bytes_list = new string[](uint256(entries.size()));
int[] memory item_id_list = new int[](uint256(entries.size()));
string[] memory item_name_bytes_list = new string[](uint256(entries.size()));
for(int i=0; i<entries.size(); ++i) {
string[] memory user_name_bytes_list = new string[](
uint256(entries.size())
);
int256[] memory item_id_list = new int256[](uint256(entries.size()));
string[] memory item_name_bytes_list = new string[](
uint256(entries.size())
);
for (int256 i = 0; i < entries.size(); ++i) {
Entry entry = entries.get(i);
user_name_bytes_list[uint256(i)] = entry.getString("name");
item_id_list[uint256(i)] = entry.getInt("item_id");
item_name_bytes_list[uint256(i)] = entry.getString("item_name");
}
return (user_name_bytes_list, item_id_list, item_name_bytes_list);
}
//insert records
function insert(string name, int item_id, string item_name) public returns(int) {
TableFactory tf = TableFactory(0x1001);
Table table = tf.openTable("t_test");
function insert(string name, int256 item_id, string item_name)
public
returns (int256)
{
Table table = tableFactory.openTable(TABLE_NAME);
Entry entry = table.newEntry();
entry.set("name", name);
entry.set("item_id", item_id);
entry.set("item_name", item_name);
int count = table.insert(name, entry);
int256 count = table.insert(name, entry);
emit InsertResult(count);
return count;
}
//update records
function update(string name, int item_id, string item_name) public returns(int) {
TableFactory tf = TableFactory(0x1001);
Table table = tf.openTable("t_test");
function update(string name, int256 item_id, string item_name)
public
returns (int256)
{
Table table = tableFactory.openTable(TABLE_NAME);
Entry entry = table.newEntry();
entry.set("item_name", item_name);
Condition condition = table.newCondition();
condition.EQ("name", name);
condition.EQ("item_id", item_id);
int count = table.update(name, entry, condition);
int256 count = table.update(name, entry, condition);
emit UpdateResult(count);
return count;
}
//remove records
function remove(string name, int item_id) public returns(int){
TableFactory tf = TableFactory(0x1001);
Table table = tf.openTable("t_test");
function remove(string name, int256 item_id) public returns (int256) {
Table table = tableFactory.openTable(TABLE_NAME);
Condition condition = table.newCondition();
condition.EQ("name", name);
condition.EQ("item_id", item_id);
int count = table.remove(name, condition);
int256 count = table.remove(name, condition);
emit RemoveResult(count);
return count;
}
}
......@@ -8,6 +8,12 @@ BASH="/bin/bash"
ZSHRC="${HOME}/.zshrc"
BASHRC="${HOME}/.bashrc"
SOLC_LINUX_URL="https://github.com/FISCO-BCOS/solidity/releases/download/v0.4.25/solc-linux.tar.gz"
SOLC_MAC_URL="https://github.com/FISCO-BCOS/solidity/releases/download/v0.4.25/solc-mac.tar.gz"
SOLC_LINUX_GM_URL="https://github.com/FISCO-BCOS/solidity/releases/download/v0.4.25/solc-linux-gm.tar.gz"
SOLC_MAC_GM_URL="https://github.com/FISCO-BCOS/solidity/releases/download/v0.4.25/solc-mac-gm.tar.gz"
SOLC_DIR="bin/solc/v0.4.25"
OS_TYPE="Linux"
LOG_WARN()
{
......@@ -100,22 +106,41 @@ install_python3()
fi
}
install_linux_solc()
{
curl -LO ${SOLC_LINUX_URL}
curl -LO ${SOLC_LINUX_GM_URL}
tar -xvf solc-linux.tar.gz
mkdir -p ${SOLC_DIR}
mv solc ${SOLC_DIR}
tar -xvf solc-linux-gm.tar.gz
mv solc ${SOLC_DIR}/solc-gm
}
install_mac_solc()
{
curl -LO ${SOLC_MAC_URL}
curl -LO ${SOLC_MAC_GM_URL}
tar -xvf solc-mac.tar.gz
mkdir -p ${SOLC_DIR}
mv solc ${SOLC_DIR}
tar -xvf solc-mac-gm.tar.gz
mv solc ${SOLC_DIR}/solc-gm
}
init_config()
{
if [ ! -f "client_config.py" ];then
LOG_INFO "copy config file..."
execute_cmd "cp client_config.py.template client_config.py"
fi
solc_path=".py-solc/solc-v0.4.25/bin/solc"
if [ ! -f "${solc_path}" ];then
solc_path="bin/solc/v0.4.25"
if [ ! -d "${solc_path}" ];then
LOG_INFO "install solc v0.4.25..."
python -m solc.install v0.4.25
if [ $? -eq 1 ];then
if [ -d "${HOME}/.py-solc/solc-v0.4.25/" ];then
execute_cmd "rm -rf ~/.py-solc/solc-v0.4.25/"
fi
LOG_INFO "install solc v0.4.25 failed, try to install slocjs"
execute_cmd "npm install solc@0.4.25"
if [ "${OS_TYPE}" == "Linux" ];then
install_linux_solc
elif [ "${OS_TYPE}" == "Darwin" ];then
install_mac_solc
fi
fi
}
......@@ -166,6 +191,7 @@ EOF
main()
{
OS_TYPE=$(uname)
while getopts "pih" option; do
case ${option} in
p) python_init
......