La implementación de contratos inteligentes con Azure Ethereum Consortium no funciona

Creé un Consorcio Azure Ethereum. La red Ethereum implementada tiene 2 nodos de transacción detrás de un balanceador de carga. A través de Putty me conecto a uno de los nodos de transacción.

luego entro

geth attach

Ahora la consola está abierta. El compilador solidity está instalado. Luego desbloqueo la cuenta para ser utilizada:

personal.unlockAccount(eth.accounts[1], "{your password}");

El saldo de la cuenta es:

400000000000000000000

Luego compilo el código:

var greeterSource = 'pragma solidity ^0.4.9; /** @title Mortal.*/ contract mortal { /* Define variable owner of the type address*/ address owner; /**@dev this function is executed at initialization and sets the owner of the contract. */ function mortal() { owner = msg.sender; } /**@dev Function to recover the funds on the contract. */ function kill() { if (msg.sender == owner) { selfdestruct(owner); } } } /** @title Greeter.*/ contract greeter is mortal { /* define variable greeting of the type string */ string greeting; /**@dev This function runs when the contract is executed. * @param _greeting Greeting message. */ function greeter(string _greeting) public { greeting = _greeting; } /* main function */ /**@dev This function returns the greeting message. * @return greeting The greeting message. */ function greet() constant returns (string) { return greeting; } }';

var greeterCompiled = web3.eth.compile.solidity(greeterSource);

El resultado:

{
  <stdin>:greeter: {
    code: "0x6060604052341561000c57fe5b6040516102f03803806102f0833981016040528051015b5b60008054600160a060020a03191633600160a060020a03161790555b805161005390600190602084019061005b565b505b506100fb565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061009c57805160ff19168380011785556100c9565b828001600101855582156100c9579182015b828111156100c95782518255916020019190600101906100ae565b5b506100d69291506100da565b5090565b6100f891905b808211156100d657600081556001016100e0565b5090565b90565b6101e68061010a6000396000f300606060405263ffffffff60e060020a60003504166341c0e1b5811461002c578063cfae32171461003e575bfe5b341561003457fe5b61003c6100ce565b005b341561004657fe5b61004e610110565b604080516020808252835181830152835191928392908301918501908083838215610094575b80518252602083111561009457601f199092019160209182019101610074565b505050905090810190601f1680156100c05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6000543373ffffffffffffffffffffffffffffffffffffffff9081169116141561010d5760005473ffffffffffffffffffffffffffffffffffffffff16ff5b5b565b6101186101a8565b60018054604080516020600284861615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561019d5780601f106101725761010080835404028352916020019161019d565b820191906000526020600020905b81548152906001019060200180831161018057829003601f168201915b505050505090505b90565b604080516020810190915260008152905600a165627a7a72305820da570cb755561def0ccbb0f3c265ec5dd9dd5aeaca595bf15ff4a3673d9d2e8d0029",
    info: {
      abiDefinition: [{...}, {...}, {...}],
      compilerOptions: "--combined-json bin,abi,userdoc,devdoc --add-std --optimize",
      compilerVersion: "0.4.9",
      developerDoc: {
        methods: {...},
        title: "Greeter."
      },
      language: "Solidity",
      languageVersion: "0.4.9",
      source: "pragma solidity ^0.4.9; /** @title Mortal.*/ contract mortal { /* Define variable owner of the type address*/ address owner; /**@dev this function is executed at initialization and sets the owner of the contract. */ function mortal() { owner = msg.sender; } /**@dev Function to recover the funds on the contract. */ function kill() { if (msg.sender == owner) { selfdestruct(owner); } } } /** @title Greeter.*/ contract greeter is mortal { /* define variable greeting of the type string */ string greeting; /**@dev This function runs when the contract is executed. * @param _greeting Greeting message. */ function greeter(string _greeting) public { greeting = _greeting; } /* main function */ /**@dev This function returns the greeting message. * @return greeting The greeting message. */ function greet() constant returns (string) { return greeting; } }",
      userDoc: {
        methods: {}
      }
    }
  },
  <stdin>:mortal: {
    code: "0x6060604052341561000c57fe5b5b60008054600160a060020a03191633600160a060020a03161790555b5b609c806100386000396000f300606060405263ffffffff60e060020a60003504166341c0e1b581146020575bfe5b3415602757fe5b602d602f565b005b6000543373ffffffffffffffffffffffffffffffffffffffff90811691161415606d5760005473ffffffffffffffffffffffffffffffffffffffff16ff5b5b5600a165627a7a723058200a9fb13e0c7088d8b8834e9dacd090047f7173bbd4b22b8a2c06a00681b5631d0029",
    info: {
      abiDefinition: [{...}, {...}],
      compilerOptions: "--combined-json bin,abi,userdoc,devdoc --add-std --optimize",
      compilerVersion: "0.4.9",
      developerDoc: {
        methods: {...},
        title: "Mortal."
      },
      language: "Solidity",
      languageVersion: "0.4.9",
      source: "pragma solidity ^0.4.9; /** @title Mortal.*/ contract mortal { /* Define variable owner of the type address*/ address owner; /**@dev this function is executed at initialization and sets the owner of the contract. */ function mortal() { owner = msg.sender; } /**@dev Function to recover the funds on the contract. */ function kill() { if (msg.sender == owner) { selfdestruct(owner); } } } /** @title Greeter.*/ contract greeter is mortal { /* define variable greeting of the type string */ string greeting; /**@dev This function runs when the contract is executed. * @param _greeting Greeting message. */ function greeter(string _greeting) public { greeting = _greeting; } /* main function */ /**@dev This function returns the greeting message. * @return greeting The greeting message. */ function greet() constant returns (string) { return greeting; } }",
      userDoc: {
        methods: {}
      }
    }
  }
}

Luego defino la variable de entrada:

var _greeting = "Hello World!";

Luego creo el contrato:

var greeterContract = web3.eth.contract(greeterCompiled["<stdin>:greeter"].info.abiDefinition);

El resultado es:

    {
  <stdin>:greeter: {
    code: "0x6060604052341561000c57fe5b6040516102f03803806102f0833981016040528051015b5b60008054600160a060020a03191633600160a060020a03161790555b805161005390600190602084019061005b565b505b506100fb565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061009c57805160ff19168380011785556100c9565b828001600101855582156100c9579182015b828111156100c95782518255916020019190600101906100ae565b5b506100d69291506100da565b5090565b6100f891905b808211156100d657600081556001016100e0565b5090565b90565b6101e68061010a6000396000f300606060405263ffffffff60e060020a60003504166341c0e1b5811461002c578063cfae32171461003e575bfe5b341561003457fe5b61003c6100ce565b005b341561004657fe5b61004e610110565b604080516020808252835181830152835191928392908301918501908083838215610094575b80518252602083111561009457601f199092019160209182019101610074565b505050905090810190601f1680156100c05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6000543373ffffffffffffffffffffffffffffffffffffffff9081169116141561010d5760005473ffffffffffffffffffffffffffffffffffffffff16ff5b5b565b6101186101a8565b60018054604080516020600284861615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561019d5780601f106101725761010080835404028352916020019161019d565b820191906000526020600020905b81548152906001019060200180831161018057829003601f168201915b505050505090505b90565b604080516020810190915260008152905600a165627a7a72305820da570cb755561def0ccbb0f3c265ec5dd9dd5aeaca595bf15ff4a3673d9d2e8d0029",
    info: {
      abiDefinition: [{...}, {...}, {...}],
      compilerOptions: "--combined-json bin,abi,userdoc,devdoc --add-std --optimize",
      compilerVersion: "0.4.9",
      developerDoc: {
        methods: {...},
        title: "Greeter."
      },
      language: "Solidity",
      languageVersion: "0.4.9",
      source: "pragma solidity ^0.4.9; /** @title Mortal.*/ contract mortal { /* Define variable owner of the type address*/ address owner; /**@dev this function is executed at initialization and sets the owner of the contract. */ function mortal() { owner = msg.sender; } /**@dev Function to recover the funds on the contract. */ function kill() { if (msg.sender == owner) { selfdestruct(owner); } } } /** @title Greeter.*/ contract greeter is mortal { /* define variable greeting of the type string */ string greeting; /**@dev This function runs when the contract is executed. * @param _greeting Greeting message. */ function greeter(string _greeting) public { greeting = _greeting; } /* main function */ /**@dev This function returns the greeting message. * @return greeting The greeting message. */ function greet() constant returns (string) { return greeting; } }",
      userDoc: {
        methods: {}
      }
    }
  },
  <stdin>:mortal: {
    code: "0x6060604052341561000c57fe5b5b60008054600160a060020a03191633600160a060020a03161790555b5b609c806100386000396000f300606060405263ffffffff60e060020a60003504166341c0e1b581146020575bfe5b3415602757fe5b602d602f565b005b6000543373ffffffffffffffffffffffffffffffffffffffff90811691161415606d5760005473ffffffffffffffffffffffffffffffffffffffff16ff5b5b5600a165627a7a723058200a9fb13e0c7088d8b8834e9dacd090047f7173bbd4b22b8a2c06a00681b5631d0029",
    info: {
      abiDefinition: [{...}, {...}],
      compilerOptions: "--combined-json bin,abi,userdoc,devdoc --add-std --optimize",
      compilerVersion: "0.4.9",
      developerDoc: {
        methods: {...},
        title: "Mortal."
      },
      language: "Solidity",
      languageVersion: "0.4.9",
      source: "pragma solidity ^0.4.9; /** @title Mortal.*/ contract mortal { /* Define variable owner of the type address*/ address owner; /**@dev this function is executed at initialization and sets the owner of the contract. */ function mortal() { owner = msg.sender; } /**@dev Function to recover the funds on the contract. */ function kill() { if (msg.sender == owner) { selfdestruct(owner); } } } /** @title Greeter.*/ contract greeter is mortal { /* define variable greeting of the type string */ string greeting; /**@dev This function runs when the contract is executed. * @param _greeting Greeting message. */ function greeter(string _greeting) public { greeting = _greeting; } /* main function */ /**@dev This function returns the greeting message. * @return greeting The greeting message. */ function greet() constant returns (string) { return greeting; } }",
      userDoc: {
        methods: {}
      }
    }
  }
}
> ^C
> var _greeting = "Hello World!";
undefined
> var greeterContract = web3.eth.contract(greeterCompiled["<stdin>:greeter"].info.abiDefinition);
undefined
> greeterContract
{
  abi: [{
      constant: false,
      inputs: [],
      name: "kill",
      outputs: [],
      payable: false,
      type: "function"
  }, {
      constant: true,
      inputs: [],
      name: "greet",
      outputs: [{...}],
      payable: false,
      type: "function"
  }, {
      inputs: [{...}],
      payable: false,
      type: "constructor"
  }],
  eth: {
    accounts: ["0xd44470753171e1b22dc9e5ffd9ac50e0427f49ca", "0x7dc65a6db5de74ace26ab27dd822dab0fcb36851"],
    blockNumber: 15544,
    coinbase: "0xd44470753171e1b22dc9e5ffd9ac50e0427f49ca",
    compile: {
      lll: function(),
      serpent: function(),
      solidity: function()
    },
    defaultAccount: undefined,
    defaultBlock: "latest",
    gasPrice: 20000000000,
    hashrate: 0,
    mining: false,
    pendingTransactions: [],
    protocolVersion: "0x3f",
    syncing: false,
    call: function(),
    contract: function(abi),
    estimateGas: function(),
    filter: function(fil, callback),
    getAccounts: function(callback),
    getBalance: function(),
    getBlock: function(),
    getBlockNumber: function(callback),
    getBlockTransactionCount: function(),
    getBlockUncleCount: function(),
    getCode: function(),
    getCoinbase: function(callback),
    getCompilers: function(),
    getGasPrice: function(callback),
    getHashrate: function(callback),
    getMining: function(callback),
    getPendingTransactions: function(callback),
    getProtocolVersion: function(callback),
    getRawTransaction: function(),
    getRawTransactionFromBlock: function(),
    getStorageAt: function(),
    getSyncing: function(callback),
    getTransaction: function(),
    getTransactionCount: function(),
    getTransactionFromBlock: function(),
    getTransactionReceipt: function(),
    getUncle: function(),
    getWork: function(),
    iban: function(iban),
    icapNamereg: function(),
    isSyncing: function(callback),
    namereg: function(),
    resend: function(),
    sendIBANTransaction: function(),
    sendRawTransaction: function(),
    sendTransaction: function(),
    sign: function(),
    signTransaction: function(),
    submitTransaction: function(),
    submitWork: function()
  },
  at: function(address, callback),
  getData: function(),
  new: function()
}

Ahora quiero implementar el contrato:

var greeter = greeterContract.new(_greeting,{from:web3.eth.accounts[1], data: greeterCompiled["<stdin>:greeter"].code, gas: 45000000000}, function(e, contract){ if(!e) { if(!contract.address) { console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined..."); } else { console.log("Contract mined! Address: " + contract.address); console.log(contract); } } })

El resultado es:

    {
  abi: [{
      constant: false,
      inputs: [],
      name: "kill",
      outputs: [],
      payable: false,
      type: "function"
  }, {
      constant: true,
      inputs: [],
      name: "greet",
      outputs: [{...}],
      payable: false,
      type: "function"
  }, {
      inputs: [{...}],
      payable: false,
      type: "constructor"
  }],
  address: undefined,
  transactionHash: null
}

Como puede ver, debería haber suficiente gas incluido. Pero luego no pasa nada y no se le asignará ninguna dirección. También el saldo de la cuenta sigue siendo el mismo. ¿No estoy conectado correctamente (cuando ejecuto admin.peers veo todos los demás nodos conectados) o cuál podría ser el problema?

espere un poco más: la devolución de llamada debe llamarse una vez más con la dirección de la instancia.
Esperé ahora durante una hora y no pasó nada... No hubo devolución de llamada ni registro en absoluto -> solo indefinido como salida inmediata y luego pude usar la consola inmediatamente después nuevamente. ¿Cual podría ser el problema?
¿Es una red privada? ¿Hay algún nodo de minería en él?
Sí, es una red privada implementada en Azure (a través de una plantilla que está disponible allí). Hay nodos de minería y se están ejecutando.
Eh, me temo que mi conocimiento es muy poco para ayudarte :(

Respuestas (1)

Ahora hay una solución (gracias a un colega que me ayudó a resolver esto :) pero de alguna manera no me satisface porque no sé exactamente por qué funciona ahora y no antes.

Mi colega usó un valor de gas diferente (1000000 en lugar de 45000000000) y tuvo que quitar el web3devar greeter = greeterContract.new(_greeting,{from:web3.eth.accounts[1], ...

Solo tuve que cambiar el valor del gas pero puedo usar web3...

Entonces, el código que funciona ahora para mí se ve así:

var greeter = greeterContract.new(_greeting,{from:web3.eth.accounts[1], data: greeterCompiled["<stdin>:greeter"].code, gas: 1000000}, function(e, contract){
    if(!e) {
        if(!contract.address) {
            console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined...");
        } else {
            console.log("Contract mined! Address: " + contract.address);
            console.log(contract);
        }
    }
})

y para mi colega

var greeter = greeterContract.new(_greeting,{from:eth.accounts[1], data: greeterCompiled["<stdin>:greeter"].code, gas: 1000000}, function(e, contract){
    if(!e) {
        if(!contract.address) {
            console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined...");
        } else {
            console.log("Contract mined! Address: " + contract.address);
            console.log(contract);
        }
    }
})