Skip to content

Commit

Permalink
Merge pull request #1920 from cheng762/develop
Browse files Browse the repository at this point in the history
merge eth updates
  • Loading branch information
benbaley authored Apr 8, 2022
2 parents 66ed834 + abae9d8 commit c5aa0ec
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 30 deletions.
25 changes: 25 additions & 0 deletions accounts/abi/bind/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"errors"
"fmt"
"math/big"
"strings"
"sync"

platon "github.com/PlatONnetwork/PlatON-Go"

Expand Down Expand Up @@ -75,6 +77,29 @@ type WatchOpts struct {
Context context.Context // Network context to support cancellation and timeouts (nil = no timeout)
}

// MetaData collects all metadata for a bound contract.
type MetaData struct {
mu sync.Mutex
Sigs map[string]string
Bin string
ABI string
ab *abi.ABI
}

func (m *MetaData) GetAbi() (*abi.ABI, error) {
m.mu.Lock()
defer m.mu.Unlock()
if m.ab != nil {
return m.ab, nil
}
if parsed, err := abi.JSON(strings.NewReader(m.ABI)); err != nil {
return nil, err
} else {
m.ab = &parsed
}
return m.ab, nil
}

// BoundContract is the base wrapper object that reflects a contract on the
// platon network. It contains a collection of methods that are used by the
// higher level contract bindings to operate.
Expand Down
34 changes: 26 additions & 8 deletions accounts/abi/bind/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ package {{.Package}}
import (
"math/big"
"strings"
"errors"
platon "github.com/PlatONnetwork/PlatON-Go"
"github.com/PlatONnetwork/PlatON-Go/accounts/abi"
Expand All @@ -101,6 +102,7 @@ import (
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = errors.New
_ = big.NewInt
_ = strings.NewReader
_ = platon.NotFound
Expand All @@ -120,32 +122,48 @@ var (
{{end}}
{{range $contract := .Contracts}}
// {{.Type}}MetaData contains all meta data concerning the {{.Type}} contract.
var {{.Type}}MetaData = &bind.MetaData{
ABI: "{{.InputABI}}",
{{if $contract.FuncSigs -}}
Sigs: map[string]string{
{{range $strsig, $binsig := .FuncSigs}}"{{$binsig}}": "{{$strsig}}",
{{end}}
},
{{end -}}
{{if .InputBin -}}
Bin: "0x{{.InputBin}}",
{{end}}
}
// {{.Type}}ABI is the input ABI used to generate the binding from.
const {{.Type}}ABI = "{{.InputABI}}"
// Deprecated: Use {{.Type}}MetaData.ABI instead.
var {{.Type}}ABI = {{.Type}}MetaData.ABI
{{if $contract.FuncSigs}}
// Deprecated: Use {{.Type}}MetaData.Sigs instead.
// {{.Type}}FuncSigs maps the 4-byte function signature to its string representation.
var {{.Type}}FuncSigs = map[string]string{
{{range $strsig, $binsig := .FuncSigs}}"{{$binsig}}": "{{$strsig}}",
{{end}}
}
var {{.Type}}FuncSigs = {{.Type}}MetaData.Sigs
{{end}}
{{if .InputBin}}
// {{.Type}}Bin is the compiled bytecode used for deploying new contracts.
var {{.Type}}Bin = "0x{{.InputBin}}"
// Deprecated: Use {{.Type}}MetaData.Bin instead.
var {{.Type}}Bin = {{.Type}}MetaData.Bin
// Deploy{{.Type}} deploys a new platon contract, binding an instance of {{.Type}} to it.
func Deploy{{.Type}}(auth *bind.TransactOpts, backend bind.ContractBackend {{range .Constructor.Inputs}}, {{.Name}} {{bindtype .Type $structs}}{{end}}) (common.Address, *types.Transaction, *{{.Type}}, error) {
parsed, err := abi.JSON(strings.NewReader({{.Type}}ABI))
parsed, err := {{.Type}}MetaData.GetAbi()
if err != nil {
return common.Address{}, nil, nil, err
}
if parsed == nil {
return common.Address{}, nil, nil, errors.New("GetABI returned nil")
}
{{range $pattern, $name := .Libraries}}
{{decapitalise $name}}Addr, _, _, _ := Deploy{{capitalise $name}}(auth, backend)
{{$contract.Type}}Bin = strings.Replace({{$contract.Type}}Bin, "__${{$pattern}}$__", {{decapitalise $name}}Addr.String()[2:], -1)
{{end}}
address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex({{.Type}}Bin), backend {{range .Constructor.Inputs}}, {{.Name}}{{end}})
address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex({{.Type}}Bin), backend {{range .Constructor.Inputs}}, {{.Name}}{{end}})
if err != nil {
return common.Address{}, nil, nil, err
}
Expand Down
29 changes: 29 additions & 0 deletions accounts/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@
package accounts

import (
"fmt"
"math/big"

"golang.org/x/crypto/sha3"

ethereum "github.com/PlatONnetwork/PlatON-Go"
"github.com/PlatONnetwork/PlatON-Go/common"
"github.com/PlatONnetwork/PlatON-Go/core/types"
Expand Down Expand Up @@ -148,6 +151,32 @@ type Backend interface {
Subscribe(sink chan<- WalletEvent) event.Subscription
}

// TextHash is a helper function that calculates a hash for the given message that can be
// safely used to calculate a signature from.
//
// The hash is calulcated as
// keccak256("\x19Ethereum Signed Message:\n"${message length}${message}).
//
// This gives context to the signed message and prevents signing of transactions.
func TextHash(data []byte) []byte {
hash, _ := TextAndHash(data)
return hash
}

// TextAndHash is a helper function that calculates a hash for the given message that can be
// safely used to calculate a signature from.
//
// The hash is calulcated as
// keccak256("\x19Ethereum Signed Message:\n"${message length}${message}).
//
// This gives context to the signed message and prevents signing of transactions.
func TextAndHash(data []byte) ([]byte, string) {
msg := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(data), string(data))
hasher := sha3.NewLegacyKeccak256()
hasher.Write([]byte(msg))
return hasher.Sum(nil), msg
}

// WalletEventType represents the different event types that can be fired by
// the wallet subscription subsystem.
type WalletEventType int
Expand Down
2 changes: 1 addition & 1 deletion core/types/transaction_signing.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ func recoverPlain(sighash common.Hash, R, S, Vb *big.Int, homestead bool) (commo
}
// encode the signature in uncompressed format
r, s := R.Bytes(), S.Bytes()
sig := make([]byte, 65)
sig := make([]byte, crypto.SignatureLength)
copy(sig[32-len(r):32], r)
copy(sig[64-len(s):64], s)
sig[64] = V
Expand Down
12 changes: 11 additions & 1 deletion crypto/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,28 @@ import (
"encoding/hex"
"errors"
"fmt"
"golang.org/x/crypto/sha3"
"hash"
"io"
"io/ioutil"
"math/big"
"os"

"golang.org/x/crypto/sha3"

"github.com/PlatONnetwork/PlatON-Go/common"
"github.com/PlatONnetwork/PlatON-Go/common/math"
"github.com/PlatONnetwork/PlatON-Go/rlp"
)

//SignatureLength indicates the byte length required to carry a signature with recovery id.
const SignatureLength = 64 + 1 // 64 bytes ECDSA signature + 1 byte recovery id

// RecoveryIDOffset points to the byte offset within the signature that contains the recovery id.
const RecoveryIDOffset = 64

// DigestLength sets the signature digest exact length
const DigestLength = 32

var (
secp256k1N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
secp256k1halfN = new(big.Int).Div(secp256k1N, big.NewInt(2))
Expand Down
17 changes: 9 additions & 8 deletions crypto/signature_cgo.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// 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/>.

//go:build !nacl && !js && !nocgo
// +build !nacl,!js,!nocgo

package crypto
Expand Down Expand Up @@ -47,24 +48,24 @@ func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
//
// This function is susceptible to chosen plaintext attacks that can leak
// information about the private key that is used for signing. Callers must
// be aware that the given hash cannot be chosen by an adversery. Common
// be aware that the given digest cannot be chosen by an adversery. Common
// solution is to hash any input before calculating the signature.
//
// The produced signature is in the [R || S || V] format where V is 0 or 1.
func Sign(hash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) {
if len(hash) != 32 {
return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash))
func Sign(digestHash []byte, prv *ecdsa.PrivateKey) (sig []byte, err error) {
if len(digestHash) != DigestLength {
return nil, fmt.Errorf("hash is required to be exactly %d bytes (%d)", DigestLength, len(digestHash))
}
seckey := math.PaddedBigBytes(prv.D, prv.Params().BitSize/8)
defer zeroBytes(seckey)
return secp256k1.Sign(hash, seckey)
return secp256k1.Sign(digestHash, seckey)
}

// VerifySignature checks that the given public key created signature over hash.
// VerifySignature checks that the given public key created signature over digest.
// The public key should be in compressed (33 bytes) or uncompressed (65 bytes) format.
// The signature should have the 64 byte [R || S] format.
func VerifySignature(pubkey, hash, signature []byte) bool {
return secp256k1.VerifySignature(pubkey, hash, signature)
func VerifySignature(pubkey, digestHash, signature []byte) bool {
return secp256k1.VerifySignature(pubkey, digestHash, signature)
}

// DecompressPubkey parses a public key in the 33-byte compressed format.
Expand Down
3 changes: 2 additions & 1 deletion crypto/signature_nocgo.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// 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/>.

//go:build nacl || js || nocgo
// +build nacl js nocgo

package crypto
Expand Down Expand Up @@ -41,7 +42,7 @@ func Ecrecover(hash, sig []byte) ([]byte, error) {
// SigToPub returns the public key that created the given signature.
func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
// Convert to btcec input format with 'recovery id' v at the beginning.
btcsig := make([]byte, 65)
btcsig := make([]byte, SignatureLength)
btcsig[0] = sig[64] + 27
copy(btcsig[1:], sig)

Expand Down
7 changes: 7 additions & 0 deletions ethclient/ethclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ func (ec *Client) BlockByNumber(ctx context.Context, number *big.Int) (*types.Bl
return ec.getBlock(ctx, "platon_getBlockByNumber", toBlockNumArg(number), true)
}

// BlockNumber returns the most recent block number
func (ec *Client) BlockNumber(ctx context.Context) (uint64, error) {
var result hexutil.Uint64
err := ec.c.CallContext(ctx, &result, "eth_blockNumber")
return uint64(result), err
}

type rpcBlock struct {
Hash common.Hash `json:"hash"`
Transactions []rpcTransaction `json:"transactions"`
Expand Down
10 changes: 5 additions & 5 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ func (s *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr c
log.Warn("Failed data sign attempt", "address", addr, "err", err)
return nil, err
}
signature[64] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper
signature[crypto.RecoveryIDOffset] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper
return signature, nil
}

Expand All @@ -470,13 +470,13 @@ func (s *PrivateAccountAPI) Sign(ctx context.Context, data hexutil.Bytes, addr c
//
// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_ecRecover
func (s *PrivateAccountAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error) {
if len(sig) != 65 {
return common.Address{}, fmt.Errorf("signature must be 65 bytes long")
if len(sig) != crypto.SignatureLength {
return common.Address{}, fmt.Errorf("signature must be %d bytes long", crypto.SignatureLength)
}
if sig[64] != 27 && sig[64] != 28 {
if sig[crypto.RecoveryIDOffset] != 27 && sig[crypto.RecoveryIDOffset] != 28 {
return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)")
}
sig[64] -= 27 // Transform yellow paper V from 27/28 to 0/1
sig[crypto.RecoveryIDOffset] -= 27 // Transform yellow paper V from 27/28 to 0/1

rpk, err := crypto.SigToPub(signHash(data), sig)
if err != nil {
Expand Down
13 changes: 7 additions & 6 deletions p2p/rlpx.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ import (
"encoding/binary"
"errors"
"fmt"
"github.com/PlatONnetwork/PlatON-Go/log"
"golang.org/x/crypto/sha3"
"hash"
"io"
"io/ioutil"
Expand All @@ -37,6 +35,9 @@ import (
"sync"
"time"

"github.com/PlatONnetwork/PlatON-Go/log"
"golang.org/x/crypto/sha3"

"github.com/PlatONnetwork/PlatON-Go/crypto"
"github.com/PlatONnetwork/PlatON-Go/crypto/ecies"
"github.com/PlatONnetwork/PlatON-Go/p2p/discover"
Expand All @@ -47,10 +48,10 @@ import (
const (
maxUint24 = ^uint32(0) >> 8

sskLen = 16 // ecies.MaxSharedKeyLength(pubKey) / 2
sigLen = 65 // elliptic S256
pubLen = 64 // 512 bit pubkey in uncompressed representation without format byte
shaLen = 32 // hash length (for nonce etc)
sskLen = 16 // ecies.MaxSharedKeyLength(pubKey) / 2
sigLen = crypto.SignatureLength // elliptic S256
pubLen = 64 // 512 bit pubkey in uncompressed representation without format byte
shaLen = 32 // hash length (for nonce etc)

authMsgLen = sigLen + shaLen + pubLen + shaLen + 1
authRespLen = pubLen + shaLen + 1
Expand Down

0 comments on commit c5aa0ec

Please sign in to comment.