Implement PostedMessage fetching in the client

Change-Id: I8b59cdbfaf37212e187257cf46674086ad96d19d
This commit is contained in:
Hendrik Hofstadt 2021-06-18 18:50:06 +02:00
parent d84b61fda5
commit 02d7257ff5
6 changed files with 78 additions and 68 deletions

View File

@ -49,6 +49,7 @@ require (
github.com/mitchellh/go-homedir v1.1.0
github.com/mr-tron/base58 v1.2.0
github.com/multiformats/go-multiaddr v0.3.1
github.com/near/borsh-go v0.3.0
github.com/olekukonko/tablewriter v0.0.4 // indirect
github.com/pborman/uuid v1.2.1 // indirect
github.com/peterh/liner v1.2.1 // indirect

View File

@ -1009,6 +1009,8 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/near/borsh-go v0.3.0 h1:+DvG7eApOD3KrHIh7TwZvYzhXUF/OzMTC6aRTUEtW+8=
github.com/near/borsh-go v0.3.0/go.mod h1:NeMochZp7jN/pYFuxLkrZtmLqbADmnp/y1+/dL+AsyQ=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=

View File

@ -12,6 +12,7 @@ type MessagePublication struct {
Timestamp time.Time
Nonce uint32
Sequence uint64
EmitterChain vaa.ChainID
EmitterAddress vaa.Address
Payload []byte

View File

@ -1,10 +1,7 @@
package ethereum
import (
"bytes"
"context"
"encoding/binary"
"fmt"
"github.com/certusone/wormhole/bridge/pkg/common"
"github.com/certusone/wormhole/bridge/pkg/p2p"
gossipv1 "github.com/certusone/wormhole/bridge/pkg/proto/gossip/v1"
@ -14,9 +11,9 @@ import (
"github.com/dfuse-io/solana-go/rpc"
eth_common "github.com/ethereum/go-ethereum/common"
"github.com/mr-tron/base58"
"github.com/near/borsh-go"
"github.com/prometheus/client_golang/prometheus"
"go.uber.org/zap"
"math/big"
"time"
)
@ -115,13 +112,10 @@ func (s *SolanaWatcher) Run(ctx context.Context) error {
accounts, err := rpcClient.GetProgramAccounts(rCtx, s.bridge, &rpc.GetProgramAccountsOpts{
Commitment: rpc.CommitmentMax, // TODO: deprecated, use Finalized
Filters: []rpc.RPCFilter{
{
DataSize: 1184, // Search for MessagePublicationAccount accounts
},
{
Memcmp: &rpc.RPCFilterMemcmp{
Offset: 1140, // Offset of VaaTime
Bytes: solana.Base58{0, 0, 0, 0}, // VAA time is 0 when no VAA is present
Offset: 0, // Offset of VaaTime
Bytes: solana.Base58{'m', 's', 'g'}, // Prefix of the posted message accounts
},
},
},
@ -151,7 +145,7 @@ func (s *SolanaWatcher) Run(ctx context.Context) error {
}
// VAA submitted
if proposal.VaaTime.Unix() != 0 {
if proposal.VaaTime != 0 {
solanaAccountSkips.WithLabelValues("is_submitted_vaa").Inc()
continue
}
@ -160,17 +154,13 @@ func (s *SolanaWatcher) Run(ctx context.Context) error {
copy(txHash[:], acc.Pubkey[:])
lock := &common.MessagePublication{
TxHash: txHash,
Timestamp: proposal.LockupTime,
Nonce: proposal.Nonce,
SourceAddress: proposal.SourceAddress,
TargetAddress: proposal.ForeignAddress,
SourceChain: vaa.ChainIDSolana,
TargetChain: proposal.ToChainID,
TokenChain: proposal.Asset.Chain,
TokenAddress: proposal.Asset.Address,
TokenDecimals: proposal.Asset.Decimals,
Amount: proposal.Amount,
TxHash: txHash,
Timestamp: time.Unix(int64(proposal.SubmissionTime), 0),
Nonce: proposal.Nonce,
Sequence: proposal.Sequence,
EmitterChain: proposal.EmitterChain,
EmitterAddress: proposal.EmitterAddress,
Payload: proposal.Payload,
}
solanaLockupsConfirmed.Inc()
@ -193,10 +183,11 @@ func (s *SolanaWatcher) Run(ctx context.Context) error {
type (
MessagePublicationAccount struct {
VaaVersion uint8
VaaTime time.Time
VaaTime uint32
VaaSignatureAccount vaa.Address
SubmissionTime time.Time
SubmissionTime uint32
Nonce uint32
Sequence uint64
EmitterChain vaa.ChainID
EmitterAddress vaa.Address
Payload []byte
@ -205,49 +196,9 @@ type (
func ParseTransferOutProposal(data []byte) (*MessagePublicationAccount, error) {
prop := &MessagePublicationAccount{}
r := bytes.NewBuffer(data)
// Skip initialized bool
r.Next(1)
if err := binary.Read(r, binary.LittleEndian, &prop.VaaVersion); err != nil {
return nil, fmt.Errorf("failed to read to vaa version: %w", err)
if err := borsh.Deserialize(prop, data); err != nil {
return nil, err
}
var vaaTime uint32
if err := binary.Read(r, binary.LittleEndian, &vaaTime); err != nil {
return nil, fmt.Errorf("failed to read vaa time: %w", err)
}
prop.VaaTime = time.Unix(int64(vaaTime), 0)
if n, err := r.Read(prop.VaaSignatureAccount[:]); err != nil || n != 32 {
return nil, fmt.Errorf("failed to read signature account: %w", err)
}
var submissionTime uint32
if err := binary.Read(r, binary.LittleEndian, &submissionTime); err != nil {
return nil, fmt.Errorf("failed to read lockup time: %w", err)
}
prop.SubmissionTime = time.Unix(int64(submissionTime), 0)
if err := binary.Read(r, binary.LittleEndian, &prop.Nonce); err != nil {
return nil, fmt.Errorf("failed to read nonce: %w", err)
}
if err := binary.Read(r, binary.LittleEndian, &prop.EmitterChain); err != nil {
return nil, fmt.Errorf("failed to read emitter chain: %w", err)
}
if n, err := r.Read(prop.EmitterAddress[:]); err != nil || n != 32 {
return nil, fmt.Errorf("failed to read emitter address: %w", err)
}
payload := make([]byte, 1000)
n, err := r.Read(payload)
if err != nil || n == 0 {
return nil, fmt.Errorf("failed to read vaa: %w", err)
}
prop.Payload = payload[:n]
return prop, nil
}

View File

@ -27,6 +27,8 @@ type (
Timestamp time.Time
// Nonce of the VAA
Nonce uint32
// Sequence of the VAA
Sequence uint64
// EmitterChain the VAA was emitted on
EmitterChain ChainID
// EmitterAddress of the contract that emitted the Message
@ -36,7 +38,7 @@ type (
}
// ChainID of a Wormhole chain
ChainID uint8
ChainID uint16
// Action of a VAA
Action uint8

View File

@ -1,5 +1,9 @@
use crate::{
api::ForeignAddress,
api::{
ForeignAddress,
PostMessage,
PostMessageData,
},
vaa::{
DeserializeGovernancePayload,
DeserializePayload,
@ -26,6 +30,11 @@ use std::{
io::{
Cursor,
Read,
Write,
},
ops::{
Deref,
DerefMut,
},
str::FromStr,
};
@ -104,8 +113,52 @@ impl Owned for SignatureSet {
}
}
#[repr(transparent)]
pub struct PostedMessage(pub PostedMessageData);
impl BorshSerialize for PostedMessage {
fn serialize<W: Write>(&self, writer: &mut W) -> std::io::Result<()> {
writer.write(&['m' as u8, 's' as u8, 'g' as u8]);
BorshSerialize::serialize(&self.0, writer)
}
}
impl BorshDeserialize for PostedMessage {
fn deserialize(buf: &mut &[u8]) -> std::io::Result<Self> {
Ok(PostedMessage(
<PostedMessageData as BorshDeserialize>::deserialize(&mut &buf[3..])?,
))
}
}
impl Deref for PostedMessage {
type Target = PostedMessageData;
fn deref(&self) -> &Self::Target {
unsafe { std::mem::transmute(&self.0) }
}
}
impl DerefMut for PostedMessage {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { std::mem::transmute(&mut self.0) }
}
}
impl Default for PostedMessage {
fn default() -> Self {
PostedMessage(PostedMessageData::default())
}
}
impl Clone for PostedMessage {
fn clone(&self) -> Self {
PostedMessage(self.0.clone())
}
}
#[derive(Default, BorshSerialize, BorshDeserialize, Clone)]
pub struct PostedMessage {
pub struct PostedMessageData {
/// Header of the posted VAA
pub vaa_version: u8,