Beispiel #1
0
def set_fee(_w3: Web3, _fee: float):
    """
    Set new fee for battery registraton

    :param Web3 _w3: Web3 instance
    :param float _fee: New fee to set
    :return: Status message
    :rtype: str
    """

    data = utils.open_data_base(ACCOUNT_DB_NAME)
    actor = data['account']

    tx = {'from': actor, 'gasPrice': utils.get_actual_gas_price(_w3)}

    mgmt_contract = utils.init_management_contract(_w3)

    utils.unlock_account(_w3, actor, data['password'])

    tx_hash = mgmt_contract.functions.setFee(_w3.toWei(_fee, 'ether')).transact(tx)
    receipt = web3.eth.wait_for_transaction_receipt(_w3, tx_hash, 120, 0.1)
    result = receipt.status

    if result == 1:
        return f"{bcolors.OKGREEN}Fee setting was successfull{bcolors.ENDC}"
    else:
        return f"{bcolors.FAIL}Fee setting failed{bcolors.ENDC}"
Beispiel #2
0
def get_addr() -> str:
    """
    Get service center's address

    :return: Service center's address
    :rtype: str 
    """

    data = utils.open_data_base(ACCOUNT_DB_NAME)
    return data['account']
Beispiel #3
0
def transfer_battery_to_sc(w3: Web3, car_battery_id: str, sc_address: str):
    """
    Transfer battery to service center

    :param Web3 w3: Web3 instance
    :param str car_battery_id: Car's battery id
    :param str sc_battery_id: Service centers's battery id

    return: Nothing
    rtype: None
    """

    data = utils.open_data_base(MGMT_CONTRACT_DB_NAME)

    if data is None:
        return 'Cannot access management contract database'

    data = utils.open_data_base(ACCOUNT_DB_NAME)

    if data is None:
        return 'Cannot access account database'

    private_key = data['key']
    battery_mgmt_contract_addr = utils.get_battery_managment_contract_addr(w3)
    battery_mgmt_contract = utils.init_battery_management_contract(
        w3, battery_mgmt_contract_addr)
    car_address = w3.eth.account.privateKeyToAccount(private_key).address
    gas_price = utils.get_actual_gas_price(w3)

    nonce = w3.eth.getTransactionCount(car_address)
    tx = {'gasPrice': gas_price, 'nonce': nonce, 'gas': 2204 * 68 + 21000}

    reg_tx = battery_mgmt_contract.functions.transfer(
        sc_address, decode_hex(car_battery_id)).buildTransaction(tx)
    sign_tx = w3.eth.account.signTransaction(reg_tx, private_key)
    tx_hash = w3.eth.sendRawTransaction(sign_tx.rawTransaction)
    receipt = web3.eth.wait_for_transaction_receipt(w3, tx_hash, 120, 0.1)

    if receipt.status != 1:
        sys.exit(
            f"{bcolors.FAIL}The car does not own this battery!{bcolors.ENDC}")
Beispiel #4
0
def get_deposit(_w3: Web3):
    """
    Get account deposit

    :param Web3 _w3: Web3 instance
    :return: Vendor's deposit in ether
    :rtype: float
    """

    data = utils.open_data_base(ACCOUNT_DB_NAME)
    actor = data['account']

    mgmt_contract = utils.init_management_contract(_w3)

    try:
        deposit = mgmt_contract.functions.getDeposit().call({'from': actor})

        return _w3.fromWei(deposit, 'ether')

    except:
        sys.exit(f"{bcolors.FAIL}The vendor doesn't exist{bcolors.ENDC}")
Beispiel #5
0
def register_car(_w3: Web3):
    """
    Register new car

    :param Web3 _w3: Web3 instance
    """

    data = utils.open_data_base(MGMT_CONTRACT_DB_NAME)

    if data is None:
        return f'{bcolors.FAIL}Cannot access management contract database{bcolors.ENDC}'

    data = CONFIG

    if data is None:
        return f'{bcolors.FAIL}Cannot access account database{bcolors.ENDC}'

    private_key = data['key']
    mgmt_contract = utils.init_management_contract(_w3)
    car_address = _w3.eth.account.privateKeyToAccount(private_key).address
    registration_required_gas = 50000
    gas_price = utils.get_actual_gas_price(_w3)

    if registration_required_gas * gas_price > _w3.eth.getBalance(car_address):
        return 'No enough funds to send transaction'

    nonce = _w3.eth.getTransactionCount(car_address)
    tx = {'gasPrice': gas_price, 'nonce': nonce}

    regTx = mgmt_contract.functions.registerCar().buildTransaction(tx)
    signTx = _w3.eth.account.signTransaction(regTx, private_key)
    txHash = _w3.eth.sendRawTransaction(signTx.rawTransaction)
    receipt = web3.eth.wait_for_transaction_receipt(_w3, txHash, 120, 0.1)

    if receipt.status == 1:
        return f'{bcolors.OKGREEN}Registered successfully{bcolors.ENDC}'
    else:
        return f'{bcolors.FAIL}Car registration failed{bcolors.ENDC}'
Beispiel #6
0
def register_scenter(_w3: Web3):
    """
    Register new service center

    :param Web3 _w3: Web3 instance
    :return: Registration status message
    :rtype: str
    """

    mgmt_contract = utils.init_management_contract(_w3)
    data = utils.open_data_base(ACCOUNT_DB_NAME)

    if data is None:
        sys.exit(f"{bcolors.FAIL}Cannot access account database{bcolors.ENDC}")

    actor = data['account']

    tx = {'from': actor, 'gasPrice': utils.get_actual_gas_price(_w3)}

    if REGISTRATION_REQUIRED_GAS * tx['gasPrice'] > _w3.eth.getBalance(actor):
        sys.exit(
            f"{bcolors.FAIL}No enough funds to send transaction{bcolors.ENDC}")

    utils.unlock_account(_w3, actor, data['password'])

    try:
        tx_hash = mgmt_contract.functions.registerServiceCenter().transact(tx)
    except ValueError:
        sys.exit(f"{bcolors.FAIL}Already registered{bcolors.ENDC}")

    receipt = web3.eth.wait_for_transaction_receipt(_w3, tx_hash, 120, 0.1)

    if receipt.status == 1:
        return f"{bcolors.OKGREEN}Registered successfully{bcolors.ENDC}"

    else:
        return f"{bcolors.FAIL}Registration failed{bcolors.ENDC}"
Beispiel #7
0
def change_owner(_w3: Web3, _battery_id: str, _new_owner: str) -> str:
    """
    Change the owner of battery

    :param Web3 _w3: Web3 instance
    :param str _battery_id: battery ID
    :param str _new_owner: New owner address
    :return: Status message
    :rtype: str    

    """

    data = utils.open_data_base(ACCOUNT_DB_NAME)
    actor = data['account']

    tx = {
        'from': actor,
        'gasPrice': utils.get_actual_gas_price(_w3),
        'gas': 2204 * 68 + 21000
    }

    battery_mgmt_contract_addr = utils.get_battery_managment_contract_addr(_w3)
    battery_mgmt_contract = utils.init_battery_management_contract(
        _w3, battery_mgmt_contract_addr)

    utils.unlock_account(_w3, actor, data['password'])

    tx_hash = battery_mgmt_contract.functions.transfer(
        _new_owner, decode_hex(_battery_id)).transact(tx)
    receipt = web3.eth.wait_for_transaction_receipt(_w3, tx_hash, 120, 0.1)
    result = receipt.status

    if result == 1:
        return f"{bcolors.OKGREEN}Ownership change was successfull{bcolors.ENDC}"
    else:
        return f"{bcolors.FAIL}Ownership change failed{bcolors.ENDC}"
Beispiel #8
0
def initiate_replacement(w3: Web3, car_battery_id: str,
                         sc_battery_id: str) -> None:
    """
    Initiate battery replacement

    :param Web3 w3: Web3 instance
    :param str car_battery_id: Car's battery
    :param str sc_battery_id: Service center's battery
    :return: Nothing
    :rtype: None
    """

    sc_battery_id_path = f"firmware/{car_battery_id[:8]}.py"
    car_battery_id_path = f"firmware/{sc_battery_id[:8]}.py"

    print("Verifying battery...")

    data = utils.verify_battery(w3, sc_battery_id_path)

    if not data[0]:
        sys.exit(f"{bcolors.FAIL}The battery is fake{bcolors.ENDC}")

    sys.stdout.write("\033[F")  #back to previous line
    sys.stdout.write("\033[K")  #clear line

    print(f"Verifying battery...{bcolors.OKGREEN}Success{bcolors.ENDC}",
          u'\u2713')

    print("Asking service center for replacement...")

    ask_for_replacement(car_battery_id, sc_battery_id,
                        get_car_account_from_db(w3))

    message = utils.open_data_base('replacement.json')

    if message is None:
        sys.exit(f"{bcolors.FAIL}Somethong went wrong...{bcolors.ENDC}")

    if not message['approved']:
        sys.exit(message['error'])

    sys.stdout.write("\033[F")  #back to previous line
    sys.stdout.write("\033[K")  #clear line

    print(
        f"Asking service center for replacement...{bcolors.OKGREEN}Approved{bcolors.ENDC}",
        u'\u2713')

    print("Getting address of the service center...")

    sc_address = get_sc_address()

    sys.stdout.write("\033[F")  #back to previous line
    sys.stdout.write("\033[K")  #clear line

    print(
        f"Getting address of the service center...{bcolors.OKGREEN}Success{bcolors.ENDC}",
        u'\u2713')

    print("Transferring battery to the service center...")

    transfer_battery_to_sc(w3, car_battery_id, sc_address)

    sys.stdout.write("\033[F")  #back to previous line
    sys.stdout.write("\033[K")  #clear line

    print(
        f"Transferring battery to the service center...{bcolors.OKGREEN}Success{bcolors.ENDC}",
        u'\u2713')

    print("Waiting for new battery installation...")

    result = get_new_battery(get_car_account_from_db(w3), car_battery_id,
                             sc_battery_id)

    sys.stdout.write("\033[F")  #back to previous line
    sys.stdout.write("\033[K")  #clear line

    print(f"Battery was installed...{bcolors.OKGREEN}Success{bcolors.ENDC}",
          u'\u2713')

    return result
Beispiel #9
0
from random import randint
import argparse
import web3
from web3 import Web3
from web3.middleware import geth_poa_middleware
from eth_utils import decode_hex

# Project modules
import utils
from TextColor.color import bcolors

URL = "http://127.0.0.1:8545"
ACCOUNT_DB_NAME = 'car.json'
MGMT_CONTRACT_DB_NAME = utils.MGMT_CONTRACT_DB_NAME
MGMT_CONTRACT_SRC_PATH = utils.MGMT_CONTRACT_SRC_PATH
CONFIG = utils.open_data_base(ACCOUNT_DB_NAME)
DATABASE = utils.open_data_base(MGMT_CONTRACT_DB_NAME)

if DATABASE is None:
    sys.exit(f"{bcolors.FAIL}Setup hasn't been done{bcolors.ENDC}")


def generate_private_key(_w3: Web3) -> str:
    """
    Generate private key for car account using current time and random int
    
    :param Web3 _w3: Web3 instance
    :return: Private Key
    :rtype: str
    """
Beispiel #10
0
def main() -> None:
    w3 = Web3(Web3.HTTPProvider(URL))

    # configure provider to work with PoA chains
    w3.middleware_onion.inject(geth_poa_middleware, layer=0)

    parser = create_parser()
    args = parser.parse_args()

    config = utils.open_data_base("account.json")

    if config is None:
        sys.exit(f"{bcolors.FAIL}Can't access account database{bcolors.ENDC}")

    actor = w3.toChecksumAddress(config['account'])
    gas_price = utils.get_actual_gas_price(w3)

    global TX_TEMPLATE
    TX_TEMPLATE = {'from': actor, 'gasPrice': gas_price}

    if args.new:
        print(utils.create_new_account(w3, args.new, ACCOUNT_DB_NAME))

    elif args.reg:
        w3.geth.personal.unlockAccount(actor, config['password'], 300)

        result = register_vendor(w3, args.reg[0],
                                 w3.toWei(float(args.reg[1]), 'ether'))

        if isinstance(result, bytes):
            print(
                f'{bcolors.OKGREEN}Success{bcolors.ENDC}\nVendor ID: {bcolors.HEADER}{del_hex_prefix(w3.toHex(result))}{bcolors.ENDC}'
            )
        else:
            sys.exit(result)

    elif args.bat:
        w3.geth.personal.unlockAccount(actor, config['password'], 300)

        if len(args.bat) == 1:
            result = register_battery(w3, int(args.bat[0]))
        else:
            result = register_battery(w3, int(args.bat[0]),
                                      Web3.toWei(float(args.bat[1])))

        if isinstance(result, list):
            for bat_id in result:
                print(
                    f'Created battery with id: {bcolors.HEADER}{bat_id[2:]}{bcolors.ENDC}'
                )

    elif args.regfee:
        print(
            f'Vendor registration fee: {bcolors.HEADER}{get_fee(w3) * 1000}{bcolors.ENDC} eth'
        )

    elif args.batfee:
        print(
            f'Battery registration fee: {bcolors.HEADER}{get_fee(w3)}{bcolors.ENDC} eth'
        )

    elif args.deposit:
        print(
            f"Vendor deposit: {bcolors.HEADER}{get_deposit(w3)}{bcolors.ENDC} eth"
        )

    elif args.owner:
        print(change_owner(w3, args.owner[0], args.owner[1]))

    else:
        sys.exit(f"{bcolors.FAIL}No parameters provided{bcolors.ENDC}")
Beispiel #11
0
def setup(_w3: Web3, _service_fee: float) -> Union[dict, None]:
    """
    Deploy and initialize Management, BatteryManagement,
    ServiceProviderWallet and CurrencyToken contracts to the blockchain

    :param Web3 _w3: Web3 instance
    :params float _service_fee: Set fee for battery registration
    :return: Pairs of contract names and their addresses if setup successfull and None if not
    :rtype: dict/None
    """

    service_fee = _w3.toWei(_service_fee, 'ether')

    data = utils.open_data_base(ACCOUNT_DB_NAME)

    if data is None:
        print("Can't access account database")
        return

    actor = data['account']

    utils.unlock_account(_w3, actor, data['password'])

    tx_dict = {}

    for i in ['token', 'wallet']:
        tx_dict[i] = utils._deploy_contract(_w3, actor, CONTRACTS[i][0], CONTRACTS[i][1])

    # wait for deployment transactions validation
    receipt_dict = utils._wait_for_validation(_w3, tx_dict)

    currency_token_contract_addr = receipt_dict['token'][1]['contractAddress']
    service_provider_wallet_addr = receipt_dict['wallet'][1]['contractAddress']

    if (receipt_dict['token'][1] is not None) and (receipt_dict['wallet'][1] is not None):
        currency_token_contract_addr = receipt_dict['token'][1]['contractAddress']
        service_provider_wallet_addr = receipt_dict['wallet'][1]['contractAddress']

        if service_provider_wallet_addr is not None:
            # deploy managment contract
            mgmt_contract_addr = utils._deploy_contract_and_wait(_w3, actor, CONTRACTS['mgmt'][0], CONTRACTS['mgmt'][1], 
                                                           service_provider_wallet_addr, service_fee)
            
            if mgmt_contract_addr is not None:
                utils._create_mgmt_contract_db(mgmt_contract_addr)

                # deploy battery managment
                battery_mgmt_contract_addr = utils._deploy_contract_and_wait(_w3, actor, CONTRACTS['battery'][0], CONTRACTS['battery'][1],
                                                                       mgmt_contract_addr, currency_token_contract_addr)
                
                if battery_mgmt_contract_addr is not None:
                    compiled_contract = utils.compile_contracts(CONTRACTS['mgmt'][0])
                    mgmt_contract = utils.initialize_contract_factory(_w3, compiled_contract,
                                                                      CONTRACTS['mgmt'][0] + ':' + CONTRACTS['mgmt'][1],
                                                                      mgmt_contract_addr)

                    tx_hash = mgmt_contract.functions.setBatteryManagementContract(battery_mgmt_contract_addr).transact({'from': actor, 'gasPrice': utils.get_actual_gas_price(_w3)})
                    receipt = web3.eth.wait_for_transaction_receipt(_w3, tx_hash, 120, 0.1)

                    if receipt.status == 1:
                        contract_addresses = {
                            'Management contract': mgmt_contract_addr,
                            'Wallet contract'    : service_provider_wallet_addr,
                            'Currency contract:' : currency_token_contract_addr
                        }

                        return contract_addresses

    return None