Skip to content

Commit

Permalink
[action] add address and hash field in SealedEnvelope (#3420)
Browse files Browse the repository at this point in the history
* [action] add `address` and `hash` field in SealedEnvelope
  • Loading branch information
saitofun authored Jun 9, 2022
1 parent 7d66698 commit a222431
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 9 deletions.
5 changes: 5 additions & 0 deletions action/action_deserializer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"encoding/hex"
"testing"

"github.com/iotexproject/go-pkgs/hash"
"github.com/iotexproject/iotex-proto/golang/iotextypes"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/proto"
Expand All @@ -34,8 +35,12 @@ func TestActionDeserializer(t *testing.T) {
r.Equal(_signByte, se.Signature())
r.Zero(se.Encoding())

// use valid signature and reset se.Hash
se.signature = _validSig
se.hash = hash.ZeroHash256
se.Hash()
se1, err := (&Deserializer{}).ActionToSealedEnvelope(se.Proto())
se1.Hash()
r.NoError(err)
r.Equal(se, se1)
}
Expand Down
24 changes: 24 additions & 0 deletions action/sealedenvelope.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/iotexproject/go-pkgs/crypto"
"github.com/iotexproject/go-pkgs/hash"
"github.com/iotexproject/iotex-address/address"
"github.com/iotexproject/iotex-proto/golang/iotextypes"
"github.com/pkg/errors"
"go.uber.org/zap"
Expand All @@ -22,6 +23,8 @@ type SealedEnvelope struct {
evmNetworkID uint32
srcPubkey crypto.PublicKey
signature []byte
srcAddress address.Address
hash hash.Hash256
}

// envelopeHash returns the raw hash of embedded Envelope (this is the hash to be signed)
Expand All @@ -48,6 +51,17 @@ func (sealed *SealedEnvelope) envelopeHash() (hash.Hash256, error) {
// Hash returns the hash value of SealedEnvelope.
// an all-0 return value means the transaction is invalid
func (sealed *SealedEnvelope) Hash() (hash.Hash256, error) {
if sealed.hash == hash.ZeroHash256 {
hashVal, hashErr := sealed.calcHash()
if hashErr == nil {
sealed.hash = hashVal
}
return sealed.hash, hashErr
}
return sealed.hash, nil
}

func (sealed *SealedEnvelope) calcHash() (hash.Hash256, error) {
switch sealed.encoding {
case iotextypes.Encoding_ETHEREUM_RLP:
act, ok := sealed.Action().(EthCompatibleAction)
Expand All @@ -69,6 +83,14 @@ func (sealed *SealedEnvelope) Hash() (hash.Hash256, error) {
// SrcPubkey returns the source public key
func (sealed *SealedEnvelope) SrcPubkey() crypto.PublicKey { return sealed.srcPubkey }

// SenderAddress returns address of the source public key
func (sealed *SealedEnvelope) SenderAddress() address.Address {
if sealed.srcAddress == nil {
sealed.srcAddress = sealed.srcPubkey.Address()
}
return sealed.srcAddress
}

// Signature returns signature bytes
func (sealed *SealedEnvelope) Signature() []byte {
sig := make([]byte, len(sealed.signature))
Expand Down Expand Up @@ -141,6 +163,8 @@ func (sealed *SealedEnvelope) LoadProto(pbAct *iotextypes.Action) error {
sealed.signature = make([]byte, sigSize)
copy(sealed.signature, pbAct.GetSignature())
sealed.encoding = encoding
sealed.hash = hash.ZeroHash256
sealed.srcAddress = nil
return nil
}

Expand Down
10 changes: 7 additions & 3 deletions action/sealedenvelope_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,25 +156,29 @@ func TestSealedEnvelope_Proto(t *testing.T) {
req.Contains(se2.LoadProto(se.Proto()).Error(), v.err)
}

se.signature = _validSig
for _, v := range []struct {
enc iotextypes.Encoding
hash string
}{
{0, "0562e100b057804ee3cb4fa906a897852aa8075013a02ef1e229360f1e5ee339"},
{1, "d5dc789026c12cc69f1ea7997fbe0aa1bcc02e85176848c7b2ecf4da6b4560d0"},
} {
se, err = createSealedEnvelope(0)
se.signature = _validSig
se.encoding = v.enc
req.NoError(se2.LoadProto(se.Proto()))
if v.enc > 0 {
se.evmNetworkID = config.EVMNetworkID()
}
h, _ := se.Hash()
req.Equal(v.hash, hex.EncodeToString(h[:]))
se.SenderAddress()
_, _ = se2.Hash()
se2.SenderAddress()
req.Equal(se, se2)
tsf2, ok := se2.Envelope.Action().(*Transfer)
req.True(ok)
req.Equal(tsf, tsf2)
h, _ := se.Hash()
req.Equal(v.hash, hex.EncodeToString(h[:]))
}
}

Expand Down
20 changes: 18 additions & 2 deletions actpool/actpool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,15 @@ func TestActPool_GetUnconfirmedActs(t *testing.T) {
require.Equal([]action.SealedEnvelope(nil), acts)

acts = ap.GetUnconfirmedActs(_addr1)
require.Equal([]action.SealedEnvelope{tsf1, tsf3, tsf4, tsf5}, acts)
validated := []action.SealedEnvelope{tsf1, tsf3, tsf4, tsf5}
require.Equal(len(acts), len(validated))
for i := 0; i < len(acts); i++ {
hashVal1, hashErr1 := validated[i].Hash()
require.NoError(hashErr1)
hashVal2, hashErr2 := acts[i].Hash()
require.NoError(hashErr2)
require.Equal(hashVal1, hashVal2)
}
}

func TestActPool_GetActionByHash(t *testing.T) {
Expand Down Expand Up @@ -1089,7 +1097,15 @@ func TestActPool_SpeedUpAction(t *testing.T) {
appliedActionList = append(appliedActionList, bestAction)
}
// tsf1 is replaced by tsf3 with higher gas price
require.Equal(appliedActionList, []action.SealedEnvelope{tsf3, tsf2})
validated := []action.SealedEnvelope{tsf3, tsf2}
require.Equal(len(appliedActionList), len(validated))
for i := 0; i < len(appliedActionList); i++ {
hashVal1, hashErr1 := validated[i].Hash()
require.NoError(hashErr1)
hashVal2, hashErr2 := appliedActionList[i].Hash()
require.NoError(hashErr2)
require.Equal(hashVal1, hashVal2)
}
}

// Helper function to return the correct pending nonce just in case of empty queue
Expand Down
36 changes: 32 additions & 4 deletions blockchain/blockdao/blockdao_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,24 @@ func TestBlockDAO(t *testing.T) {
require.Equal(tipBlk.Height(), height)
blk, err := dao.GetBlock(hash)
require.NoError(err)
require.Equal(tipBlk, blk)
require.Equal(len(blk.Actions), len(tipBlk.Actions))
for i := 0; i < len(blk.Actions); i++ {
hashVal1, hashErr1 := blk.Actions[i].Hash()
require.NoError(hashErr1)
hashVal2, hashErr2 := tipBlk.Actions[i].Hash()
require.NoError(hashErr2)
require.Equal(hashVal1, hashVal2)
}
blk, err = dao.GetBlockByHeight(height)
require.NoError(err)
require.Equal(tipBlk, blk)
require.Equal(len(blk.Actions), len(tipBlk.Actions))
for i := 0; i < len(blk.Actions); i++ {
hashVal1, hashErr1 := blk.Actions[i].Hash()
require.NoError(hashErr1)
hashVal2, hashErr2 := tipBlk.Actions[i].Hash()
require.NoError(hashErr2)
require.Equal(hashVal1, hashVal2)
}
r, err := dao.GetReceipts(height)
require.NoError(err)
require.Equal(len(receipts[i]), len(r))
Expand Down Expand Up @@ -329,10 +343,24 @@ func TestBlockDAO(t *testing.T) {
require.Equal(tipHeight, height)
blk, err := dao.GetBlock(h)
require.NoError(err)
require.Equal(tipBlk, blk)
require.Equal(len(blk.Actions), len(tipBlk.Actions))
for i := 0; i < len(blk.Actions); i++ {
hashVal1, hashErr1 := blk.Actions[i].Hash()
require.NoError(hashErr1)
hashVal2, hashErr2 := tipBlk.Actions[i].Hash()
require.NoError(hashErr2)
require.Equal(hashVal1, hashVal2)
}
blk, err = dao.GetBlockByHeight(height)
require.NoError(err)
require.Equal(tipBlk, blk)
require.Equal(len(blk.Actions), len(tipBlk.Actions))
for i := 0; i < len(blk.Actions); i++ {
hashVal1, hashErr1 := blk.Actions[i].Hash()
require.NoError(hashErr1)
hashVal2, hashErr2 := tipBlk.Actions[i].Hash()
require.NoError(hashErr2)
require.Equal(hashVal1, hashVal2)
}

// test BlockDAO's API, 2nd loop to test LRU cache
for i := 0; i < 2; i++ {
Expand Down

0 comments on commit a222431

Please sign in to comment.