Process ENS records
This commit is contained in:
parent
6fdf6e297c
commit
77561e3567
@ -21,6 +21,8 @@ const tokenTransferEventSignature = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f16
|
||||
const tokenERC1155TransferSingleEventSignature = "0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62"
|
||||
const tokenERC1155TransferBatchEventSignature = "0x4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb"
|
||||
|
||||
const nameRegisteredEventSignature = "0xca6abbe9d7f11422cb6ca7629fbf6fe9efb1c621f71ce8f02b9f2a230097404f"
|
||||
|
||||
const contractNameSignature = "0x06fdde03"
|
||||
const contractSymbolSignature = "0x95d89b41"
|
||||
const contractDecimalsSignature = "0x313ce567"
|
||||
|
||||
@ -163,16 +163,16 @@ func processParam(data string, index int, t *abi.Type, processed []bool) ([]stri
|
||||
}
|
||||
// get element count of dynamic type
|
||||
c, err := strconv.ParseInt(data[d:d+64], 16, 64)
|
||||
count := int(c)
|
||||
if err != nil {
|
||||
return nil, 0, false
|
||||
}
|
||||
count := int(c)
|
||||
processed[dynIndex] = true
|
||||
dynIndex++
|
||||
if t.T == abi.StringTy || t.T == abi.BytesTy {
|
||||
d += 64
|
||||
de := d + (count << 1)
|
||||
if de > len(data) {
|
||||
if de > len(data) || de < 0 {
|
||||
return nil, 0, false
|
||||
}
|
||||
if count == 0 {
|
||||
@ -292,3 +292,27 @@ func ParseInputData(signatures *[]bchain.FourByteSignature, data string) *bchain
|
||||
}
|
||||
return &parsed
|
||||
}
|
||||
|
||||
// getEnsRecord processes transaction log entry and tries to parse ENS record from it
|
||||
func getEnsRecord(l *rpcLogWithTxHash) *bchain.AddressAliasRecord {
|
||||
if len(l.Topics) == 3 && l.Topics[0] == nameRegisteredEventSignature && len(l.Data) >= 322 {
|
||||
address, err := addressFromPaddedHex(l.Topics[2])
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
c, err := strconv.ParseInt(l.Data[194:194+64], 16, 64)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
de := 194 + 64 + (int(c) << 1)
|
||||
if de > len(l.Data) || de < 0 {
|
||||
return nil
|
||||
}
|
||||
b, err := hex.DecodeString(l.Data[194+64 : de])
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return &bchain.AddressAliasRecord{Address: address, Name: string(b)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -367,3 +367,79 @@ func TestParseInputData(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_getEnsRecord(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
log rpcLogWithTxHash
|
||||
want *bchain.AddressAliasRecord
|
||||
}{
|
||||
{
|
||||
name: "unraveled",
|
||||
log: rpcLogWithTxHash{
|
||||
RpcLog: bchain.RpcLog{
|
||||
Address: "0x283Af0B28c62C092C9727F1Ee09c02CA627EB7F5",
|
||||
Topics: []string{
|
||||
"0xca6abbe9d7f11422cb6ca7629fbf6fe9efb1c621f71ce8f02b9f2a230097404f",
|
||||
"0x40ce2aa8cd9ee9fef4bf3a68abab7fbcceb6bac89370518caf6a602cefe836bd",
|
||||
"0x0000000000000000000000002c630b16aa53ae0189880e15c23323688acb607c",
|
||||
},
|
||||
Data: "0x00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000017629245f5a86f0000000000000000000000000000000000000000000000000000000069dbb21d0000000000000000000000000000000000000000000000000000000000000009756e726176656c65640000000000000000000000000000000000000000000000",
|
||||
},
|
||||
},
|
||||
want: &bchain.AddressAliasRecord{Address: "0x2C630b16Aa53ae0189880e15C23323688acb607c", Name: "unraveled"},
|
||||
},
|
||||
{
|
||||
name: "4x unraveled",
|
||||
log: rpcLogWithTxHash{
|
||||
RpcLog: bchain.RpcLog{
|
||||
Address: "0x283Af0B28c62C092C9727F1Ee09c02CA627EB7F5",
|
||||
Topics: []string{
|
||||
"0xca6abbe9d7f11422cb6ca7629fbf6fe9efb1c621f71ce8f02b9f2a230097404f",
|
||||
"0x40ce2aa8cd9ee9fef4bf3a68abab7fbcceb6bac89370518caf6a602cefe836bd",
|
||||
"0x0000000000000000000000002c630b16aa53ae0189880e15c23323688acb607c",
|
||||
},
|
||||
Data: "0x00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000017629245f5a86f0000000000000000000000000000000000000000000000000000000069dbb21d0000000000000000000000000000000000000000000000000000000000000024756e726176656c6564756e726176656c6564756e726176656c6564756e726176656c656400000000000000000000000000000000000000000000000000000000",
|
||||
},
|
||||
},
|
||||
want: &bchain.AddressAliasRecord{Address: "0x2C630b16Aa53ae0189880e15C23323688acb607c", Name: "unraveledunraveledunraveledunraveled"},
|
||||
},
|
||||
{
|
||||
name: "no signature",
|
||||
log: rpcLogWithTxHash{
|
||||
RpcLog: bchain.RpcLog{
|
||||
Address: "0x283Af0B28c62C092C9727F1Ee09c02CA627EB7F5",
|
||||
Topics: []string{
|
||||
"0xca6abbe9d7f11422cb6ca7629fbf6fe9efb1c621f71ce8f02b9f2a230097404e",
|
||||
"0x40ce2aa8cd9ee9fef4bf3a68abab7fbcceb6bac89370518caf6a602cefe836bd",
|
||||
"0x0000000000000000000000002c630b16aa53ae0189880e15c23323688acb607c",
|
||||
},
|
||||
Data: "0x00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000017629245f5a86f0000000000000000000000000000000000000000000000000000000069dbb21d0000000000000000000000000000000000000000000000000000000000000009756e726176656c65640000000000000000000000000000000000000000000000",
|
||||
},
|
||||
},
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "name length does not match",
|
||||
log: rpcLogWithTxHash{
|
||||
RpcLog: bchain.RpcLog{
|
||||
Address: "0x283Af0B28c62C092C9727F1Ee09c02CA627EB7F5",
|
||||
Topics: []string{
|
||||
"0xca6abbe9d7f11422cb6ca7629fbf6fe9efb1c621f71ce8f02b9f2a230097404f",
|
||||
"0x40ce2aa8cd9ee9fef4bf3a68abab7fbcceb6bac89370518caf6a602cefe836bd",
|
||||
"0x0000000000000000000000002c630b16aa53ae0189880e15c23323688acb607c",
|
||||
},
|
||||
Data: "0x00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000017629245f5a86f0000000000000000000000000000000000000000000000000000000069dbb21d0000000000000000000000000000000000000000000000000000000000000ff9756e726176656c65640000000000000000000000000000000000000000000000",
|
||||
},
|
||||
},
|
||||
want: nil,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := getEnsRecord(&tt.log); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("getEnsRecord() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -497,24 +497,28 @@ func (b *EthereumRPC) getBlockRaw(hash string, height uint32, fullTxs bool) (jso
|
||||
return raw, nil
|
||||
}
|
||||
|
||||
func (b *EthereumRPC) getTokenTransferEventsForBlock(blockNumber string) (map[string][]*bchain.RpcLog, error) {
|
||||
func (b *EthereumRPC) processEventsForBlock(blockNumber string) (map[string][]*bchain.RpcLog, []bchain.AddressAliasRecord, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), b.timeout)
|
||||
defer cancel()
|
||||
var logs []rpcLogWithTxHash
|
||||
var ensRecords []bchain.AddressAliasRecord
|
||||
err := b.rpc.CallContext(ctx, &logs, "eth_getLogs", map[string]interface{}{
|
||||
"fromBlock": blockNumber,
|
||||
"toBlock": blockNumber,
|
||||
// "topics": []string{tokenTransferEventSignature, tokenERC1155TransferSingleEventSignature, tokenERC1155TransferBatchEventSignature},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "blockNumber %v", blockNumber)
|
||||
return nil, nil, errors.Annotatef(err, "blockNumber %v", blockNumber)
|
||||
}
|
||||
r := make(map[string][]*bchain.RpcLog)
|
||||
for i := range logs {
|
||||
l := &logs[i]
|
||||
r[l.Hash] = append(r[l.Hash], &l.RpcLog)
|
||||
ens := getEnsRecord(l)
|
||||
if ens != nil {
|
||||
ensRecords = append(ensRecords, *ens)
|
||||
}
|
||||
}
|
||||
return r, nil
|
||||
return r, ensRecords, nil
|
||||
}
|
||||
|
||||
type rpcCallTrace struct {
|
||||
@ -636,17 +640,24 @@ func (b *EthereumRPC) GetBlock(hash string, height uint32) (*bchain.Block, error
|
||||
if err != nil {
|
||||
return nil, errors.Annotatef(err, "hash %v, height %v", hash, height)
|
||||
}
|
||||
// get contract transfers events
|
||||
logs, err := b.getTokenTransferEventsForBlock(head.Number)
|
||||
// get block events
|
||||
logs, ens, err := b.processEventsForBlock(head.Number)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// error fetching internal data does not stop the block processing
|
||||
var blockSpecificData *bchain.EthereumBlockSpecificData
|
||||
internalData, err := b.getInternalDataForBlock(head.Hash, body.Transactions)
|
||||
if err != nil {
|
||||
blockSpecificData = &bchain.EthereumBlockSpecificData{InternalDataError: err.Error()}
|
||||
glog.Info("InternalDataError ", bbh.Height, ": ", err.Error())
|
||||
if err != nil || len(ens) > 0 {
|
||||
blockSpecificData = &bchain.EthereumBlockSpecificData{}
|
||||
if err != nil {
|
||||
blockSpecificData.InternalDataError = err.Error()
|
||||
glog.Info("InternalDataError ", bbh.Height, ": ", err.Error())
|
||||
}
|
||||
if len(ens) > 0 {
|
||||
blockSpecificData.AddressAliasRecords = ens
|
||||
glog.Info("ENS", ens)
|
||||
}
|
||||
}
|
||||
|
||||
btxs := make([]bchain.Tx, len(body.Transactions))
|
||||
|
||||
@ -121,12 +121,21 @@ type RpcReceipt struct {
|
||||
Logs []*RpcLog `json:"logs"`
|
||||
}
|
||||
|
||||
// EthereumSpecificData contains data specific to Ethereum transactions
|
||||
type EthereumSpecificData struct {
|
||||
Tx *RpcTransaction `json:"tx"`
|
||||
InternalData *EthereumInternalData `json:"internalData,omitempty"`
|
||||
Receipt *RpcReceipt `json:"receipt,omitempty"`
|
||||
}
|
||||
|
||||
type EthereumBlockSpecificData struct {
|
||||
InternalDataError string
|
||||
// AddressAliasRecord maps address to ENS name
|
||||
type AddressAliasRecord struct {
|
||||
Address string
|
||||
Name string
|
||||
}
|
||||
|
||||
// EthereumBlockSpecificData contain data specific for Ethereum block
|
||||
type EthereumBlockSpecificData struct {
|
||||
InternalDataError string
|
||||
AddressAliasRecords []AddressAliasRecord
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user