Multiinicio en una sola transacción

Estoy codificando un contrato en el que me gustaría que se llamen algunas funciones solo si lo aprueban 2 personas (un comerciante y un cliente).

Ahora, sé que podría programar un búfer que almacene la solicitud pendiente y esperar a que cada parte envíe una transacción de confirmación.

No quiero que el comerciante actúe sin la aprobación del cliente, pero el problema es que no quiero que el cliente pague la gasolina.

Lo que estaba pensando era de alguna manera hacer solo una transacción, enviada por el comerciante (quien pagará por el gas), pero que pudiera verificar en mi contrato inteligente que la transacción fue firmada por el cliente.

¿Tiene algún consejo sobre cuál es la mejor manera de implementarlo?

Gracias por tus respuestas

Respuestas (2)

Podría usar un enfoque similar a las pruebas de equilibrio en la implementación de canales estatales de Raiden . Básicamente, puede hacer que el cliente firme una confirmación que solo el cliente podría haber firmado y luego verificar esa firma en un contrato de Solidity.

En su ejemplo particular, lo abordaría así:

  1. Merchant almacena la dirección del cliente en un contrato inteligente.
  2. El cliente firma los datos de la transacción fuera de la cadena.
  3. El comerciante envía la transacción al contrato incluyendo la firma del cliente.
  4. El contrato inteligente deriva la dirección de la firma y la compara con la dirección del cliente almacenada en el paso 1.

Vea el código para usar Metamask para firmar datos aquí .

Aquí hay otro ejemplo de multisig de transacción única de Christian Lundkvist. Este esquema está más cerca de Bitcoin multisig que los contratos stateful multisig.

https://medium.com/@ChrisLundkvist/exploring-simpler-ethereum-multisig-contracts-b71020c19037

Código:

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 {}

}