/
tx.go
118 lines (103 loc) · 3.7 KB
/
tx.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package evm
import (
"context"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/renproject/id"
"github.com/renproject/multichain/api/account"
"github.com/renproject/multichain/api/address"
"github.com/renproject/multichain/api/contract"
"github.com/renproject/pack"
)
// TxBuilder represents a transaction builder that builds transactions to be
// broadcasted to the ethereum network. The TxBuilder is configured using a
// chain id.
type TxBuilder struct {
ChainID *big.Int
}
// NewTxBuilder creates a new transaction builder.
func NewTxBuilder(chainID *big.Int) TxBuilder {
return TxBuilder{chainID}
}
// BuildTx receives transaction fields and constructs a new transaction.
func (txBuilder TxBuilder) BuildTx(ctx context.Context, fromPubKey *id.PubKey, to address.Address, value, nonce, gasLimit, gasPrice, gasCap pack.U256, payload pack.Bytes) (account.Tx, error) {
toAddr, err := NewAddressFromHex(string(pack.String(to)))
if err != nil {
return nil, fmt.Errorf("bad to address '%v': %v", to, err)
}
addr := common.Address(toAddr)
return &Tx{
EthTx: types.NewTransaction(nonce.Int().Uint64(),
addr, value.Int(),
gasLimit.Int().Uint64(),
gasPrice.Int(),
payload,
),
Signer: types.LatestSignerForChainID(txBuilder.ChainID),
}, nil
}
// Tx represents a ethereum transaction, encapsulating a payload/data and its
// Signer.
type Tx struct {
EthTx *types.Transaction
Signer types.Signer
}
// Hash returns the hash that uniquely identifies the transaction.
// Generally, hashes are irreversible hash functions that consume the
// content of the transaction.
func (tx Tx) Hash() pack.Bytes {
return tx.EthTx.Hash().Bytes()
}
// From returns the address that is sending the transaction. Generally,
// this is also the address that must sign the transaction.
func (tx Tx) From() address.Address {
addr, err := types.Sender(tx.Signer, tx.EthTx)
if err != nil {
return address.Address("")
}
return address.Address(addr.Hex())
}
// To returns the address that is receiving the transaction. This can be the
// address of an external account, controlled by a private key, or it can be
// the address of a contract.
func (tx Tx) To() address.Address {
return address.Address(tx.EthTx.To().Hex())
}
// Value being sent from the sender to the receiver.
func (tx Tx) Value() pack.U256 {
return pack.NewU256FromInt(tx.EthTx.Value())
}
// Nonce returns the nonce used to order the transaction with respect to all
// other transactions signed and submitted by the sender.
func (tx Tx) Nonce() pack.U256 {
return pack.NewU256FromU64(pack.NewU64(tx.EthTx.Nonce()))
}
// Payload returns arbitrary data that is associated with the transaction.
// Generally, this payload is used to send notes between external accounts,
// or invoke business logic on a contract.
func (tx Tx) Payload() contract.CallData {
return contract.CallData(tx.EthTx.Data())
}
// Sighashes returns the digests that must be signed before the transaction
// can be submitted by the client.
func (tx Tx) Sighashes() ([]pack.Bytes32, error) {
return []pack.Bytes32{pack.Bytes32(tx.Signer.Hash(tx.EthTx))}, nil
}
// Sign the transaction by injecting signatures for the required sighashes.
// The serialized public key used to sign the sighashes must also be
// specified.
func (tx *Tx) Sign(signatures []pack.Bytes65, pubkey pack.Bytes) error {
signedtx, err := tx.EthTx.WithSignature(tx.Signer, signatures[0].Bytes())
if err != nil {
return err
}
tx.EthTx = signedtx
return nil
}
// Serialize the transaction into bytes. Generally, this is the format in
// which the transaction will be submitted by the client.
func (tx Tx) Serialize() (pack.Bytes, error) {
return tx.EthTx.MarshalBinary()
}