Solidity

如何在不使用 Browser Solidity 等圖形使用者界面的情況下參考庫合約部署合約?

  • January 3, 2017

由於庫合約方法失敗 #2831問題,我正在使用 Solidity 瀏覽器部署合約。在以下答案https://ethereum.stackexchange.com/a/9181/4575我已指導使用 Solidity Browser 作為(請注意,此解決方案有效。):

我通過點擊塊圖示並選擇 Web3 Provider 將 Solidity Browser 連接到我的本地私有節點。然後我點擊創建將上面的合約部署到區塊鏈。

我在我的伺服器上使用 Solidity Browser,由於我的 ssh 連接,很難使用圖形使用者界面執行此過程。

$$ Q $$是否可以通過 Solidity 瀏覽器在不使用圖形使用者界面的情況下部署合約?還是有其他解決方案? 感謝您寶貴的時間和幫助。

概括

要使用 部署您的庫和合約程式碼geth,您必須:

  1. 部署您的LinkedList庫程式碼並記下它部署到的地址。
  2. 將程式碼中的__LinkedList___...___文本替換為部署地址並部署程式碼。Array``LinkedLibrary

其他一些選擇:

  1. 在遠端伺服器和本地電腦之間創建一個 SSH 隧道,以便您可以geth從本地電腦訪問遠端伺服器的 RPC 埠。然後使用本地電腦上的 Browser Solidity 連接到本地電腦埠,該埠是遠端伺服器gethRPC 埠的代理 - 請參閱如何將 Geth 的 RPC 伺服器公開給外部連接?
  2. 將本地機器的geth實例設置為遠端伺服器geth實例的對等點。然後,您可以使用 Browser Solidity 與本地電腦的geth實例進行互動,您的操作將被鏡像到您的遠端伺服器上。請參閱在專用網路上的節點之間失去連接並在此站點上搜尋專用網路。

使用下面評論中提供的原始碼進行更新

以下是來自下面連結的原始碼,除了pragma語句和添加constanttest_callstack()函式中外,未更改:

library LinkedList {
 uint80 constant None = uint80(0); // NULL.

 struct data {
   uint256 head;
   Node[100]  n;
   uint    size;
   uint    insert_number;
   uint    buffer_size;
 }

 struct Node {
   string  data;
   address owner;
   uint    own;
   uint    prev;
   uint    next;
 }

 function construct_me(data storage self){
   self.n[0].own      = 0;
   self.n[0].next     = 0;
   self.n[0].prev     = 0;
   self.head          = 0;

   self.insert_number = self.size = 1;

   self.buffer_size   = 100;
 }
}

contract owned {
 address  public owner;
 function owned() {
   owner = msg.sender;
 }
 function ownerOnly() {
   if (msg.sender != owner) throw;
 }
 modifier onlyOwner {
    if (msg.sender != owner) throw;
         _;
 }
 function transferOwnership(address newOwner) onlyOwner {
   owner = newOwner;
 }
}

contract Array is owned {
 using LinkedList for LinkedList.data;
 using LinkedList for LinkedList.Node;
 LinkedList.data list;

 function Array(){
   if( test_callstack() != 1 ) throw;
   list.construct_me();
 }

 function test_callstack() constant returns ( int ){ return 1; }
}

我已將上面的原始碼保存到Contract.sol.

我使用以下語句將扁平原始碼分配給變數(參考https://ethereum.stackexchange.com/a/2610/1268):

Iota:DeployLibrary user$ echo "var myContractSource='`$HOME/bin/stripCrLf Contract.sol`'"
var myContractSource="library LinkedList { uint80 constant None = uint80(0);  struct data { uint256 head;  Node[100] n;  uint size; uint insert_number; uint buffer_size; } struct Node { string data;  address owner;  uint own;  uint prev; uint next;  } function construct_me(data storage self){  self.n[0].own = 0; self.n[0].next = 0; self.n[0].prev = 0; self.head = 0; self.insert_number = self.size = 1;  self.buffer_size = 100; }}contract owned {  address public owner; function owned() { owner = msg.sender; } function ownerOnly() { if (msg.sender != owner) throw; } modifier onlyOwner { if (msg.sender != owner) throw; _; } function transferOwnership(address newOwner) onlyOwner { owner = newOwner; }}contract Array is owned { using LinkedList for LinkedList.data; using LinkedList for LinkedList.Node; LinkedList.data list; function Array(){  if( test_callstack() != 1 ) throw;  list.construct_me(); } function test_callstack() constant returns ( int ){ return 1; }}"

我將上面的行複製到剪貼板並將其粘貼到--devgeth 實例中:

> var myContractSource="library LinkedList { uint80 constant None = uint80(0);  struct data { uint256 head;  Node[100] n;  uint size; uint insert_number; uint buffer_size; } struct Node { string data;  address owner;  uint own;  uint prev; uint next;  } function construct_me(data storage self){  self.n[0].own = 0; self.n[0].next = 0; self.n[0].prev = 0; self.head = 0; self.insert_number = self.size = 1;  self.buffer_size = 100; }}contract owned {  address public owner; function owned() { owner = msg.sender; } function ownerOnly() { if (msg.sender != owner) throw; } modifier onlyOwner { if (msg.sender != owner) throw; _; } function transferOwnership(address newOwner) onlyOwner { owner = newOwner; }}contract Array is owned { using LinkedList for LinkedList.data; using LinkedList for LinkedList.Node; LinkedList.data list; function Array(){  if( test_callstack() != 1 ) throw;  list.construct_me(); } function test_callstack() constant returns ( int ){ return 1; }}"
undefined

我編譯了原始碼:

> var myContractCompiled=web3.eth.compile.solidity(myContractSource);
undefined

要檢查可用的 ABI,我鍵入以下內容:

> myContractCompiled
myContractCompiled
{
 Array: {
   code: "0x6060604081905260008054600160a060020a0319166c01000000000000000000000000338102041781557f14ea1cf8000000000000000000000000000000000000000000000000000000008252600160645273__LinkedList____________________________916314ea1cf89160849160248186803b1560025760325a03f41560025750505060fd806100936000396000f3606060405260e060020a60003504631309238c8114603a578063896f40dd1460525780638da5cb5b146071578063f2fde38b146086575b6002565b34600257600160408051918252519081900360200190f35b3460025760a860005433600160a060020a0390811691161460c6576002565b3460025760aa600054600160a060020a031681565b3460025760a860043560005433600160a060020a0390811691161460c8576002565b005b60408051600160a060020a039092168252519081900360200190f35b565b600080546c010000000000000000000000008084020473ffffffffffffffffffffffffffffffffffffffff199091161790555056",
   info: {
     abiDefinition: [{...}, {...}, {...}, {...}, {...}],
     compilerOptions: "--combined-json bin,abi,userdoc,devdoc --add-std --optimize",
     compilerVersion: "0.4.4",
     developerDoc: {
       methods: {}
     },
     language: "Solidity",
     languageVersion: "0.4.4",
     source: "library LinkedList { uint80 constant None = uint80(0);  struct data { uint256 head;  Node[100] n;  uint size; uint insert_number; uint buffer_size; } struct Node { string data;  address owner;  uint own;  uint prev; uint next;  } function construct_me(data storage self){  self.n[0].own = 0; self.n[0].next = 0; self.n[0].prev = 0; self.head = 0; self.insert_number = self.size = 1;  self.buffer_size = 100; }}contract owned {  address public owner; function owned() { owner = msg.sender; } function ownerOnly() { if (msg.sender != owner) throw; } modifier onlyOwner { if (msg.sender != owner) throw; _; } function transferOwnership(address newOwner) onlyOwner { owner = newOwner; }}contract Array is owned { using LinkedList for LinkedList.data; using LinkedList for LinkedList.Node; LinkedList.data list; function Array(){  if( test_callstack() != 1 ) throw;  list.construct_me(); } function test_callstack() constant returns ( int ){ return 1; }}",
     userDoc: {
       methods: {}
     }
   }
 },
 LinkedList: {
   code: "0x6060604052605c8060106000396000f36504044633f3de50606060405260e060020a600035046314ea1cf881146024575b6007565b600060036004803591820183905560058201839055810182905590815560016101f582018190556101f682015560646101f79091015500",
   info: {
     abiDefinition: [{...}],
     compilerOptions: "--combined-json bin,abi,userdoc,devdoc --add-std --optimize",
     compilerVersion: "0.4.4",
     developerDoc: {
       methods: {}
     },
     language: "Solidity",
     languageVersion: "0.4.4",
     source: "library LinkedList { uint80 constant None = uint80(0);  struct data { uint256 head;  Node[100] n;  uint size; uint insert_number; uint buffer_size; } struct Node { string data;  address owner;  uint own;  uint prev; uint next;  } function construct_me(data storage self){  self.n[0].own = 0; self.n[0].next = 0; self.n[0].prev = 0; self.head = 0; self.insert_number = self.size = 1;  self.buffer_size = 100; }}contract owned {  address public owner; function owned() { owner = msg.sender; } function ownerOnly() { if (msg.sender != owner) throw; } modifier onlyOwner { if (msg.sender != owner) throw; _; } function transferOwnership(address newOwner) onlyOwner { owner = newOwner; }}contract Array is owned { using LinkedList for LinkedList.data; using LinkedList for LinkedList.Node; LinkedList.data list; function Array(){  if( test_callstack() != 1 ) throw;  list.construct_me(); } function test_callstack() constant returns ( int ){ return 1; }}",
     userDoc: {
       methods: {}
     }
   }
 },
 owned: {
   code: "0x6060604052600080546c0100000000000000000000000033810204600160a060020a031990911617905560db806100366000396000f3606060405260e060020a6000350463896f40dd811460305780638da5cb5b14604f578063f2fde38b146064575b6002565b34600257608660005433600160a060020a0390811691161460a4576002565b346002576088600054600160a060020a031681565b34600257608660043560005433600160a060020a0390811691161460a6576002565b005b60408051600160a060020a039092168252519081900360200190f35b565b600080546c010000000000000000000000008084020473ffffffffffffffffffffffffffffffffffffffff199091161790555056",
   info: {
     abiDefinition: [{...}, {...}, {...}, {...}],
     compilerOptions: "--combined-json bin,abi,userdoc,devdoc --add-std --optimize",
     compilerVersion: "0.4.4",
     developerDoc: {
       methods: {}
     },
     language: "Solidity",
     languageVersion: "0.4.4",
     source: "library LinkedList { uint80 constant None = uint80(0);  struct data { uint256 head;  Node[100] n;  uint size; uint insert_number; uint buffer_size; } struct Node { string data;  address owner;  uint own;  uint prev; uint next;  } function construct_me(data storage self){  self.n[0].own = 0; self.n[0].next = 0; self.n[0].prev = 0; self.head = 0; self.insert_number = self.size = 1;  self.buffer_size = 100; }}contract owned {  address public owner; function owned() { owner = msg.sender; } function ownerOnly() { if (msg.sender != owner) throw; } modifier onlyOwner { if (msg.sender != owner) throw; _; } function transferOwnership(address newOwner) onlyOwner { owner = newOwner; }}contract Array is owned { using LinkedList for LinkedList.data; using LinkedList for LinkedList.Node; LinkedList.data list; function Array(){  if( test_callstack() != 1 ) throw;  list.construct_me(); } function test_callstack() constant returns ( int ){ return 1; }}",
     userDoc: {
       methods: {}
     }
   }
 }
}

注意myContractCompiled.Array.code包含文本__LinkedList__...___。這將需要替換為已部署庫的地址(不帶0x前綴) 。LinkedList

部署LinkedList庫:

> var myLinkedListLib = web3.eth.contract(myContractCompiled.LinkedList.info.abiDefinition);
undefined
> var linkedListLib = myLinkedListLib.new({
   from:web3.eth.accounts[0],
   data: myContractCompiled.LinkedList.code, gas: 400000},
   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);
       }
   }
})
Contract transaction send: TransactionHash: 0x420908d8f22649542d532f256dff3ae5a7b473c68c68274d8c83ba9539f6d0e1 waiting to be mined...
Contract mined! Address: 0xc6fa3b899c8840585e706f90d1e43c7229cf9d5d

讓我們檢查一下使用的氣體:

> eth.getTransactionReceipt("0x420908d8f22649542d532f256dff3ae5a7b473c68c68274d8c83ba9539f6d0e1")
{
 blockHash: "0xff0ba9946211a9d3b0824e5758d148334ef1de6689c8fba70916e52bd35e2167",
 blockNumber: 2370,
 contractAddress: "0xc6fa3b899c8840585e706f90d1e43c7229cf9d5d",
 cumulativeGasUsed: 78469,
 from: "0x000d1009bd8f0b1301cc5edc28ed1222a3ce671e",
 gasUsed: 78469,
 logs: [],
 logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
 root: "0x9c7f63caedfd133826622a2872907fc52ede05cc9c0b644bfadf92bcfa5aaed5",
 to: null,
 transactionHash: "0x420908d8f22649542d532f256dff3ae5a7b473c68c68274d8c83ba9539f6d0e1",
 transactionIndex: 0
}

將 Array 合約程式碼中的文本替換__LinkedList__*為上述地址。

> var arrayCode = myContractCompiled.Array.code.replace(/__LinkedList__+/g, "c6fa3b899c8840585e706f90d1e43c7229cf9d5d")
undefined
> arrayCode
"0x6060604081905260008054600160a060020a0319166c01000000000000000000000000338102041781557f14ea1cf8000000000000000000000000000000000000000000000000000000008252600160645273c6fa3b899c8840585e706f90d1e43c7229cf9d5d916314ea1cf89160849160248186803b1560025760325a03f41560025750505060fd806100936000396000f3606060405260e060020a60003504631309238c8114603a578063896f40dd1460525780638da5cb5b146071578063f2fde38b146086575b6002565b34600257600160408051918252519081900360200190f35b3460025760a860005433600160a060020a0390811691161460c6576002565b3460025760aa600054600160a060020a031681565b3460025760a860043560005433600160a060020a0390811691161460c8576002565b005b60408051600160a060020a039092168252519081900360200190f35b565b600080546c010000000000000000000000008084020473ffffffffffffffffffffffffffffffffffffffff199091161790555056"

Array使用修改後的程式碼進行部署:

> var myArray = web3.eth.contract(myContractCompiled.Array.info.abiDefinition);
undefined
> var array = myArray.new({
   from:web3.eth.accounts[0],
   data: arrayCode, gas: 400000},
   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);
       }
   }
})
Contract transaction send: TransactionHash: 0x2652d322915ec6f3668a701b5ef41c09cf5aa93de0fd7c18f8de9250a9811505 waiting to be mined...
undefined
...
Contract mined! Address: 0x036a55eb6419b503692eeedd3c446f9252642001

I0103 19:47:37.967249 miner/worker.go:516] commit new work on block 1504 with 1 txs & 0 uncles. Took 4.177908ms
...
> eth.getTransactionReceipt("0x2652d322915ec6f3668a701b5ef41c09cf5aa93de0fd7c18f8de9250a9811505")
{
 blockHash: "0xb6da4bcb8349333f023ed9fc41c47275e27bd1cc446c130842ee8eda51323ee9",
 blockNumber: 2429,
 contractAddress: "0x036a55eb6419b503692eeedd3c446f9252642001",
 cumulativeGasUsed: 227373,
 from: "0x000d1009bd8f0b1301cc5edc28ed1222a3ce671e",
 gasUsed: 227373,
 logs: [],
 logsBloom: "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
 root: "0x4fe08613be0eb3475f25cec740b723d8124161bc36093cf2064543ef3e6cdd45",
 to: null,
 transactionHash: "0x2652d322915ec6f3668a701b5ef41c09cf5aa93de0fd7c18f8de9250a9811505",
 transactionIndex: 0
}

讓我們測試你的功能:

> array.test_callstack()
1

注意:如果您將庫呼叫合約部署到私有/開發網路,上述程式碼需要homesteadBlock在您的配置中指定- 請參閱如何從合約呼叫庫函式?=>genesis.json$$ error $$合約程式碼無法儲存,請檢查您的gas量。未定義

引用自:https://ethereum.stackexchange.com/questions/11030