解決部署合約 insufficient funds for gas * price + value 問題

當我在建置完geth客戶端私有鏈後,想要把truffle範例中的Metacoin部署上去,卻出現了以下的問題:

在genesis.json中定義的gasLimit是8000000,而現在的gasprice可以透過javascript console內的指令eth.gasPrice來查詢,得到如下圖結果:

解決辦法

如果是在私有鏈的情況下,可以透過在geth指令後方加上--miner.gasprice '0' 來解決這個問題。 加上此flag後再重啟客戶端,透過eth.gasPrice指令查詢,此時gasPrice變成0了!當然也就不會有insufficient funds的問題。

解決 5432 port 被PostgreSQL 佔用問題

當我在使用Docker啟用postgreSQL建置資料庫時,遇到了5432這個port被佔用的問題 (Ports are not available: listen tcp 0.0.0.0:5432: bind: address already in use) 按照官網說明使用:

brew remove postgresql

之後,如果port還是被佔用的狀態,先用下面指令確認 port 5432 被佔用的狀況:

sudo lsof -i TCP:5432

我的Mac是出現以下畫面

輸入下列指令

sudo pkill -u postgres

再確認一次應該就可以了!

刪除 git 陰魂不散的 DS.Store

於terminal輸入:

find . -name .DS_Store -print0 | xargs -0 git rm -f --ignore-unmatch

輸入以下指令將.DS_Store加入.gitignore

echo .DS_Store >> .gitignore

commit .gitignore file

git add .gitignore
git commit -m '.DS_Store banished!'

資料來源

區塊鏈生存指南 讀書紀錄


書籍這裡買:天瓏博客來

  • 區塊鏈使用私鑰加密交易紀錄,節點用公鑰解密–>數位簽章,公鑰即像亂碼的錢包地址
  • 主流公鏈如比特幣、以太坊的非對稱式加密透過橢圓公式ECC
  • 區塊鏈的不可能三角:去中心化、安全、效能,只能三取二
  • CBC是區塊鏈的前身!!區塊鏈因為鏈會分岔,所以也有重放攻擊,藉由讓鏈有獨立ID避免此問題

主流鏈

Bitcoin

“Be your own bank”

  • 發明者中本聰
  • 節點要挖礦也要接收外部請求,中本聰一開始也是以socket & thread 完成資料的接收與處理,一個thread 處理socket的連接,另一個處理接收後的資訊
  • 區塊容量上限 1MB –> 3.3-7 TPS(transaction per seconds), visa : 1700 TPS
  • 每2016個block調整一次difficulty,盡量10分鐘出一個block
  • BIP
    • Bitcoin的改善協議
  • UXTO(Unspent Transaction Output) 架構–>用支票的方式交易
    • 每一張支票只能被使用一次–>可對抗雙花攻擊
    • 帳戶目前餘額:所有持有UXTO的金額總和
    • 優點:擴充性佳、隱私性提升
  • 三次重大版本更新
    1. 多重簽名 Pay to Multi Signature(P2MS)/Pay to Script Hash(P2SH)
    2. 隔離驗證(Segregaed Witness, Segwit) 可以提升兩倍交易量,擴充區塊大小其實也可以,但區塊大傳播慢
    3. 閃電網路(Lightning Network)
      • 鏈下擴容,微小的支付並不會馬上上鏈,而是去鏈上開閃電支付的通道,接著到鏈下把牽過的交易資訊給對方,等到要結算再統一上鏈
      • 只要與閃電網路任何一個節點開啟支付通道,那就可以與節點連接的所有閃電網路進行無延遲無手續費的交易
      • 要先抵押資產,就像要刷悠遊卡之前要先儲值

Ethereum

  • 具圖靈完備性
  • 用Gas機制限制運算量、手續費,手續費上限=Gas Limit*Gas Price
    • Gas
    • Gas Price:願意為每個Gas付多少錢(Gwei)
    • Gas Limit:願意為了這筆交易買多少Gas
  • 每個區塊的Gas上限:800萬Gas,誰出的Gas Price高,礦工就販售位置給誰,所以出的Gas Price越高,交易越快被打包進區塊。
  • 約15秒出一次塊
  • EIP
    • Ethereum的改善協議
    • 以太坊基金會開發維護,會基於EIP發出相對應的ERC讓大家討論 ex.ERC20
  • Account 架構–>像是銀行簽帳卡
    • 每筆交易都有一個遞增的nonce值,值越小越優先執行–>避免雙花攻擊
    • 優點:簡單、效率,不用產生額外UXTO

共識

拜占庭將軍問題

整個Bitcoin全節點可以視作一種純P2P網路,為了保持各個節點間資料一致性,傳播資料要考慮有假造的節點,如何確保資料同步、一致性,形成共識?–>要對抗女巫攻擊(惡意使壞的節點)

  • 問題背景: 有很多將軍,要投票達成一致策略,要撤離或是要進攻城市,投票過程每位將軍要把自己的決定通知給其他所有將軍,總計自己的決定和收到的其他將軍的決定,就可以推算出共同結果。 但將軍裡可能有叛徒,會有以下問題
    1. 故意投不好的策略、不照最後決定行動
    2. 假其他將軍之名傳假訊息給別人
    3. 送信的信使被攔截

證明自己有廣播/投票權利

  • 工作量證明 POW(Proof Of Work)
    • 手中必須持有運算力,不斷找nonce
    • 缺點:區塊鏈發展被礦池把持
  • 權益證明 POS(Proof Of Stake)
    • 持幣越多,越有權力去廣播與投票

實用拜占庭容錯(PBFT)

考慮視域變化(view-change),分為三階段:

  1. pre-prepare
  2. prepare
  3. commit

分岔

有時候分岔不是因為技術、惡意節點、駭客,而是因為社群意見的分裂。

  • 暫時性分岔 因為網路延遲造成短時間不同步的現象
    • 孤兒塊Orphan Block : 鏈長較短被捨棄的區塊、交易不算、沒獎勵
    • Ethereum因為出塊時間比較短,會產生的孤兒塊也比較多,所以改用叔塊機制
    • 叔塊Uncle Block : 必須在出現暫時性分岔後的六代內被納進主鏈,間隔越多代,出塊獎勵越少

以下兩種跟軟體升級、程式碼或協定更動有關

  • 軟分岔 Soft Fork
    • 更新完還是可以接受與過去版本間形成部分的共識–>向後相容
    • 新舊版本可以共存同個鏈
    • 以功能的更新居多
  • 硬分岔 Hard Fork
    • 更新後完全無法與舊版本形成共識
    • 新舊版本不可共存於同個鏈上
    • 通常是共識規則的更新
      • 舊版本無法驗證新版本下產生的區塊
    • Ex. Ethereum Classic(ETC) 自 Ethereum 分岔出 Bitcoin Cash(BCH) 自 Bitcoin 分岔出

隱藏交易細節

零知識證明

  • 不提供任何有關訊息的資料,仍可以說服對方該筆訊息是正確的
  • 不讓礦工知道所有交易明細,但要說服對方這筆交易合法合規
  • 核心:同態隱藏 Homomorphic Hidings

主流匿蹤貨幣

  • ZEC
  • Monero(XMR)
  • Dash
    • 有master node機制,並非去中心化的(decentralized)

其他技術

  • Socket
    1. Stream socket (TCP)
    2. Datagram socket (UDP)

其他專有名詞

Initial Coin Offering(ICO) Initial Exchange Offering(IEO) Initial Fork Offering(IFO) Security Token Offering(STO)

網站

Solidity doc速讀筆記

Useful example

Style Guide 值得注意的地方

參考網址

  • the Solidity compiler encourages the use of machine-readable SPDX license identifiers(用來標示許可). Every source file should start with a comment indicating its license:
    // SPDX-License-Identifier: MIT
    

    State Variables

    Variables whose values are permanently stored in contract storage.

  • 可以被宣告成constantimmutable.
    • constant : The value has to be fixed at compile-time/ It is also possible to define constant variables at the file level.
    • immutable : It can still be assigned at construction time.

Value Type

  • bool : 包括constants true and false
  • Integer:int / unit
  • Fixed Point Numbers : fixed / ufixed
  • Address
    • address: Holds a 20 byte value (size of an Ethereum address).
    • address payable: Same as address, but with the additional members transfer and send.可以接收Ether.
    • 可做Implicit和Explicit conversion.參考
    • 如果計畫要接收Ether,最好一開始就宣告address payable
    • Members of Address Types
      • ex. balance and transfer
           address payable x = payable(0x123);
           address myAddress = address(this);
           if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10);
        
      • call, delegatecall and staticcall
    • 注意: All contracts can be converted to address type, so it is possible to query the balance of the current contract using address(this).balance.
  • Fixed-size byte arrays
    • The value types bytes1, bytes2, bytes3, …, bytes32 hold a sequence of bytes from one to up to 32.
    • Dynamically-sized byte array像是bytes,string Not a value-type!
  • String Literals and Types
    • They do not imply trailing zeroes as in C; “foo” represents three bytes, not four.
    • "foo" "bar" is equivalent to "foobar" –>遇到超長string的時候有用
  • enum
    • default:第一個成員
    • Using type(NameOfEnum).min and type(NameOfEnum).max you can get the smallest and respectively largest value of the given enum.
    • Enums can also be declared on the file level, outside of contract or library definitions.

Reference Types

  • Structs, Arrays and Mappings.
  • Use a reference type, you always have to explicitly provide the data area where the type is stored:
    • memory
    • storage
    • calldata  
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.9.0;

contract C {
    // The data location of x is storage.
    // This is the only place where the
    // data location can be omitted.
    uint[] x;

    // The data location of memoryArray is memory.
    function f(uint[] memory memoryArray) public {
        x = memoryArray; // works, copies the whole array to storage
        uint[] storage y = x; // works, assigns a pointer, data location of y is storage
        y[7]; // fine, returns the 8th element
        y.pop(); // fine, modifies x through y
        delete x; // fine, clears the array, also modifies y
        // The following does not work; it would need to create a new temporary /
        // unnamed array in storage, but storage is "statically" allocated:
        // y = memoryArray;
        // This does not work either, since it would "reset" the pointer, but there
        // is no sensible location it could point to.
        // delete y;
        g(x); // calls g, handing over a reference to x
        h(x); // calls h and creates an independent, temporary copy in memory
    }

    function g(uint[] storage) internal pure {}
    function h(uint[] memory) public pure {}
}

Arrays

  • An array of 5 dynamic arrays of uint is written as uint[][5] –> 和其他語言相反
    • 宣告 uint[][5] memory x 後 * access the seventh uint in the third dynamic array using x[2][6] * access the third dynamic array, usex[2]
  • X[3] is always an array containing three elements of type X, even if X is itself an array –> 和其他語言不同
  • Allocating Memory Arrays
    • uint[] memory a = new uint[](7);
    • As opposed to storage arrays, it is not possible to resize memory arrays (e.g. the .push member functions are not available)

Array Literals

  • 複雜
  • [1, 2, 3] is uint8[3] memory, because the type of each of these constants is uint8. If you want the result to be a uint[3] memory type, you need to convert the first element to uint. ex. [uint(1), 2, 3]
  • [1, -1] is invalid,因為第一個是uint8,而第二個是int8,應該寫成[int8(1), -1]
  • Fixed size memory arrays cannot be assigned to dynamically-sized memory arrays
    • uint[] memory x = [uint(1), 3, 4]; –>錯
    • 正確:分開assign值
        uint[] memory x = new uint[](3);
        x[0] = 1;
        x[1] = 3;
        x[2] = 4;
      

      Array Members

  • length
  • push()
  • push(x)
  • pop

Special array

  • bytes
  • string

Mapping Types

mapping(_KeyType => _ValueType) _VariableName
  • 可以想成hash table
  • the key data is not stored in a mapping, only its keccak256 hash is used to look up the value. 所以對key沒有長度的限制
  • The _KeyType can be any built-in value type, bytes, string, or any contract or enum type. Other user-defined or complex types, such as mappings, structs or array types are not allowed.
  • _ValueType can be any type, including mappings, arrays and structs.
  • You cannot iterate over mappings, i.e. you cannot enumerate their keys. 但可以自己實作

delete

  • delete a assigns the initial value for the type to a.
    uint x = data;
    delete x; // sets x to 0, does not affect data
    delete data; // sets data to 0, does not affect x
    uint[] storage y = dataArray;
    delete dataArray; // this sets dataArray.length to zero, but as uint[] is a complex object, also
    // y is affected which is an alias to the storage object
    // On the other hand: "delete y" is not valid, as assignments to local variables
    // referencing storage objects can only be made from existing storage objects.
    
  • 如果delete a[x],會刪除index x的element,造成array中間有個Gap.

Function Type

function (<parameter types>) {internal|external} [pure|constant|view|payable] [returns (<return types>)]
  • 預設:internal,所以internal external可省略
  • External (or public) functions 的members:
    • .address returns the address of the contract of the function.
    • .selector returns the ABI function selector
    • {gas: ...} and {value: ...} to specify the amount of gas or the amount of wei sent to a function, respectively.

Visibility and Getters

external

  • Part of the contract interface
  • means they can be called from other contracts and via transactions.
  • An external function f cannot be called internally (i.e. f() does not work, but this.f() works).

    public

  • Part of the contract interface
  • can be either called internally or via messages
  • For public state variables, an automatic getter function (see below) is generated.

    internal

  • can only be accessed internally (i.e. from within the current contract or contracts deriving from it),without using this.

    private

  • are only visible for the contract they are defined in and not in derived contracts.

    getter function

  • The compiler automatically creates getter functions for all public state variables.
  • The mapping and arrays (with the exception of byte arrays) in the struct are omitted because there is no good way to select individual struct members or provide a key for the mapping

State Mutability

view

Functions can be declared view in which case they promise not to modify the state. 下面行為被認為是 modifying the state:

  • Writing to state variables.
  • Emitting events.
  • Creating other contracts.
  • Using selfdestruct.
  • Sending Ether via calls.
  • Calling any function not marked view or pure.
  • Using low-level calls.
  • Using inline assembly that contains certain opcodes.

    pure

    Functions can be declared pure in which case they promise not to read from or modify the state. 下面行為被認為是reading from the state:

  • Reading from state variables.
  • Accessing address(this).balance or address.balance.
  • Accessing any of the members of block, tx, msg (with the exception of msg.sig and msg.data).
  • Calling any function not marked pure.
  • Using inline assembly that contains certain opcodes.

    payable

    讓函式可以接收以太幣 延伸閱讀

Special Functions

Receive Ether Function

  • 一個合約只能有一個receive function
  • 宣告使用 receive() external payable { ... } * 不用function keyword * 不能有arguments * 不能return東西 *一定要有external visibility and payable state mutability

    Fallback Function

  • 一個合約只能有一個fallback function
  • 宣告使用 fallback () external [payable] or fallback (bytes calldata _input) external [payable] returns (bytes memory _output) * 不用function keyword * 不能有arguments * 不能return東西 *一定要有external visibility

Error handling: Assert, Require, Revert and Exceptions

參考網址

  • The assert function creates an error of type Panic(uint256).
  • The require function either creates an error without any data or an error of type Error(string).
  • The revert statement takes a custom error as direct argument without parentheses: revert CustomError(arg1, arg2);

try/catch

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.1;

interface DataFeed { function getData(address token) external returns (uint value); }

contract FeedConsumer {
    DataFeed feed;
    uint errorCount;
    function rate(address token) public returns (uint value, bool success) {
        // Permanently disable the mechanism if there are
        // more than 10 errors.
        require(errorCount < 10);
        try feed.getData(token) returns (uint v) {
            return (v, true);
        } catch Error(string memory /*reason*/) {
            // This is executed in case
            // revert was called inside getData
            // and a reason string was provided.
            errorCount++;
            return (0, false);
        } catch Panic(uint /*errorCode*/) {
            // This is executed in case of a panic,
            // i.e. a serious error like division by zero
            // or overflow. The error code can be used
            // to determine the kind of error.
            errorCount++;
            return (0, false);
        } catch (bytes memory /*lowLevelData*/) {
            // This is executed in case revert() was used.
            errorCount++;
            return (0, false);
        }
    }
}

Self Destruct

參考網址 The only way to remove code from the blockchain is when a contract at that address performs the selfdestruct operation. 很危險!如果其他人傳送Ether到已經被移除的合約地址,Ether會被永久遺失。

其他

  • 可以返回多個return值
  • 可以overloading–A contract can have multiple functions of the same name but with different parameter types
  • 和c一樣有struct