Я кодирую контракт, в котором я хотел бы, чтобы некоторые функции вызывались только в том случае, если они одобрены двумя людьми (продавцом и покупателем).
Теперь я знаю, что могу запрограммировать буфер, хранящий ожидающие запросы и ожидающий, пока каждая часть отправит подтверждение транзакции.
Я не хочу, чтобы продавец действовал без одобрения покупателя, но проблема в том, что я не хочу, чтобы покупатель платил за газ.
Я думал каким-то образом сделать только одну транзакцию, отправленную продавцом (который, таким образом, будет платить за газ), но чтобы я мог проверить в своем смарт-контракте, что транзакция была подписана покупателем.
Есть ли у вас какие-либо советы о том, как лучше всего это реализовать?
Спасибо за ваши ответы
Вы можете использовать подход, аналогичный Balance Proofs в реализации Raiden каналов состояния . По сути, вы можете попросить клиента подписать подтверждение, которое мог подписать только клиент, а затем проверить эту подпись в контракте Solidity.
В вашем конкретном примере я бы подошел к этому так:
См. код использования Metamask для подписи данных здесь .
Вот еще один пример мультиподписи одной транзакции от Кристиана Лундквиста. Эта схема ближе к биткойн-мультиподписи, чем к мультиподписным контрактам с отслеживанием состояния.
https://medium.com/@ChrisLundkvist/exploring-simpler-ethereum-multisig-contracts-b71020c19037
Код:
pragma solidity 0.4.15;
contract SimpleMultiSig {
uint public nonce; // (only) mutable state
uint public threshold; // immutable state
mapping (address => bool) isOwner; // immutable state
address[] public ownersArr; // immutable state
function SimpleMultiSig(uint threshold_, address[] owners_) {
require(owners_.length <= 10 && threshold_ <= owners_.length && threshold_ != 0);
address lastAdd = address(0);
for (uint i=0; i<owners_.length; i++) {
require(owners_[i] > lastAdd);
isOwner[owners_[i]] = true;
lastAdd = owners_[i];
}
ownersArr = owners_;
threshold = threshold_;
}
// Note that address recovered from signatures must be strictly increasing
function execute(uint8[] sigV, bytes32[] sigR, bytes32[] sigS, address destination, uint value, bytes data) {
require(sigR.length == threshold);
require(sigR.length == sigS.length && sigR.length == sigV.length);
// Follows ERC191 signature scheme: https://github.com/ethereum/EIPs/issues/191
bytes32 txHash = keccak256(byte(0x19), byte(0), this, destination, value, data, nonce);
address lastAdd = address(0); // cannot have address(0) as an owner
for (uint i = 0; i < threshold; i++) {
address recovered = ecrecover(txHash, sigV[i], sigR[i], sigS[i]);
require(recovered > lastAdd && isOwner[recovered]);
lastAdd = recovered;
}
// If we make it here all signatures are accounted for
nonce = nonce + 1;
require(destination.call.value(value)(data));
}
function () payable {}
}