aboutsummaryrefslogtreecommitdiffstats
path: root/contracts/chequebook
diff options
context:
space:
mode:
Diffstat (limited to 'contracts/chequebook')
-rw-r--r--contracts/chequebook/api.go68
-rw-r--r--contracts/chequebook/cheque.go642
-rw-r--r--contracts/chequebook/cheque_test.go487
-rw-r--r--contracts/chequebook/contract/chequebook.go367
-rw-r--r--contracts/chequebook/contract/chequebook.sol47
-rw-r--r--contracts/chequebook/contract/code.go5
-rw-r--r--contracts/chequebook/contract/mortal.sol10
-rw-r--r--contracts/chequebook/contract/owned.sol15
-rw-r--r--contracts/chequebook/gencode.go70
9 files changed, 0 insertions, 1711 deletions
diff --git a/contracts/chequebook/api.go b/contracts/chequebook/api.go
deleted file mode 100644
index fb7080308..000000000
--- a/contracts/chequebook/api.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-package chequebook
-
-import (
- "errors"
- "math/big"
-
- "github.com/ethereum/go-ethereum/common"
-)
-
-const Version = "1.0"
-
-var errNoChequebook = errors.New("no chequebook")
-
-type API struct {
- chequebookf func() *Chequebook
-}
-
-func NewAPI(ch func() *Chequebook) *API {
- return &API{ch}
-}
-
-func (a *API) Balance() (string, error) {
- ch := a.chequebookf()
- if ch == nil {
- return "", errNoChequebook
- }
- return ch.Balance().String(), nil
-}
-
-func (a *API) Issue(beneficiary common.Address, amount *big.Int) (cheque *Cheque, err error) {
- ch := a.chequebookf()
- if ch == nil {
- return nil, errNoChequebook
- }
- return ch.Issue(beneficiary, amount)
-}
-
-func (a *API) Cash(cheque *Cheque) (txhash string, err error) {
- ch := a.chequebookf()
- if ch == nil {
- return "", errNoChequebook
- }
- return ch.Cash(cheque)
-}
-
-func (a *API) Deposit(amount *big.Int) (txhash string, err error) {
- ch := a.chequebookf()
- if ch == nil {
- return "", errNoChequebook
- }
- return ch.Deposit(amount)
-}
diff --git a/contracts/chequebook/cheque.go b/contracts/chequebook/cheque.go
deleted file mode 100644
index 32e840676..000000000
--- a/contracts/chequebook/cheque.go
+++ /dev/null
@@ -1,642 +0,0 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-// Package chequebook package wraps the 'chequebook' Ethereum smart contract.
-//
-// The functions in this package allow using chequebook for
-// issuing, receiving, verifying cheques in ether; (auto)cashing cheques in ether
-// as well as (auto)depositing ether to the chequebook contract.
-package chequebook
-
-//go:generate abigen --sol contract/chequebook.sol --exc contract/mortal.sol:mortal,contract/owned.sol:owned --pkg contract --out contract/chequebook.go
-//go:generate go run ./gencode.go
-
-import (
- "bytes"
- "context"
- "crypto/ecdsa"
- "encoding/json"
- "fmt"
- "io/ioutil"
- "math/big"
- "os"
- "sync"
- "time"
-
- "github.com/ethereum/go-ethereum/accounts/abi/bind"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
- "github.com/ethereum/go-ethereum/contracts/chequebook/contract"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/swarm/services/swap/swap"
-)
-
-// TODO(zelig): watch peer solvency and notify of bouncing cheques
-// TODO(zelig): enable paying with cheque by signing off
-
-// Some functionality requires interacting with the blockchain:
-// * setting current balance on peer's chequebook
-// * sending the transaction to cash the cheque
-// * depositing ether to the chequebook
-// * watching incoming ether
-
-var (
- gasToCash = uint64(2000000) // gas cost of a cash transaction using chequebook
- // gasToDeploy = uint64(3000000)
-)
-
-// Backend wraps all methods required for chequebook operation.
-type Backend interface {
- bind.ContractBackend
- TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error)
- BalanceAt(ctx context.Context, address common.Address, blockNum *big.Int) (*big.Int, error)
-}
-
-// Cheque represents a payment promise to a single beneficiary.
-type Cheque struct {
- Contract common.Address // address of chequebook, needed to avoid cross-contract submission
- Beneficiary common.Address
- Amount *big.Int // cumulative amount of all funds sent
- Sig []byte // signature Sign(Keccak256(contract, beneficiary, amount), prvKey)
-}
-
-func (ch *Cheque) String() string {
- return fmt.Sprintf("contract: %s, beneficiary: %s, amount: %v, signature: %x", ch.Contract.Hex(), ch.Beneficiary.Hex(), ch.Amount, ch.Sig)
-}
-
-type Params struct {
- ContractCode, ContractAbi string
-}
-
-var ContractParams = &Params{contract.ChequebookBin, contract.ChequebookABI}
-
-// Chequebook can create and sign cheques from a single contract to multiple beneficiaries.
-// It is the outgoing payment handler for peer to peer micropayments.
-type Chequebook struct {
- path string // path to chequebook file
- prvKey *ecdsa.PrivateKey // private key to sign cheque with
- lock sync.Mutex //
- backend Backend // blockchain API
- quit chan bool // when closed causes autodeposit to stop
- owner common.Address // owner address (derived from pubkey)
- contract *contract.Chequebook // abigen binding
- session *contract.ChequebookSession // abigen binding with Tx Opts
-
- // persisted fields
- balance *big.Int // not synced with blockchain
- contractAddr common.Address // contract address
- sent map[common.Address]*big.Int //tallies for beneficiaries
-
- txhash string // tx hash of last deposit tx
- threshold *big.Int // threshold that triggers autodeposit if not nil
- buffer *big.Int // buffer to keep on top of balance for fork protection
-
- log log.Logger // contextual logger with the contract address embedded
-}
-
-func (cb *Chequebook) String() string {
- return fmt.Sprintf("contract: %s, owner: %s, balance: %v, signer: %x", cb.contractAddr.Hex(), cb.owner.Hex(), cb.balance, cb.prvKey.PublicKey)
-}
-
-// NewChequebook creates a new Chequebook.
-func NewChequebook(path string, contractAddr common.Address, prvKey *ecdsa.PrivateKey, backend Backend) (*Chequebook, error) {
- balance := new(big.Int)
- sent := make(map[common.Address]*big.Int)
-
- chbook, err := contract.NewChequebook(contractAddr, backend)
- if err != nil {
- return nil, err
- }
- transactOpts := bind.NewKeyedTransactor(prvKey)
- session := &contract.ChequebookSession{
- Contract: chbook,
- TransactOpts: *transactOpts,
- }
-
- cb := &Chequebook{
- prvKey: prvKey,
- balance: balance,
- contractAddr: contractAddr,
- sent: sent,
- path: path,
- backend: backend,
- owner: transactOpts.From,
- contract: chbook,
- session: session,
- log: log.New("contract", contractAddr),
- }
- if (contractAddr != common.Address{}) {
- cb.setBalanceFromBlockChain()
- cb.log.Trace("New chequebook initialised", "owner", cb.owner, "balance", cb.balance)
- }
- return cb, nil
-}
-
-func (cb *Chequebook) setBalanceFromBlockChain() {
- balance, err := cb.backend.BalanceAt(context.TODO(), cb.contractAddr, nil)
- if err != nil {
- log.Error("Failed to retrieve chequebook balance", "err", err)
- } else {
- cb.balance.Set(balance)
- }
-}
-
-// LoadChequebook loads a chequebook from disk (file path).
-func LoadChequebook(path string, prvKey *ecdsa.PrivateKey, backend Backend, checkBalance bool) (*Chequebook, error) {
- data, err := ioutil.ReadFile(path)
- if err != nil {
- return nil, err
- }
- cb, _ := NewChequebook(path, common.Address{}, prvKey, backend)
-
- if err = json.Unmarshal(data, cb); err != nil {
- return nil, err
- }
- if checkBalance {
- cb.setBalanceFromBlockChain()
- }
- log.Trace("Loaded chequebook from disk", "path", path)
-
- return cb, nil
-}
-
-// chequebookFile is the JSON representation of a chequebook.
-type chequebookFile struct {
- Balance string
- Contract string
- Owner string
- Sent map[string]string
-}
-
-// UnmarshalJSON deserialises a chequebook.
-func (cb *Chequebook) UnmarshalJSON(data []byte) error {
- var file chequebookFile
- err := json.Unmarshal(data, &file)
- if err != nil {
- return err
- }
- _, ok := cb.balance.SetString(file.Balance, 10)
- if !ok {
- return fmt.Errorf("cumulative amount sent: unable to convert string to big integer: %v", file.Balance)
- }
- cb.contractAddr = common.HexToAddress(file.Contract)
- for addr, sent := range file.Sent {
- cb.sent[common.HexToAddress(addr)], ok = new(big.Int).SetString(sent, 10)
- if !ok {
- return fmt.Errorf("beneficiary %v cumulative amount sent: unable to convert string to big integer: %v", addr, sent)
- }
- }
- return nil
-}
-
-// MarshalJSON serialises a chequebook.
-func (cb *Chequebook) MarshalJSON() ([]byte, error) {
- var file = &chequebookFile{
- Balance: cb.balance.String(),
- Contract: cb.contractAddr.Hex(),
- Owner: cb.owner.Hex(),
- Sent: make(map[string]string),
- }
- for addr, sent := range cb.sent {
- file.Sent[addr.Hex()] = sent.String()
- }
- return json.Marshal(file)
-}
-
-// Save persists the chequebook on disk, remembering balance, contract address and
-// cumulative amount of funds sent for each beneficiary.
-func (cb *Chequebook) Save() error {
- data, err := json.MarshalIndent(cb, "", " ")
- if err != nil {
- return err
- }
- cb.log.Trace("Saving chequebook to disk", cb.path)
-
- return ioutil.WriteFile(cb.path, data, os.ModePerm)
-}
-
-// Stop quits the autodeposit go routine to terminate
-func (cb *Chequebook) Stop() {
- defer cb.lock.Unlock()
- cb.lock.Lock()
- if cb.quit != nil {
- close(cb.quit)
- cb.quit = nil
- }
-}
-
-// Issue creates a cheque signed by the chequebook owner's private key. The
-// signer commits to a contract (one that they own), a beneficiary and amount.
-func (cb *Chequebook) Issue(beneficiary common.Address, amount *big.Int) (*Cheque, error) {
- defer cb.lock.Unlock()
- cb.lock.Lock()
-
- if amount.Sign() <= 0 {
- return nil, fmt.Errorf("amount must be greater than zero (%v)", amount)
- }
- var (
- ch *Cheque
- err error
- )
- if cb.balance.Cmp(amount) < 0 {
- err = fmt.Errorf("insufficient funds to issue cheque for amount: %v. balance: %v", amount, cb.balance)
- } else {
- var sig []byte
- sent, found := cb.sent[beneficiary]
- if !found {
- sent = new(big.Int)
- cb.sent[beneficiary] = sent
- }
- sum := new(big.Int).Set(sent)
- sum.Add(sum, amount)
-
- sig, err = crypto.Sign(sigHash(cb.contractAddr, beneficiary, sum), cb.prvKey)
- if err == nil {
- ch = &Cheque{
- Contract: cb.contractAddr,
- Beneficiary: beneficiary,
- Amount: sum,
- Sig: sig,
- }
- sent.Set(sum)
- cb.balance.Sub(cb.balance, amount) // subtract amount from balance
- }
- }
- // auto deposit if threshold is set and balance is less then threshold
- // note this is called even if issuing cheque fails
- // so we reattempt depositing
- if cb.threshold != nil {
- if cb.balance.Cmp(cb.threshold) < 0 {
- send := new(big.Int).Sub(cb.buffer, cb.balance)
- cb.deposit(send)
- }
- }
- return ch, err
-}
-
-// Cash is a convenience method to cash any cheque.
-func (cb *Chequebook) Cash(ch *Cheque) (string, error) {
- return ch.Cash(cb.session)
-}
-
-// data to sign: contract address, beneficiary, cumulative amount of funds ever sent
-func sigHash(contract, beneficiary common.Address, sum *big.Int) []byte {
- bigamount := sum.Bytes()
- if len(bigamount) > 32 {
- return nil
- }
- var amount32 [32]byte
- copy(amount32[32-len(bigamount):32], bigamount)
- input := append(contract.Bytes(), beneficiary.Bytes()...)
- input = append(input, amount32[:]...)
- return crypto.Keccak256(input)
-}
-
-// Balance returns the current balance of the chequebook.
-func (cb *Chequebook) Balance() *big.Int {
- defer cb.lock.Unlock()
- cb.lock.Lock()
- return new(big.Int).Set(cb.balance)
-}
-
-// Owner returns the owner account of the chequebook.
-func (cb *Chequebook) Owner() common.Address {
- return cb.owner
-}
-
-// Address returns the on-chain contract address of the chequebook.
-func (cb *Chequebook) Address() common.Address {
- return cb.contractAddr
-}
-
-// Deposit deposits money to the chequebook account.
-func (cb *Chequebook) Deposit(amount *big.Int) (string, error) {
- defer cb.lock.Unlock()
- cb.lock.Lock()
- return cb.deposit(amount)
-}
-
-// deposit deposits amount to the chequebook account.
-// The caller must hold lock.
-func (cb *Chequebook) deposit(amount *big.Int) (string, error) {
- // since the amount is variable here, we do not use sessions
- depositTransactor := bind.NewKeyedTransactor(cb.prvKey)
- depositTransactor.Value = amount
- chbookRaw := &contract.ChequebookRaw{Contract: cb.contract}
- tx, err := chbookRaw.Transfer(depositTransactor)
- if err != nil {
- cb.log.Warn("Failed to fund chequebook", "amount", amount, "balance", cb.balance, "target", cb.buffer, "err", err)
- return "", err
- }
- // assume that transaction is actually successful, we add the amount to balance right away
- cb.balance.Add(cb.balance, amount)
- cb.log.Trace("Deposited funds to chequebook", "amount", amount, "balance", cb.balance, "target", cb.buffer)
- return tx.Hash().Hex(), nil
-}
-
-// AutoDeposit (re)sets interval time and amount which triggers sending funds to the
-// chequebook. Contract backend needs to be set if threshold is not less than buffer, then
-// deposit will be triggered on every new cheque issued.
-func (cb *Chequebook) AutoDeposit(interval time.Duration, threshold, buffer *big.Int) {
- defer cb.lock.Unlock()
- cb.lock.Lock()
- cb.threshold = threshold
- cb.buffer = buffer
- cb.autoDeposit(interval)
-}
-
-// autoDeposit starts a goroutine that periodically sends funds to the chequebook
-// contract caller holds the lock the go routine terminates if Chequebook.quit is closed.
-func (cb *Chequebook) autoDeposit(interval time.Duration) {
- if cb.quit != nil {
- close(cb.quit)
- cb.quit = nil
- }
- // if threshold >= balance autodeposit after every cheque issued
- if interval == time.Duration(0) || cb.threshold != nil && cb.buffer != nil && cb.threshold.Cmp(cb.buffer) >= 0 {
- return
- }
-
- ticker := time.NewTicker(interval)
- cb.quit = make(chan bool)
- quit := cb.quit
-
- go func() {
- for {
- select {
- case <-quit:
- return
- case <-ticker.C:
- cb.lock.Lock()
- if cb.balance.Cmp(cb.buffer) < 0 {
- amount := new(big.Int).Sub(cb.buffer, cb.balance)
- txhash, err := cb.deposit(amount)
- if err == nil {
- cb.txhash = txhash
- }
- }
- cb.lock.Unlock()
- }
- }
- }()
-}
-
-// Outbox can issue cheques from a single contract to a single beneficiary.
-type Outbox struct {
- chequeBook *Chequebook
- beneficiary common.Address
-}
-
-// NewOutbox creates an outbox.
-func NewOutbox(cb *Chequebook, beneficiary common.Address) *Outbox {
- return &Outbox{cb, beneficiary}
-}
-
-// Issue creates cheque.
-func (o *Outbox) Issue(amount *big.Int) (swap.Promise, error) {
- return o.chequeBook.Issue(o.beneficiary, amount)
-}
-
-// AutoDeposit enables auto-deposits on the underlying chequebook.
-func (o *Outbox) AutoDeposit(interval time.Duration, threshold, buffer *big.Int) {
- o.chequeBook.AutoDeposit(interval, threshold, buffer)
-}
-
-// Stop helps satisfy the swap.OutPayment interface.
-func (o *Outbox) Stop() {}
-
-// String implements fmt.Stringer.
-func (o *Outbox) String() string {
- return fmt.Sprintf("chequebook: %v, beneficiary: %s, balance: %v", o.chequeBook.Address().Hex(), o.beneficiary.Hex(), o.chequeBook.Balance())
-}
-
-// Inbox can deposit, verify and cash cheques from a single contract to a single
-// beneficiary. It is the incoming payment handler for peer to peer micropayments.
-type Inbox struct {
- lock sync.Mutex
- contract common.Address // peer's chequebook contract
- beneficiary common.Address // local peer's receiving address
- sender common.Address // local peer's address to send cashing tx from
- signer *ecdsa.PublicKey // peer's public key
- txhash string // tx hash of last cashing tx
- session *contract.ChequebookSession // abi contract backend with tx opts
- quit chan bool // when closed causes autocash to stop
- maxUncashed *big.Int // threshold that triggers autocashing
- cashed *big.Int // cumulative amount cashed
- cheque *Cheque // last cheque, nil if none yet received
- log log.Logger // contextual logger with the contract address embedded
-}
-
-// NewInbox creates an Inbox. An Inboxes is not persisted, the cumulative sum is updated
-// from blockchain when first cheque is received.
-func NewInbox(prvKey *ecdsa.PrivateKey, contractAddr, beneficiary common.Address, signer *ecdsa.PublicKey, abigen bind.ContractBackend) (*Inbox, error) {
- if signer == nil {
- return nil, fmt.Errorf("signer is null")
- }
- chbook, err := contract.NewChequebook(contractAddr, abigen)
- if err != nil {
- return nil, err
- }
- transactOpts := bind.NewKeyedTransactor(prvKey)
- transactOpts.GasLimit = gasToCash
- session := &contract.ChequebookSession{
- Contract: chbook,
- TransactOpts: *transactOpts,
- }
- sender := transactOpts.From
-
- inbox := &Inbox{
- contract: contractAddr,
- beneficiary: beneficiary,
- sender: sender,
- signer: signer,
- session: session,
- cashed: new(big.Int).Set(common.Big0),
- log: log.New("contract", contractAddr),
- }
- inbox.log.Trace("New chequebook inbox initialized", "beneficiary", inbox.beneficiary, "signer", hexutil.Bytes(crypto.FromECDSAPub(signer)))
- return inbox, nil
-}
-
-func (i *Inbox) String() string {
- return fmt.Sprintf("chequebook: %v, beneficiary: %s, balance: %v", i.contract.Hex(), i.beneficiary.Hex(), i.cheque.Amount)
-}
-
-// Stop quits the autocash goroutine.
-func (i *Inbox) Stop() {
- defer i.lock.Unlock()
- i.lock.Lock()
- if i.quit != nil {
- close(i.quit)
- i.quit = nil
- }
-}
-
-// Cash attempts to cash the current cheque.
-func (i *Inbox) Cash() (string, error) {
- if i.cheque == nil {
- return "", nil
- }
- txhash, err := i.cheque.Cash(i.session)
- i.log.Trace("Cashing in chequebook cheque", "amount", i.cheque.Amount, "beneficiary", i.beneficiary)
- i.cashed = i.cheque.Amount
-
- return txhash, err
-}
-
-// AutoCash (re)sets maximum time and amount which triggers cashing of the last uncashed
-// cheque if maxUncashed is set to 0, then autocash on receipt.
-func (i *Inbox) AutoCash(cashInterval time.Duration, maxUncashed *big.Int) {
- defer i.lock.Unlock()
- i.lock.Lock()
- i.maxUncashed = maxUncashed
- i.autoCash(cashInterval)
-}
-
-// autoCash starts a loop that periodically clears the last cheque
-// if the peer is trusted. Clearing period could be 24h or a week.
-// The caller must hold lock.
-func (i *Inbox) autoCash(cashInterval time.Duration) {
- if i.quit != nil {
- close(i.quit)
- i.quit = nil
- }
- // if maxUncashed is set to 0, then autocash on receipt
- if cashInterval == time.Duration(0) || i.maxUncashed != nil && i.maxUncashed.Sign() == 0 {
- return
- }
-
- ticker := time.NewTicker(cashInterval)
- i.quit = make(chan bool)
- quit := i.quit
-
- go func() {
- for {
- select {
- case <-quit:
- return
- case <-ticker.C:
- i.lock.Lock()
- if i.cheque != nil && i.cheque.Amount.Cmp(i.cashed) != 0 {
- txhash, err := i.Cash()
- if err == nil {
- i.txhash = txhash
- }
- }
- i.lock.Unlock()
- }
- }
- }()
-}
-
-// Receive is called to deposit the latest cheque to the incoming Inbox.
-// The given promise must be a *Cheque.
-func (i *Inbox) Receive(promise swap.Promise) (*big.Int, error) {
- ch := promise.(*Cheque)
-
- defer i.lock.Unlock()
- i.lock.Lock()
-
- var sum *big.Int
- if i.cheque == nil {
- // the sum is checked against the blockchain once a cheque is received
- tally, err := i.session.Sent(i.beneficiary)
- if err != nil {
- return nil, fmt.Errorf("inbox: error calling backend to set amount: %v", err)
- }
- sum = tally
- } else {
- sum = i.cheque.Amount
- }
-
- amount, err := ch.Verify(i.signer, i.contract, i.beneficiary, sum)
- var uncashed *big.Int
- if err == nil {
- i.cheque = ch
-
- if i.maxUncashed != nil {
- uncashed = new(big.Int).Sub(ch.Amount, i.cashed)
- if i.maxUncashed.Cmp(uncashed) < 0 {
- i.Cash()
- }
- }
- i.log.Trace("Received cheque in chequebook inbox", "amount", amount, "uncashed", uncashed)
- }
-
- return amount, err
-}
-
-// Verify verifies cheque for signer, contract, beneficiary, amount, valid signature.
-func (ch *Cheque) Verify(signerKey *ecdsa.PublicKey, contract, beneficiary common.Address, sum *big.Int) (*big.Int, error) {
- log.Trace("Verifying chequebook cheque", "cheque", ch, "sum", sum)
- if sum == nil {
- return nil, fmt.Errorf("invalid amount")
- }
-
- if ch.Beneficiary != beneficiary {
- return nil, fmt.Errorf("beneficiary mismatch: %v != %v", ch.Beneficiary.Hex(), beneficiary.Hex())
- }
- if ch.Contract != contract {
- return nil, fmt.Errorf("contract mismatch: %v != %v", ch.Contract.Hex(), contract.Hex())
- }
-
- amount := new(big.Int).Set(ch.Amount)
- if sum != nil {
- amount.Sub(amount, sum)
- if amount.Sign() <= 0 {
- return nil, fmt.Errorf("incorrect amount: %v <= 0", amount)
- }
- }
-
- pubKey, err := crypto.SigToPub(sigHash(ch.Contract, beneficiary, ch.Amount), ch.Sig)
- if err != nil {
- return nil, fmt.Errorf("invalid signature: %v", err)
- }
- if !bytes.Equal(crypto.FromECDSAPub(pubKey), crypto.FromECDSAPub(signerKey)) {
- return nil, fmt.Errorf("signer mismatch: %x != %x", crypto.FromECDSAPub(pubKey), crypto.FromECDSAPub(signerKey))
- }
- return amount, nil
-}
-
-// v/r/s representation of signature
-func sig2vrs(sig []byte) (v byte, r, s [32]byte) {
- v = sig[64] + 27
- copy(r[:], sig[:32])
- copy(s[:], sig[32:64])
- return
-}
-
-// Cash cashes the cheque by sending an Ethereum transaction.
-func (ch *Cheque) Cash(session *contract.ChequebookSession) (string, error) {
- v, r, s := sig2vrs(ch.Sig)
- tx, err := session.Cash(ch.Beneficiary, ch.Amount, v, r, s)
- if err != nil {
- return "", err
- }
- return tx.Hash().Hex(), nil
-}
-
-// ValidateCode checks that the on-chain code at address matches the expected chequebook
-// contract code. This is used to detect suicided chequebooks.
-func ValidateCode(ctx context.Context, b Backend, address common.Address) (bool, error) {
- code, err := b.CodeAt(ctx, address, nil)
- if err != nil {
- return false, err
- }
- return bytes.Equal(code, common.FromHex(contract.ContractDeployedCode)), nil
-}
diff --git a/contracts/chequebook/cheque_test.go b/contracts/chequebook/cheque_test.go
deleted file mode 100644
index 4bd2e176b..000000000
--- a/contracts/chequebook/cheque_test.go
+++ /dev/null
@@ -1,487 +0,0 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-package chequebook
-
-import (
- "crypto/ecdsa"
- "math/big"
- "os"
- "path/filepath"
- "testing"
- "time"
-
- "github.com/ethereum/go-ethereum/accounts/abi/bind"
- "github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/contracts/chequebook/contract"
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/crypto"
-)
-
-var (
- key0, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
- key1, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
- key2, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
- addr0 = crypto.PubkeyToAddress(key0.PublicKey)
- addr1 = crypto.PubkeyToAddress(key1.PublicKey)
- addr2 = crypto.PubkeyToAddress(key2.PublicKey)
-)
-
-func newTestBackend() *backends.SimulatedBackend {
- return backends.NewSimulatedBackend(core.GenesisAlloc{
- addr0: {Balance: big.NewInt(1000000000)},
- addr1: {Balance: big.NewInt(1000000000)},
- addr2: {Balance: big.NewInt(1000000000)},
- }, 10000000)
-}
-
-func deploy(prvKey *ecdsa.PrivateKey, amount *big.Int, backend *backends.SimulatedBackend) (common.Address, error) {
- deployTransactor := bind.NewKeyedTransactor(prvKey)
- deployTransactor.Value = amount
- addr, _, _, err := contract.DeployChequebook(deployTransactor, backend)
- if err != nil {
- return common.Address{}, err
- }
- backend.Commit()
- return addr, nil
-}
-
-func TestIssueAndReceive(t *testing.T) {
- path := filepath.Join(os.TempDir(), "chequebook-test.json")
- backend := newTestBackend()
- addr0, err := deploy(key0, big.NewInt(0), backend)
- if err != nil {
- t.Fatalf("deploy contract: expected no error, got %v", err)
- }
- chbook, err := NewChequebook(path, addr0, key0, backend)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- chbook.sent[addr1] = new(big.Int).SetUint64(42)
- amount := common.Big1
-
- if _, err = chbook.Issue(addr1, amount); err == nil {
- t.Fatalf("expected insufficient funds error, got none")
- }
-
- chbook.balance = new(big.Int).Set(common.Big1)
- if chbook.Balance().Cmp(common.Big1) != 0 {
- t.Fatalf("expected: %v, got %v", "0", chbook.Balance())
- }
-
- ch, err := chbook.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
-
- if chbook.Balance().Sign() != 0 {
- t.Errorf("expected: %v, got %v", "0", chbook.Balance())
- }
-
- chbox, err := NewInbox(key1, addr0, addr1, &key0.PublicKey, backend)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
-
- received, err := chbox.Receive(ch)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
-
- if received.Cmp(big.NewInt(43)) != 0 {
- t.Errorf("expected: %v, got %v", "43", received)
- }
-
-}
-
-func TestCheckbookFile(t *testing.T) {
- path := filepath.Join(os.TempDir(), "chequebook-test.json")
- backend := newTestBackend()
- chbook, err := NewChequebook(path, addr0, key0, backend)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- chbook.sent[addr1] = new(big.Int).SetUint64(42)
- chbook.balance = new(big.Int).Set(common.Big1)
-
- chbook.Save()
-
- chbook, err = LoadChequebook(path, key0, backend, false)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- if chbook.Balance().Cmp(common.Big1) != 0 {
- t.Errorf("expected: %v, got %v", "0", chbook.Balance())
- }
-
- var ch *Cheque
- if ch, err = chbook.Issue(addr1, common.Big1); err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- if ch.Amount.Cmp(new(big.Int).SetUint64(43)) != 0 {
- t.Errorf("expected: %v, got %v", "0", ch.Amount)
- }
-
- err = chbook.Save()
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
-}
-
-func TestVerifyErrors(t *testing.T) {
- path0 := filepath.Join(os.TempDir(), "chequebook-test-0.json")
- backend := newTestBackend()
- contr0, err := deploy(key0, common.Big2, backend)
- if err != nil {
- t.Errorf("expected no error, got %v", err)
- }
- chbook0, err := NewChequebook(path0, contr0, key0, backend)
- if err != nil {
- t.Errorf("expected no error, got %v", err)
- }
-
- path1 := filepath.Join(os.TempDir(), "chequebook-test-1.json")
- contr1, _ := deploy(key1, common.Big2, backend)
- chbook1, err := NewChequebook(path1, contr1, key1, backend)
- if err != nil {
- t.Errorf("expected no error, got %v", err)
- }
-
- chbook0.sent[addr1] = new(big.Int).SetUint64(42)
- chbook0.balance = new(big.Int).Set(common.Big2)
- chbook1.balance = new(big.Int).Set(common.Big1)
- amount := common.Big1
- ch0, err := chbook0.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
-
- chbox, err := NewInbox(key1, contr0, addr1, &key0.PublicKey, backend)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
-
- received, err := chbox.Receive(ch0)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
-
- if received.Cmp(big.NewInt(43)) != 0 {
- t.Errorf("expected: %v, got %v", "43", received)
- }
-
- ch1, err := chbook0.Issue(addr2, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
-
- received, err = chbox.Receive(ch1)
- t.Logf("correct error: %v", err)
- if err == nil {
- t.Fatalf("expected receiver error, got none and value %v", received)
- }
-
- ch2, err := chbook1.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- received, err = chbox.Receive(ch2)
- t.Logf("correct error: %v", err)
- if err == nil {
- t.Fatalf("expected sender error, got none and value %v", received)
- }
-
- _, err = chbook1.Issue(addr1, new(big.Int).SetInt64(-1))
- t.Logf("correct error: %v", err)
- if err == nil {
- t.Fatalf("expected incorrect amount error, got none")
- }
-
- received, err = chbox.Receive(ch0)
- t.Logf("correct error: %v", err)
- if err == nil {
- t.Fatalf("expected incorrect amount error, got none and value %v", received)
- }
-
-}
-
-func TestDeposit(t *testing.T) {
- path0 := filepath.Join(os.TempDir(), "chequebook-test-0.json")
- backend := newTestBackend()
- contr0, _ := deploy(key0, new(big.Int), backend)
-
- chbook, err := NewChequebook(path0, contr0, key0, backend)
- if err != nil {
- t.Errorf("expected no error, got %v", err)
- }
-
- balance := new(big.Int).SetUint64(42)
- chbook.Deposit(balance)
- backend.Commit()
- if chbook.Balance().Cmp(balance) != 0 {
- t.Fatalf("expected balance %v, got %v", balance, chbook.Balance())
- }
-
- amount := common.Big1
- _, err = chbook.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
- exp := new(big.Int).SetUint64(41)
- if chbook.Balance().Cmp(exp) != 0 {
- t.Fatalf("expected balance %v, got %v", exp, chbook.Balance())
- }
-
- // autodeposit on each issue
- chbook.AutoDeposit(0, balance, balance)
- _, err = chbook.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
- _, err = chbook.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
- if chbook.Balance().Cmp(balance) != 0 {
- t.Fatalf("expected balance %v, got %v", balance, chbook.Balance())
- }
-
- // autodeposit off
- chbook.AutoDeposit(0, common.Big0, balance)
- _, err = chbook.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
- _, err = chbook.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
-
- exp = new(big.Int).SetUint64(40)
- if chbook.Balance().Cmp(exp) != 0 {
- t.Fatalf("expected balance %v, got %v", exp, chbook.Balance())
- }
-
- // autodeposit every 200ms if new cheque issued
- interval := 200 * time.Millisecond
- chbook.AutoDeposit(interval, common.Big1, balance)
- _, err = chbook.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
- _, err = chbook.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
-
- exp = new(big.Int).SetUint64(38)
- if chbook.Balance().Cmp(exp) != 0 {
- t.Fatalf("expected balance %v, got %v", exp, chbook.Balance())
- }
-
- time.Sleep(3 * interval)
- backend.Commit()
- if chbook.Balance().Cmp(balance) != 0 {
- t.Fatalf("expected balance %v, got %v", balance, chbook.Balance())
- }
-
- exp = new(big.Int).SetUint64(40)
- chbook.AutoDeposit(4*interval, exp, balance)
- _, err = chbook.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
- _, err = chbook.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- time.Sleep(3 * interval)
- backend.Commit()
- if chbook.Balance().Cmp(exp) != 0 {
- t.Fatalf("expected balance %v, got %v", exp, chbook.Balance())
- }
-
- _, err = chbook.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- time.Sleep(1 * interval)
- backend.Commit()
-
- if chbook.Balance().Cmp(balance) != 0 {
- t.Fatalf("expected balance %v, got %v", balance, chbook.Balance())
- }
-
- chbook.AutoDeposit(1*interval, common.Big0, balance)
- chbook.Stop()
-
- _, err = chbook.Issue(addr1, common.Big1)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
-
- _, err = chbook.Issue(addr1, common.Big2)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
-
- time.Sleep(1 * interval)
- backend.Commit()
-
- exp = new(big.Int).SetUint64(39)
- if chbook.Balance().Cmp(exp) != 0 {
- t.Fatalf("expected balance %v, got %v", exp, chbook.Balance())
- }
-
-}
-
-func TestCash(t *testing.T) {
- path := filepath.Join(os.TempDir(), "chequebook-test.json")
- backend := newTestBackend()
- contr0, _ := deploy(key0, common.Big2, backend)
-
- chbook, err := NewChequebook(path, contr0, key0, backend)
- if err != nil {
- t.Errorf("expected no error, got %v", err)
- }
- chbook.sent[addr1] = new(big.Int).SetUint64(42)
- amount := common.Big1
- chbook.balance = new(big.Int).Set(common.Big1)
- ch, err := chbook.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
- chbox, err := NewInbox(key1, contr0, addr1, &key0.PublicKey, backend)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
-
- // cashing latest cheque
- if _, err = chbox.Receive(ch); err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- if _, err = ch.Cash(chbook.session); err != nil {
- t.Fatal("Cash failed:", err)
- }
- backend.Commit()
-
- chbook.balance = new(big.Int).Set(common.Big3)
- ch0, err := chbook.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
- ch1, err := chbook.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
-
- interval := 10 * time.Millisecond
- // setting autocash with interval of 10ms
- chbox.AutoCash(interval, nil)
- _, err = chbox.Receive(ch0)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- _, err = chbox.Receive(ch1)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
- // after 3x interval time and 2 cheques received, exactly one cashing tx is sent
- time.Sleep(4 * interval)
- backend.Commit()
-
- // after stopping autocash no more tx are sent
- ch2, err := chbook.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- chbox.Stop()
- _, err = chbox.Receive(ch2)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- time.Sleep(2 * interval)
- backend.Commit()
-
- // autocash below 1
- chbook.balance = big.NewInt(2)
- chbox.AutoCash(0, common.Big1)
-
- ch3, err := chbook.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
-
- ch4, err := chbook.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
-
- _, err = chbox.Receive(ch3)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
- _, err = chbox.Receive(ch4)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
-
- // autochash on receipt when maxUncashed is 0
- chbook.balance = new(big.Int).Set(common.Big2)
- chbox.AutoCash(0, common.Big0)
-
- ch5, err := chbook.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
-
- ch6, err := chbook.Issue(addr1, amount)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
-
- _, err = chbox.Receive(ch5)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
-
- _, err = chbox.Receive(ch6)
- if err != nil {
- t.Fatalf("expected no error, got %v", err)
- }
- backend.Commit()
-
-}
diff --git a/contracts/chequebook/contract/chequebook.go b/contracts/chequebook/contract/chequebook.go
deleted file mode 100644
index 3129b811c..000000000
--- a/contracts/chequebook/contract/chequebook.go
+++ /dev/null
@@ -1,367 +0,0 @@
-// Code generated - DO NOT EDIT.
-// This file is a generated binding and any manual changes will be lost.
-
-package contract
-
-import (
- "math/big"
- "strings"
-
- ethereum "github.com/ethereum/go-ethereum"
- "github.com/ethereum/go-ethereum/accounts/abi"
- "github.com/ethereum/go-ethereum/accounts/abi/bind"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/event"
-)
-
-// ChequebookABI is the input ABI used to generate the binding from.
-const ChequebookABI = "[{\"constant\":false,\"inputs\":[],\"name\":\"kill\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"sent\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"beneficiary\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"sig_v\",\"type\":\"uint8\"},{\"name\":\"sig_r\",\"type\":\"bytes32\"},{\"name\":\"sig_s\",\"type\":\"bytes32\"}],\"name\":\"cash\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"deadbeat\",\"type\":\"address\"}],\"name\":\"Overdraft\",\"type\":\"event\"}]"
-
-// ChequebookBin is the compiled bytecode used for deploying new contracts.
-const ChequebookBin = `0x606060405260008054600160a060020a033316600160a060020a03199091161790556102ec806100306000396000f3006060604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166341c0e1b581146100585780637bf786f81461006b578063fbf788d61461009c575b005b341561006357600080fd5b6100566100ca565b341561007657600080fd5b61008a600160a060020a03600435166100f1565b60405190815260200160405180910390f35b34156100a757600080fd5b610056600160a060020a036004351660243560ff60443516606435608435610103565b60005433600160a060020a03908116911614156100ef57600054600160a060020a0316ff5b565b60016020526000908152604090205481565b600160a060020a0385166000908152600160205260408120548190861161012957600080fd5b3087876040516c01000000000000000000000000600160a060020a03948516810282529290931690910260148301526028820152604801604051809103902091506001828686866040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f115156101cf57600080fd5b505060206040510351600054600160a060020a039081169116146101f257600080fd5b50600160a060020a03808716600090815260016020526040902054860390301631811161026257600160a060020a0387166000818152600160205260409081902088905582156108fc0290839051600060405180830381858888f19350505050151561025d57600080fd5b6102b7565b6000547f2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f97890600160a060020a0316604051600160a060020a03909116815260200160405180910390a186600160a060020a0316ff5b505050505050505600a165627a7a72305820533e856fc37e3d64d1706bcc7dfb6b1d490c8d566ea498d9d01ec08965a896ca0029`
-
-// DeployChequebook deploys a new Ethereum contract, binding an instance of Chequebook to it.
-func DeployChequebook(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Chequebook, error) {
- parsed, err := abi.JSON(strings.NewReader(ChequebookABI))
- if err != nil {
- return common.Address{}, nil, nil, err
- }
- address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(ChequebookBin), backend)
- if err != nil {
- return common.Address{}, nil, nil, err
- }
- return address, tx, &Chequebook{ChequebookCaller: ChequebookCaller{contract: contract}, ChequebookTransactor: ChequebookTransactor{contract: contract}, ChequebookFilterer: ChequebookFilterer{contract: contract}}, nil
-}
-
-// Chequebook is an auto generated Go binding around an Ethereum contract.
-type Chequebook struct {
- ChequebookCaller // Read-only binding to the contract
- ChequebookTransactor // Write-only binding to the contract
- ChequebookFilterer // Log filterer for contract events
-}
-
-// ChequebookCaller is an auto generated read-only Go binding around an Ethereum contract.
-type ChequebookCaller struct {
- contract *bind.BoundContract // Generic contract wrapper for the low level calls
-}
-
-// ChequebookTransactor is an auto generated write-only Go binding around an Ethereum contract.
-type ChequebookTransactor struct {
- contract *bind.BoundContract // Generic contract wrapper for the low level calls
-}
-
-// ChequebookFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
-type ChequebookFilterer struct {
- contract *bind.BoundContract // Generic contract wrapper for the low level calls
-}
-
-// ChequebookSession is an auto generated Go binding around an Ethereum contract,
-// with pre-set call and transact options.
-type ChequebookSession struct {
- Contract *Chequebook // Generic contract binding to set the session for
- CallOpts bind.CallOpts // Call options to use throughout this session
- TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
-}
-
-// ChequebookCallerSession is an auto generated read-only Go binding around an Ethereum contract,
-// with pre-set call options.
-type ChequebookCallerSession struct {
- Contract *ChequebookCaller // Generic contract caller binding to set the session for
- CallOpts bind.CallOpts // Call options to use throughout this session
-}
-
-// ChequebookTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
-// with pre-set transact options.
-type ChequebookTransactorSession struct {
- Contract *ChequebookTransactor // Generic contract transactor binding to set the session for
- TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
-}
-
-// ChequebookRaw is an auto generated low-level Go binding around an Ethereum contract.
-type ChequebookRaw struct {
- Contract *Chequebook // Generic contract binding to access the raw methods on
-}
-
-// ChequebookCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
-type ChequebookCallerRaw struct {
- Contract *ChequebookCaller // Generic read-only contract binding to access the raw methods on
-}
-
-// ChequebookTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
-type ChequebookTransactorRaw struct {
- Contract *ChequebookTransactor // Generic write-only contract binding to access the raw methods on
-}
-
-// NewChequebook creates a new instance of Chequebook, bound to a specific deployed contract.
-func NewChequebook(address common.Address, backend bind.ContractBackend) (*Chequebook, error) {
- contract, err := bindChequebook(address, backend, backend, backend)
- if err != nil {
- return nil, err
- }
- return &Chequebook{ChequebookCaller: ChequebookCaller{contract: contract}, ChequebookTransactor: ChequebookTransactor{contract: contract}, ChequebookFilterer: ChequebookFilterer{contract: contract}}, nil
-}
-
-// NewChequebookCaller creates a new read-only instance of Chequebook, bound to a specific deployed contract.
-func NewChequebookCaller(address common.Address, caller bind.ContractCaller) (*ChequebookCaller, error) {
- contract, err := bindChequebook(address, caller, nil, nil)
- if err != nil {
- return nil, err
- }
- return &ChequebookCaller{contract: contract}, nil
-}
-
-// NewChequebookTransactor creates a new write-only instance of Chequebook, bound to a specific deployed contract.
-func NewChequebookTransactor(address common.Address, transactor bind.ContractTransactor) (*ChequebookTransactor, error) {
- contract, err := bindChequebook(address, nil, transactor, nil)
- if err != nil {
- return nil, err
- }
- return &ChequebookTransactor{contract: contract}, nil
-}
-
-// NewChequebookFilterer creates a new log filterer instance of Chequebook, bound to a specific deployed contract.
-func NewChequebookFilterer(address common.Address, filterer bind.ContractFilterer) (*ChequebookFilterer, error) {
- contract, err := bindChequebook(address, nil, nil, filterer)
- if err != nil {
- return nil, err
- }
- return &ChequebookFilterer{contract: contract}, nil
-}
-
-// bindChequebook binds a generic wrapper to an already deployed contract.
-func bindChequebook(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
- parsed, err := abi.JSON(strings.NewReader(ChequebookABI))
- if err != nil {
- return nil, err
- }
- return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
-}
-
-// Call invokes the (constant) contract method with params as input values and
-// sets the output to result. The result type might be a single field for simple
-// returns, a slice of interfaces for anonymous returns and a struct for named
-// returns.
-func (_Chequebook *ChequebookRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
- return _Chequebook.Contract.ChequebookCaller.contract.Call(opts, result, method, params...)
-}
-
-// Transfer initiates a plain transaction to move funds to the contract, calling
-// its default method if one is available.
-func (_Chequebook *ChequebookRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _Chequebook.Contract.ChequebookTransactor.contract.Transfer(opts)
-}
-
-// Transact invokes the (paid) contract method with params as input values.
-func (_Chequebook *ChequebookRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
- return _Chequebook.Contract.ChequebookTransactor.contract.Transact(opts, method, params...)
-}
-
-// Call invokes the (constant) contract method with params as input values and
-// sets the output to result. The result type might be a single field for simple
-// returns, a slice of interfaces for anonymous returns and a struct for named
-// returns.
-func (_Chequebook *ChequebookCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
- return _Chequebook.Contract.contract.Call(opts, result, method, params...)
-}
-
-// Transfer initiates a plain transaction to move funds to the contract, calling
-// its default method if one is available.
-func (_Chequebook *ChequebookTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _Chequebook.Contract.contract.Transfer(opts)
-}
-
-// Transact invokes the (paid) contract method with params as input values.
-func (_Chequebook *ChequebookTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
- return _Chequebook.Contract.contract.Transact(opts, method, params...)
-}
-
-// Sent is a free data retrieval call binding the contract method 0x7bf786f8.
-//
-// Solidity: function sent( address) constant returns(uint256)
-func (_Chequebook *ChequebookCaller) Sent(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) {
- var (
- ret0 = new(*big.Int)
- )
- out := ret0
- err := _Chequebook.contract.Call(opts, out, "sent", arg0)
- return *ret0, err
-}
-
-// Sent is a free data retrieval call binding the contract method 0x7bf786f8.
-//
-// Solidity: function sent( address) constant returns(uint256)
-func (_Chequebook *ChequebookSession) Sent(arg0 common.Address) (*big.Int, error) {
- return _Chequebook.Contract.Sent(&_Chequebook.CallOpts, arg0)
-}
-
-// Sent is a free data retrieval call binding the contract method 0x7bf786f8.
-//
-// Solidity: function sent( address) constant returns(uint256)
-func (_Chequebook *ChequebookCallerSession) Sent(arg0 common.Address) (*big.Int, error) {
- return _Chequebook.Contract.Sent(&_Chequebook.CallOpts, arg0)
-}
-
-// Cash is a paid mutator transaction binding the contract method 0xfbf788d6.
-//
-// Solidity: function cash(beneficiary address, amount uint256, sig_v uint8, sig_r bytes32, sig_s bytes32) returns()
-func (_Chequebook *ChequebookTransactor) Cash(opts *bind.TransactOpts, beneficiary common.Address, amount *big.Int, sigV uint8, sigR [32]byte, sigS [32]byte) (*types.Transaction, error) {
- return _Chequebook.contract.Transact(opts, "cash", beneficiary, amount, sigV, sigR, sigS)
-}
-
-// Cash is a paid mutator transaction binding the contract method 0xfbf788d6.
-//
-// Solidity: function cash(beneficiary address, amount uint256, sig_v uint8, sig_r bytes32, sig_s bytes32) returns()
-func (_Chequebook *ChequebookSession) Cash(beneficiary common.Address, amount *big.Int, sigV uint8, sigR [32]byte, sigS [32]byte) (*types.Transaction, error) {
- return _Chequebook.Contract.Cash(&_Chequebook.TransactOpts, beneficiary, amount, sigV, sigR, sigS)
-}
-
-// Cash is a paid mutator transaction binding the contract method 0xfbf788d6.
-//
-// Solidity: function cash(beneficiary address, amount uint256, sig_v uint8, sig_r bytes32, sig_s bytes32) returns()
-func (_Chequebook *ChequebookTransactorSession) Cash(beneficiary common.Address, amount *big.Int, sigV uint8, sigR [32]byte, sigS [32]byte) (*types.Transaction, error) {
- return _Chequebook.Contract.Cash(&_Chequebook.TransactOpts, beneficiary, amount, sigV, sigR, sigS)
-}
-
-// Kill is a paid mutator transaction binding the contract method 0x41c0e1b5.
-//
-// Solidity: function kill() returns()
-func (_Chequebook *ChequebookTransactor) Kill(opts *bind.TransactOpts) (*types.Transaction, error) {
- return _Chequebook.contract.Transact(opts, "kill")
-}
-
-// Kill is a paid mutator transaction binding the contract method 0x41c0e1b5.
-//
-// Solidity: function kill() returns()
-func (_Chequebook *ChequebookSession) Kill() (*types.Transaction, error) {
- return _Chequebook.Contract.Kill(&_Chequebook.TransactOpts)
-}
-
-// Kill is a paid mutator transaction binding the contract method 0x41c0e1b5.
-//
-// Solidity: function kill() returns()
-func (_Chequebook *ChequebookTransactorSession) Kill() (*types.Transaction, error) {
- return _Chequebook.Contract.Kill(&_Chequebook.TransactOpts)
-}
-
-// ChequebookOverdraftIterator is returned from FilterOverdraft and is used to iterate over the raw logs and unpacked data for Overdraft events raised by the Chequebook contract.
-type ChequebookOverdraftIterator struct {
- Event *ChequebookOverdraft // Event containing the contract specifics and raw log
-
- contract *bind.BoundContract // Generic contract to use for unpacking event data
- event string // Event name to use for unpacking event data
-
- logs chan types.Log // Log channel receiving the found contract events
- sub ethereum.Subscription // Subscription for errors, completion and termination
- done bool // Whether the subscription completed delivering logs
- fail error // Occurred error to stop iteration
-}
-
-// Next advances the iterator to the subsequent event, returning whether there
-// are any more events found. In case of a retrieval or parsing error, false is
-// returned and Error() can be queried for the exact failure.
-func (it *ChequebookOverdraftIterator) Next() bool {
- // If the iterator failed, stop iterating
- if it.fail != nil {
- return false
- }
- // If the iterator completed, deliver directly whatever's available
- if it.done {
- select {
- case log := <-it.logs:
- it.Event = new(ChequebookOverdraft)
- if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
- it.fail = err
- return false
- }
- it.Event.Raw = log
- return true
-
- default:
- return false
- }
- }
- // Iterator still in progress, wait for either a data or an error event
- select {
- case log := <-it.logs:
- it.Event = new(ChequebookOverdraft)
- if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
- it.fail = err
- return false
- }
- it.Event.Raw = log
- return true
-
- case err := <-it.sub.Err():
- it.done = true
- it.fail = err
- return it.Next()
- }
-}
-
-// Error retruned any retrieval or parsing error occurred during filtering.
-func (it *ChequebookOverdraftIterator) Error() error {
- return it.fail
-}
-
-// Close terminates the iteration process, releasing any pending underlying
-// resources.
-func (it *ChequebookOverdraftIterator) Close() error {
- it.sub.Unsubscribe()
- return nil
-}
-
-// ChequebookOverdraft represents a Overdraft event raised by the Chequebook contract.
-type ChequebookOverdraft struct {
- Deadbeat common.Address
- Raw types.Log // Blockchain specific contextual infos
-}
-
-// FilterOverdraft is a free log retrieval operation binding the contract event 0x2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f978.
-//
-// Solidity: event Overdraft(deadbeat address)
-func (_Chequebook *ChequebookFilterer) FilterOverdraft(opts *bind.FilterOpts) (*ChequebookOverdraftIterator, error) {
-
- logs, sub, err := _Chequebook.contract.FilterLogs(opts, "Overdraft")
- if err != nil {
- return nil, err
- }
- return &ChequebookOverdraftIterator{contract: _Chequebook.contract, event: "Overdraft", logs: logs, sub: sub}, nil
-}
-
-// WatchOverdraft is a free log subscription operation binding the contract event 0x2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f978.
-//
-// Solidity: event Overdraft(deadbeat address)
-func (_Chequebook *ChequebookFilterer) WatchOverdraft(opts *bind.WatchOpts, sink chan<- *ChequebookOverdraft) (event.Subscription, error) {
-
- logs, sub, err := _Chequebook.contract.WatchLogs(opts, "Overdraft")
- if err != nil {
- return nil, err
- }
- return event.NewSubscription(func(quit <-chan struct{}) error {
- defer sub.Unsubscribe()
- for {
- select {
- case log := <-logs:
- // New log arrived, parse the event and forward to the user
- event := new(ChequebookOverdraft)
- if err := _Chequebook.contract.UnpackLog(event, "Overdraft", log); err != nil {
- return err
- }
- event.Raw = log
-
- select {
- case sink <- event:
- case err := <-sub.Err():
- return err
- case <-quit:
- return nil
- }
- case err := <-sub.Err():
- return err
- case <-quit:
- return nil
- }
- }
- }), nil
-}
diff --git a/contracts/chequebook/contract/chequebook.sol b/contracts/chequebook/contract/chequebook.sol
deleted file mode 100644
index c386cceed..000000000
--- a/contracts/chequebook/contract/chequebook.sol
+++ /dev/null
@@ -1,47 +0,0 @@
-pragma solidity ^0.4.18;
-
-import "./mortal.sol";
-
-/// @title Chequebook for Ethereum micropayments
-/// @author Daniel A. Nagy <daniel@ethereum.org>
-contract chequebook is mortal {
- // Cumulative paid amount in wei to each beneficiary
- mapping (address => uint256) public sent;
-
- /// @notice Overdraft event
- event Overdraft(address deadbeat);
-
- // Allow sending ether to the chequebook.
- function() public payable { }
-
- /// @notice Cash cheque
- ///
- /// @param beneficiary beneficiary address
- /// @param amount cumulative amount in wei
- /// @param sig_v signature parameter v
- /// @param sig_r signature parameter r
- /// @param sig_s signature parameter s
- /// The digital signature is calculated on the concatenated triplet of contract address, beneficiary address and cumulative amount
- function cash(address beneficiary, uint256 amount, uint8 sig_v, bytes32 sig_r, bytes32 sig_s) public {
- // Check if the cheque is old.
- // Only cheques that are more recent than the last cashed one are considered.
- require(amount > sent[beneficiary]);
- // Check the digital signature of the cheque.
- bytes32 hash = keccak256(address(this), beneficiary, amount);
- require(owner == ecrecover(hash, sig_v, sig_r, sig_s));
- // Attempt sending the difference between the cumulative amount on the cheque
- // and the cumulative amount on the last cashed cheque to beneficiary.
- uint256 diff = amount - sent[beneficiary];
- if (diff <= this.balance) {
- // update the cumulative amount before sending
- sent[beneficiary] = amount;
- beneficiary.transfer(diff);
- } else {
- // Upon failure, punish owner for writing a bounced cheque.
- // owner.sendToDebtorsPrison();
- Overdraft(owner);
- // Compensate beneficiary.
- selfdestruct(beneficiary);
- }
- }
-}
diff --git a/contracts/chequebook/contract/code.go b/contracts/chequebook/contract/code.go
deleted file mode 100644
index d837a9d60..000000000
--- a/contracts/chequebook/contract/code.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package contract
-
-// ContractDeployedCode is used to detect suicides. This constant needs to be
-// updated when the contract code is changed.
-const ContractDeployedCode = "0x6060604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166341c0e1b581146100585780637bf786f81461006b578063fbf788d61461009c575b005b341561006357600080fd5b6100566100ca565b341561007657600080fd5b61008a600160a060020a03600435166100f1565b60405190815260200160405180910390f35b34156100a757600080fd5b610056600160a060020a036004351660243560ff60443516606435608435610103565b60005433600160a060020a03908116911614156100ef57600054600160a060020a0316ff5b565b60016020526000908152604090205481565b600160a060020a0385166000908152600160205260408120548190861161012957600080fd5b3087876040516c01000000000000000000000000600160a060020a03948516810282529290931690910260148301526028820152604801604051809103902091506001828686866040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f115156101cf57600080fd5b505060206040510351600054600160a060020a039081169116146101f257600080fd5b50600160a060020a03808716600090815260016020526040902054860390301631811161026257600160a060020a0387166000818152600160205260409081902088905582156108fc0290839051600060405180830381858888f19350505050151561025d57600080fd5b6102b7565b6000547f2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f97890600160a060020a0316604051600160a060020a03909116815260200160405180910390a186600160a060020a0316ff5b505050505050505600a165627a7a72305820533e856fc37e3d64d1706bcc7dfb6b1d490c8d566ea498d9d01ec08965a896ca0029"
diff --git a/contracts/chequebook/contract/mortal.sol b/contracts/chequebook/contract/mortal.sol
deleted file mode 100644
index c43f1e4f7..000000000
--- a/contracts/chequebook/contract/mortal.sol
+++ /dev/null
@@ -1,10 +0,0 @@
-pragma solidity ^0.4.0;
-
-import "./owned.sol";
-
-contract mortal is owned {
- function kill() public {
- if (msg.sender == owner)
- selfdestruct(owner);
- }
-}
diff --git a/contracts/chequebook/contract/owned.sol b/contracts/chequebook/contract/owned.sol
deleted file mode 100644
index ee9860d34..000000000
--- a/contracts/chequebook/contract/owned.sol
+++ /dev/null
@@ -1,15 +0,0 @@
-pragma solidity ^0.4.0;
-
-contract owned {
- address owner;
-
- modifier onlyowner() {
- if (msg.sender == owner) {
- _;
- }
- }
-
- function owned() public {
- owner = msg.sender;
- }
-}
diff --git a/contracts/chequebook/gencode.go b/contracts/chequebook/gencode.go
deleted file mode 100644
index ddfe8d151..000000000
--- a/contracts/chequebook/gencode.go
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
-
-// +build none
-
-// This program generates contract/code.go, which contains the chequebook code
-// after deployment.
-package main
-
-import (
- "fmt"
- "io/ioutil"
- "math/big"
-
- "github.com/ethereum/go-ethereum/accounts/abi/bind"
- "github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
- "github.com/ethereum/go-ethereum/contracts/chequebook/contract"
- "github.com/ethereum/go-ethereum/core"
- "github.com/ethereum/go-ethereum/crypto"
-)
-
-var (
- testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
- testAlloc = core.GenesisAlloc{
- crypto.PubkeyToAddress(testKey.PublicKey): {Balance: big.NewInt(500000000000)},
- }
-)
-
-func main() {
- backend := backends.NewSimulatedBackend(testAlloc, uint64(100000000))
- auth := bind.NewKeyedTransactor(testKey)
-
- // Deploy the contract, get the code.
- addr, _, _, err := contract.DeployChequebook(auth, backend)
- if err != nil {
- panic(err)
- }
- backend.Commit()
- code, err := backend.CodeAt(nil, addr, nil)
- if err != nil {
- panic(err)
- }
- if len(code) == 0 {
- panic("empty code")
- }
-
- // Write the output file.
- content := fmt.Sprintf(`package contract
-
-// ContractDeployedCode is used to detect suicides. This constant needs to be
-// updated when the contract code is changed.
-const ContractDeployedCode = "%#x"
-`, code)
- if err := ioutil.WriteFile("contract/code.go", []byte(content), 0644); err != nil {
- panic(err)
- }
-}