Skip to content
This repository has been archived by the owner on Aug 2, 2021. It is now read-only.

contracts/swap, swap: refactor contractAddress, remove backend as inputParam, function order in contracts/swap #1748

Merged
merged 4 commits into from
Sep 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 56 additions & 53 deletions contracts/swap/swap.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ type Backend interface {
}

// Deploy deploys an instance of the underlying contract and returns its `Contract` abstraction
func Deploy(auth *bind.TransactOpts, backend bind.ContractBackend, owner common.Address, harddepositTimeout time.Duration) (common.Address, Contract, *types.Transaction, error) {
func Deploy(auth *bind.TransactOpts, backend bind.ContractBackend, owner common.Address, harddepositTimeout time.Duration) (Contract, *types.Transaction, error) {
addr, tx, s, err := contract.DeploySimpleSwap(auth, backend, owner, big.NewInt(int64(harddepositTimeout)))
c := simpleContract{instance: s, address: addr}
return addr, c, tx, err
return c, tx, err
}

// InstanceAt creates a new instance of a contract at a specific address.
Expand Down Expand Up @@ -86,64 +86,16 @@ type CashChequeResult struct {

// Params encapsulates some contract parameters (currently mostly informational)
type Params struct {
ContractCode, ContractAbi string
}

// ValidateCode checks that the on-chain code at address matches the expected swap
// contract code.
func ValidateCode(ctx context.Context, b bind.ContractBackend, address common.Address) error {
codeReadFromAddress, err := b.CodeAt(ctx, address, nil)
if err != nil {
return err
}
referenceCode := common.FromHex(contract.SimpleSwapDeployedCode)
if !bytes.Equal(codeReadFromAddress, referenceCode) {
return ErrNotASwapContract
}
return nil
}

// WaitFunc is the default function to wait for transactions
// We can overwrite this in tests so that we don't need to wait for mining
var WaitFunc = waitForTx

// waitForTx waits for transaction to be mined and returns the receipt
func waitForTx(auth *bind.TransactOpts, backend Backend, tx *types.Transaction) (*types.Receipt, error) {
// it blocks here until tx is mined
receipt, err := bind.WaitMined(auth.Context, backend, tx)
if err != nil {
return nil, err
}
// indicate whether the transaction did not revert
if receipt.Status != types.ReceiptStatusSuccessful {
return nil, ErrTransactionReverted
}
return receipt, nil
ContractCode string
ContractAbi string
ContractAddress common.Address
}

type simpleContract struct {
instance *contract.SimpleSwap
address common.Address
}

// ContractParams returns contract information
func (s simpleContract) ContractParams() *Params {
return &Params{
ContractCode: contract.SimpleSwapBin,
ContractAbi: contract.SimpleSwapABI,
}
}

// PaidOut returns the total paid out amount for the given address
func (s simpleContract) PaidOut(opts *bind.CallOpts, addr common.Address) (*big.Int, error) {
return s.instance.PaidOut(opts, addr)
}

// Issuer returns the contract owner from the blockchain
func (s simpleContract) Issuer(opts *bind.CallOpts) (common.Address, error) {
return s.instance.Issuer(opts)
}

// CashChequeBeneficiary cashes the cheque on the blockchain and blocks until the transaction is mined.
func (s simpleContract) CashChequeBeneficiary(auth *bind.TransactOpts, backend Backend, beneficiary common.Address, cumulativePayout *big.Int, ownerSig []byte) (*CashChequeResult, *types.Receipt, error) {
tx, err := s.instance.CashChequeBeneficiary(auth, beneficiary, cumulativePayout, ownerSig)
Expand Down Expand Up @@ -177,3 +129,54 @@ func (s simpleContract) CashChequeBeneficiary(auth *bind.TransactOpts, backend B

return result, receipt, nil
}

// ContractParams returns contract information
func (s simpleContract) ContractParams() *Params {
return &Params{
ContractCode: contract.SimpleSwapBin,
ContractAbi: contract.SimpleSwapABI,
ContractAddress: s.address,
}
}

// Issuer returns the contract owner from the blockchain
func (s simpleContract) Issuer(opts *bind.CallOpts) (common.Address, error) {
return s.instance.Issuer(opts)
}

// PaidOut returns the total paid out amount for the given address
func (s simpleContract) PaidOut(opts *bind.CallOpts, addr common.Address) (*big.Int, error) {
return s.instance.PaidOut(opts, addr)
}

// ValidateCode checks that the on-chain code at address matches the expected swap
// contract code.
func ValidateCode(ctx context.Context, b bind.ContractBackend, address common.Address) error {
codeReadFromAddress, err := b.CodeAt(ctx, address, nil)
if err != nil {
return err
}
referenceCode := common.FromHex(contract.SimpleSwapDeployedCode)
if !bytes.Equal(codeReadFromAddress, referenceCode) {
return ErrNotASwapContract
}
return nil
}

// WaitFunc is the default function to wait for transactions
// We can overwrite this in tests so that we don't need to wait for mining
var WaitFunc = waitForTx

// waitForTx waits for transaction to be mined and returns the receipt
func waitForTx(auth *bind.TransactOpts, backend Backend, tx *types.Transaction) (*types.Receipt, error) {
// it blocks here until tx is mined
receipt, err := bind.WaitMined(auth.Context, backend, tx)
if err != nil {
return nil, err
}
// indicate whether the transaction did not revert
if receipt.Status != types.ReceiptStatusSuccessful {
return nil, ErrTransactionReverted
}
return receipt, nil
}
2 changes: 1 addition & 1 deletion swap/peer.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ func (p *Peer) createCheque() (*Cheque, error) {
cheque = &Cheque{
ChequeParams: ChequeParams{
CumulativePayout: total + amount,
Contract: p.swap.owner.Contract,
Contract: p.swap.GetParams().ContractAddress,
Beneficiary: p.beneficiary,
},
Honey: honey,
Expand Down
2 changes: 1 addition & 1 deletion swap/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (s *Swap) run(p *p2p.Peer, rw p2p.MsgReadWriter) error {
protoPeer := protocols.NewPeer(p, rw, Spec)

handshake, err := protoPeer.Handshake(context.Background(), &HandshakeMsg{
ContractAddress: s.owner.Contract,
ContractAddress: s.GetParams().ContractAddress,
}, s.verifyHandshake)
if err != nil {
return err
Expand Down
19 changes: 12 additions & 7 deletions swap/protocol_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func TestHandshake(t *testing.T) {
defer clean()

ctx := context.Background()
err = testDeploy(ctx, swap.backend, swap)
err = testDeploy(ctx, swap)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -83,7 +83,7 @@ func TestHandshake(t *testing.T) {
{
Code: 0,
Msg: &HandshakeMsg{
ContractAddress: swap.owner.Contract,
ContractAddress: swap.GetParams().ContractAddress,
},
Peer: creditor.ID(),
},
Expand All @@ -92,7 +92,7 @@ func TestHandshake(t *testing.T) {
{
Code: 0,
Msg: &HandshakeMsg{
ContractAddress: swap.owner.Contract,
ContractAddress: swap.GetParams().ContractAddress,
},
Peer: debitor.ID(),
},
Expand Down Expand Up @@ -121,11 +121,11 @@ func TestEmitCheque(t *testing.T) {
ctx := context.Background()

log.Debug("deploy to simulated backend")
err := testDeploy(ctx, creditorSwap.backend, creditorSwap)
err := testDeploy(ctx, creditorSwap)
if err != nil {
t.Fatal(err)
}
err = testDeploy(ctx, debitorSwap.backend, debitorSwap)
err = testDeploy(ctx, debitorSwap)
if err != nil {
t.Fatal(err)
}
Expand All @@ -135,7 +135,7 @@ func TestEmitCheque(t *testing.T) {
// create the debitor peer
dPtpPeer := p2p.NewPeer(enode.ID{}, "debitor", []p2p.Cap{})
dProtoPeer := protocols.NewPeer(dPtpPeer, nil, Spec)
debitor, err := creditorSwap.addPeer(dProtoPeer, debitorSwap.owner.address, debitorSwap.owner.Contract)
debitor, err := creditorSwap.addPeer(dProtoPeer, debitorSwap.owner.address, debitorSwap.GetParams().ContractAddress)
if err != nil {
t.Fatal(err)
}
Expand All @@ -151,7 +151,7 @@ func TestEmitCheque(t *testing.T) {
log.Debug("create a cheque")
cheque := &Cheque{
ChequeParams: ChequeParams{
Contract: debitorSwap.owner.Contract,
Contract: debitorSwap.GetParams().ContractAddress,
Beneficiary: creditorSwap.owner.address,
CumulativePayout: 42,
},
Expand Down Expand Up @@ -202,6 +202,11 @@ func TestTriggerPaymentThreshold(t *testing.T) {
debitorSwap, clean := newTestSwap(t, ownerKey)
defer clean()

ctx := context.Background()
err := testDeploy(ctx, debitorSwap)
if err != nil {
t.Fatal(err)
}
mortelli marked this conversation as resolved.
Show resolved Hide resolved
// setup the wait for mined transaction function for testing
cleanup := setupContractTest()
defer cleanup()
Expand Down
26 changes: 9 additions & 17 deletions swap/swap.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ type Swap struct {

// Owner encapsulates information related to accessing the contract
type Owner struct {
Contract common.Address // address of swap contract
address common.Address // owner address
privateKey *ecdsa.PrivateKey // private key
publicKey *ecdsa.PublicKey // public key
Expand Down Expand Up @@ -130,7 +129,7 @@ func createOwner(prvkey *ecdsa.PrivateKey) *Owner {

// DeploySuccess is for convenience log output
func (s *Swap) DeploySuccess() string {
return fmt.Sprintf("contract: %s, owner: %s, deposit: %v, signer: %x", s.owner.Contract.Hex(), s.owner.address.Hex(), s.params.InitialDepositAmount, s.owner.publicKey)
return fmt.Sprintf("contract: %s, owner: %s, deposit: %v, signer: %x", s.GetParams().ContractAddress.Hex(), s.owner.address.Hex(), s.params.InitialDepositAmount, s.owner.publicKey)
Copy link
Contributor

@holisticode holisticode Sep 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not related to this PR, but your change reminds me of it: signer: %x........,s.owner.publickey actually prints garbage. Can you open an issue where we'd print the hex value of it? Thanks.

As it is a very small change, you could do it as part of this PR if you want.

}

// Add is the (sole) accounting function
Expand Down Expand Up @@ -217,7 +216,7 @@ func (s *Swap) handleEmitChequeMsg(ctx context.Context, p *Peer, msg *EmitCheque
// The function cashes the cheque by sending it to the blockchain
func cashCheque(s *Swap, otherSwap contract.Contract, opts *bind.TransactOpts, cheque *Cheque) {
// blocks here, as we are waiting for the transaction to be mined
result, receipt, err := otherSwap.CashChequeBeneficiary(opts, s.backend, s.owner.Contract, big.NewInt(int64(cheque.CumulativePayout)), cheque.Signature)
result, receipt, err := otherSwap.CashChequeBeneficiary(opts, s.backend, s.GetParams().ContractAddress, big.NewInt(int64(cheque.CumulativePayout)), cheque.Signature)
if err != nil {
// TODO: do something with the error
// and we actually need to log this error as we are in an async routine; nobody is handling this error for now
Expand Down Expand Up @@ -352,16 +351,11 @@ func (s *Swap) Close() error {
return s.store.Close()
}

// GetParams returns contract parameters (Bin, ABI) from the contract
// GetParams returns contract parameters (Bin, ABI, contractAddress) from the contract
func (s *Swap) GetParams() *swap.Params {
return s.contract.ContractParams()
}

// setChequebookAddr sets the chequebook address
func (s *Swap) setChequebookAddr(chequebookAddr common.Address) {
s.owner.Contract = chequebookAddr
}

// getContractOwner retrieve the owner of the chequebook at address from the blockchain
func (s *Swap) getContractOwner(ctx context.Context, address common.Address) (common.Address, error) {
contr, err := contract.InstanceAt(address, s.backend)
Expand All @@ -380,7 +374,7 @@ func (s *Swap) StartChequebook(chequebookAddr common.Address) error {
}
log.Info("Using the provided chequebook", "chequebookAddr", chequebookAddr)
} else {
if err := s.Deploy(context.Background(), s.backend); err != nil {
if err := s.Deploy(context.Background()); err != nil {
return err
}
log.Info("New SWAP contract deployed", "contract info", s.DeploySuccess())
Expand All @@ -398,42 +392,40 @@ func (s *Swap) BindToContractAt(address common.Address) (err error) {
if err != nil {
return err
}
s.setChequebookAddr(address)
return nil
}

// Deploy deploys the Swap contract and sets the contract address
func (s *Swap) Deploy(ctx context.Context, backend swap.Backend) error {
func (s *Swap) Deploy(ctx context.Context) error {
opts := bind.NewKeyedTransactor(s.owner.privateKey)
// initial topup value
opts.Value = big.NewInt(int64(s.params.InitialDepositAmount))
opts.Context = ctx

log.Info("deploying new swap", "owner", opts.From.Hex())
address, err := s.deployLoop(opts, backend, s.owner.address, defaultHarddepositTimeoutDuration)
address, err := s.deployLoop(opts, s.owner.address, defaultHarddepositTimeoutDuration)
if err != nil {
log.Error("unable to deploy swap", "error", err)
return err
}
s.setChequebookAddr(address)
log.Info("swap deployed", "address", address.Hex(), "owner", opts.From.Hex())

return err
}

// deployLoop repeatedly tries to deploy the swap contract .
func (s *Swap) deployLoop(opts *bind.TransactOpts, backend swap.Backend, owner common.Address, defaultHarddepositTimeoutDuration time.Duration) (addr common.Address, err error) {
func (s *Swap) deployLoop(opts *bind.TransactOpts, owner common.Address, defaultHarddepositTimeoutDuration time.Duration) (addr common.Address, err error) {
var tx *types.Transaction
for try := 0; try < deployRetries; try++ {
if try > 0 {
time.Sleep(deployDelay)
}

if _, s.contract, tx, err = contract.Deploy(opts, backend, owner, defaultHarddepositTimeoutDuration); err != nil {
if s.contract, tx, err = contract.Deploy(opts, s.backend, owner, defaultHarddepositTimeoutDuration); err != nil {
log.Warn("can't send chequebook deploy tx", "try", try, "error", err)
continue
}
if addr, err = bind.WaitDeployed(opts.Context, backend, tx); err != nil {
if addr, err = bind.WaitDeployed(opts.Context, s.backend, tx); err != nil {
log.Warn("chequebook deploy error", "try", try, "error", err)
continue
}
Expand Down
Loading