如何在不使用 Browser Solidity 等圖形使用者界面的情況下參考庫合約部署合約?
由於庫合約方法失敗 #2831問題,我正在使用 Solidity 瀏覽器部署合約。在以下答案https://ethereum.stackexchange.com/a/9181/4575我已指導使用 Solidity Browser 作為(請注意,此解決方案有效。):
我通過點擊塊圖示並選擇 Web3 Provider 將 Solidity Browser 連接到我的本地私有節點。然後我點擊創建將上面的合約部署到區塊鏈。
我在我的伺服器上使用 Solidity Browser,由於我的 ssh 連接,很難使用圖形使用者界面執行此過程。
$$ Q $$是否可以通過 Solidity 瀏覽器在不使用圖形使用者界面的情況下部署合約?還是有其他解決方案? 感謝您寶貴的時間和幫助。
概括
要使用 部署您的庫和合約程式碼
geth
,您必須:
- 部署您的
LinkedList
庫程式碼並記下它部署到的地址。- 將程式碼中的
__LinkedList___...___
文本替換為部署地址並部署程式碼。Array``LinkedLibrary
其他一些選擇:
- 在遠端伺服器和本地電腦之間創建一個 SSH 隧道,以便您可以
geth
從本地電腦訪問遠端伺服器的 RPC 埠。然後使用本地電腦上的 Browser Solidity 連接到本地電腦埠,該埠是遠端伺服器geth
RPC 埠的代理 - 請參閱如何將 Geth 的 RPC 伺服器公開給外部連接?- 將本地機器的
geth
實例設置為遠端伺服器geth
實例的對等點。然後,您可以使用 Browser Solidity 與本地電腦的geth
實例進行互動,您的操作將被鏡像到您的遠端伺服器上。請參閱在專用網路上的節點之間失去連接並在此站點上搜尋專用網路。使用下面評論中提供的原始碼進行更新
以下是來自下面連結的原始碼,除了
pragma
語句和添加constant
到test_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; }}"
我將上面的行複製到剪貼板並將其粘貼到
--dev
geth 實例中:> 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量。未定義。