Я пытаюсь реализовать смарт-контракт для случая использования управления идентификацией.
Я могу пройти все тестовые случаи, которые я написал мокко с трюфелем.
Я компилирую этот смарт-контракт с помощью трюфеля и вызываю его из web3.py.
Но когда я добавляю запись в сопоставление ( sicontracts
) с ключом как bytes32
(хэш Ipfs, преобразованный в bytes32) и значением, как struct SIContract
в файле function submitContract
. Кажется, он не сохраняется в сопоставлении. Когда я проверяю это, function approveContract
он всегда возвращает false. Когда я проверил, я обнаружил, что мое сопоставление не сохраняется. Пожалуйста помоги.
Код прочности:
pragma solidity ^0.4.0;
/**
* The purpose of this contract is to provide a mechanism to verify idntity
*/
contract SmartIdentityRegistry {
address private owner;
uint constant PENDING = 0;
uint constant ACTIVE = 1;
uint constant REJECTED = 2;
/**
* Constructor of the registry.
*/
function SmartIdentityRegistry() {
owner = msg.sender;
}
/**
* The SIContract structure: every SIContract is composed of:
* - Hash of contract bytecode
* - Account that submitted the address
* - Status - 0 = pending, 1 = active, 2 = rejected.
*/
struct SIContract {
bytes32 hash;
address submitter;
uint status;
}
/**
* Mapping for contract registry.
*/
mapping(bytes32 => SIContract) public sicontracts;
/**
* The only permission worth setting; doing the reverse is pointless as a contract
* owner can interact with the contract as an anonymous third party simply by using
* another public key address.
*/
modifier onlyBy(address _account) {
if (msg.sender != _account) {
revert();
}
_;
}
/**
* Anyone can submit a contract for acceptance into a registry.
*/
function submitContract(bytes32 _contractHash, address idOwner) returns(bool) {
var sicontract = sicontracts[_contractHash];
sicontract.hash = _contractHash;
sicontract.submitter = idOwner;
sicontract.status = PENDING;
return true;
}
/**
* Only the registry owner (ideally multi-sig) can approve a contract.
*/
function approveContract(bytes32 _contractHash) returns(bool) {
var sicontract = sicontracts[_contractHash];
if(sicontract.submitter != msg.sender){
return false;
}
sicontract.status = ACTIVE;
return true;
}
/**
* Only the registry owner (ideally multi-sig) can reject a contract.
*/
function rejectContract(bytes32 _contractHash) onlyBy(owner) returns(bool) {
var sicontract = sicontracts[_contractHash];
sicontract.status = REJECTED;
return true;
}
/**
* Only the registry owner and original submitter can delete a contract.
* A contract in the rejected list cannot be removed.
*/
function deleteContract(bytes32 _contractHash) returns(bool) {
var sicontract = sicontracts[_contractHash];
if (sicontract.status != REJECTED) {
if (sicontract.submitter == msg.sender) {
if (msg.sender == owner) {
delete sicontracts[_contractHash];
return true;
}
}
} else {
revert();
}
}
/**
* This is the public registry function that contracts should use to check
* whether a contract is valid. It's defined as a function, rather than .call
* so that the registry owner can choose to charge based on their reputation
* of managing good contracts in a registry.
*
* Using a function rather than a call also allows for better management of
* dependencies when a chain forks, as the registry owner can choose to kill
* the registry on the wrong fork to stop this function executing.
*/
function isValidContract(bytes32 _contractHash) returns(bool) {
if (sicontracts[_contractHash].status == ACTIVE) {
return true;
}
if (sicontracts[_contractHash].status == REJECTED) {
revert();
} else {
return false;
}
}
}
Код Python для вызова функции отправки
self.smartIdContract.call({"from": sender_account}).submitContract(hex_hash,decode_hex(id_public_key))
Код для проверки представленной выше записи
self.smartIdContract.call({"from": wrong_addr}).approveContract(id_hash)
Что я делаю не так ? Почему мои тестовые примеры мокко работают нормально, а вызовы web3.py терпят неудачу? Я использую testrpc в качестве сети.
Мои тестовые примеры мокко для вышеуказанного контракта:
/**
* The purpose of this test contract is to test the functions in SmartIdentityRegistry.sol.
*/
var SmartIdentityRegistry = artifacts.require("SmartIdentityRegistry");
contract('SmartIdentityRegistry', function(accounts) {
var registry,
contractRegistry1,
contractRegistry2,
contracthash1,
contracthash2;
contracthash1 = '0xca02b2202ffaacbd499438ef6d594a48f7a7631b60405ec8f30a0d7c096d54d5';
contracthash2 = '0xca02b2202ffaacbd499438ef6d594a48f7a7631b60405ec8f30a0d7c096dc3ff';
before("Setup the Smart Identity registry and hydrate the required variables", function(done) {
contractRegistry1 = accounts[0];
contractRegistry2 = accounts[1];
SmartIdentityRegistry.new({from: contractRegistry1})
.then(function(response) {
registry = response;
done();
});
return registry,
contractRegistry1,
contractRegistry2;
});
describe("SmartIdentityRegistry tests", function() {
it("will submit a contract into the registry", function() {
return registry.submitContract(contracthash1,contractRegistry2, {from: contractRegistry1})
.then(function(response) {
assert.isOk(response, 'Contract submitting failed');
});
});
it("will prove that the submitter can only approve a contract", function() {
return registry.approveContract(contracthash1, {from: contractRegistry2})
.then(function(response) {
assert.isOk(response, 'Contract approval failed');
});
});
it("will prove that a non-id owner cannot approve a contract", function() {
return registry.approveContract(contracthash1, {from: contractRegistry1})
.catch(function(error) {
assert.isOk(error, "Expected error has not been caught");
});
});
it("will prove that the registry owner can reject a contract", function() {
return registry.rejectContract(contracthash1, {from: contractRegistry1})
.then(function(response) {
assert.isOk(response, 'Contract rejection failed');
});
});
it("will prove that a non-owner cannot reject a contract", function() {
return registry.rejectContract(contracthash1, {from: contractRegistry2})
.catch(function(error) {
assert.isOk(error, "Expected error has not been caught");
});
});
it("will delete a contract from the registry", function() {
registry.submitContract(contracthash2,contractRegistry2, {from: contractRegistry1})
.then(function(response) {
assert.isOk(response, 'Contract submitting failed');
});
return registry.deleteContract(contracthash2).then(function(response) {
assert.isOk(response, 'Contract failed to be deleted');
});
});
it("will verify a contract is not valid", function() {
registry.submitContract(contracthash2,contractRegistry2, {from: contractRegistry1})
.then(function(response) {
assert.isOk(response, 'Contract submitting failed');
});
return registry.isValidContract(contracthash2).then(function(response) {
assert.isOk(response, 'Failed to verify contract');
});
});
it("will verify a contract is not valid and will throw an error", function() {
registry.submitContract(contracthash2,contractRegistry2, {from: contractRegistry1})
.then(function(response) {
assert.isOk(response, 'Contract submitting failed');
});
registry.rejectContract(contracthash2, {from: contractRegistry1});
return registry.isValidContract(contracthash2)
.catch(function(error) {
assert.isOk(error, "Expected error has not been caught");
});
});
it("will verify a contract is valid", function() {
registry.submitContract(contracthash2, contractRegistry2,{from: contractRegistry1})
.then(function(response) {
assert.isOk(response, 'Contract submitting failed');
});
registry.approveContract(contracthash2, {from: contractRegistry2});
return registry.isValidContract(contracthash2)
.then(function(response) {
assert.isOk(response, 'Failed to verify contract');
});
});
});
});
Вместо звонка вам нужна транзакция. См.: В чем разница между транзакцией и вызовом?
Итак, вместо:
self.smartIdContract.call({"from": sender_account}).submitContract(...)
Пытаться:
self.smartIdContract.transact({"from": sender_account}).submitContract(...)
Или более новый синтаксис из Web3.py v4:
bound_submission = self.smartIdContract.functions.submitContract(...)
txn_hash = bound_submission.transact({"from": sender_account})
Билл Голдберг
Билл Голдберг
резчик
isValidContract
. Но да, событие может быть даже лучше здесь.Билл Голдберг
резчик