The following code segment demonstrates a Golang implementation for transaction submission.
import (
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
"math/big"
)
var privateKey = "01833a126ec45d0191519748146b9e35647aab7fed28de1c8e17824970f964a3"
type PaymentMessage struct {
ChainID *big.Int
Nonce uint64
To common.Address
Value *big.Int
Token *common.Address `rlp:"optional"`
}
type Signature struct {
R string
S string
V uint64
}
func SignMessage(msg *PaymentMessage) (*Signature, error) {
encoded, err := rlp.EncodeToBytes(msg)
if err != nil {
return nil, err
}
hash := crypto.Keccak256(encoded)
fmt.Printf("Signature Hash: %s\n", common.BytesToHash(hash))
key, err := crypto.HexToECDSA(privateKey)
if err != nil {
return nil, err
}
sign, err := crypto.Sign(hash, key)
if err != nil {
return nil, err
}
fmt.Printf("Signature: 0x%x\n", sign)
fmt.Printf("Raw bytes: %v\n", sign)
r := sign[:32]
s := sign[32:64]
v := sign[64]
return &Signature{
R: common.BytesToHash(r).Hex(),
S: common.BytesToHash(s).Hex(),
V: uint64(v),
}, nil
}
func main() {
tokenAddr := common.HexToAddress("0x2045a425D0e131E747f8be2F044413733e412d7d")
payment := &PaymentMessage{
ChainID: big.NewInt(1212101),
Nonce: 0,
To: common.HexToAddress("0x937b9aff6404141681cbf39301aeb869500bbdf0"),
Value: big.NewInt(1),
Token: &tokenAddr,
}
signature, err := SignMessage(payment)
if err != nil {
panic(fmt.Sprintf("sign payment msg error: %v", err))
}
fmt.Printf("Payment msg Signature: %v\n", signature)
}