Skip to content

Commit 021e761

Browse files
authored
Merge pull request #38 from AudiusProject/mjp-rewards-2
Add Secp256k1 Instruction test, add EvaluateAttestations instruction
2 parents aa79580 + ce03174 commit 021e761

13 files changed

Lines changed: 376 additions & 42 deletions

api/solana/programs/reward-manager/EvaluateAttestations.go

Lines changed: 0 additions & 3 deletions
This file was deleted.

api/solana/programs/reward-manager/ChangeManagerAccount.go renamed to api/solana/programs/reward_manager/ChangeManagerAccount.go

File renamed without changes.
File renamed without changes.

api/solana/programs/reward-manager/CreateSenderPublic.go renamed to api/solana/programs/reward_manager/CreateSenderPublic.go

File renamed without changes.
File renamed without changes.

api/solana/programs/reward-manager/DeleteSenderPublic.go renamed to api/solana/programs/reward_manager/DeleteSenderPublic.go

File renamed without changes.
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
package reward_manager
2+
3+
import (
4+
"encoding/hex"
5+
"strings"
6+
7+
bin "github.com/gagliardetto/binary"
8+
"github.com/gagliardetto/solana-go"
9+
)
10+
11+
type EvaluateAttestation struct {
12+
// Instruction Data
13+
Amount uint64
14+
DisbursementID string
15+
ReceipientEthAddress string
16+
17+
// Used for derivations
18+
RewardManagerState solana.PublicKey `bin:"-" borsh_skip:"true"`
19+
Payer solana.PublicKey `bin:"-" borsh_skip:"true"`
20+
DestinationUserBank solana.PublicKey `bin:"-" borsh_skip:"true"`
21+
TokenSource solana.PublicKey `bin:"-" borsh_skip:"true"`
22+
AntiAbuseOracleEthAddress string `bin:"-" borsh_skip:"true"`
23+
24+
// Accounts
25+
solana.AccountMetaSlice `bin:"-" borsh_skip:"true"`
26+
}
27+
28+
func NewEvaluateAttestationInstructionBuilder() *EvaluateAttestation {
29+
data := &EvaluateAttestation{}
30+
return data
31+
}
32+
33+
func (inst *EvaluateAttestation) SetDisbursementID(challengedId string, specifier string) *EvaluateAttestation {
34+
inst.DisbursementID = challengedId + ":" + specifier
35+
return inst
36+
}
37+
38+
func (inst *EvaluateAttestation) SetRecipientEthAddress(recipientEthAddress string) *EvaluateAttestation {
39+
inst.ReceipientEthAddress = recipientEthAddress
40+
return inst
41+
}
42+
43+
func (inst *EvaluateAttestation) SetAmount(amount uint64) *EvaluateAttestation {
44+
inst.Amount = amount
45+
return inst
46+
}
47+
48+
func (inst *EvaluateAttestation) SetAntiAbuseOracleEthAddress(antiAbuseOracleAddress string) *EvaluateAttestation {
49+
inst.AntiAbuseOracleEthAddress = antiAbuseOracleAddress
50+
return inst
51+
}
52+
53+
func (inst *EvaluateAttestation) SetRewardManagerState(state solana.PublicKey) *EvaluateAttestation {
54+
inst.RewardManagerState = state
55+
return inst
56+
}
57+
58+
func (inst *EvaluateAttestation) SetTokenSource(tokenSource solana.PublicKey) *EvaluateAttestation {
59+
inst.TokenSource = tokenSource
60+
return inst
61+
}
62+
63+
func (inst *EvaluateAttestation) SetDestinationUserBank(userBank solana.PublicKey) *EvaluateAttestation {
64+
inst.DestinationUserBank = userBank
65+
return inst
66+
}
67+
68+
func (inst *EvaluateAttestation) SetPayer(payer solana.PublicKey) *EvaluateAttestation {
69+
inst.Payer = payer
70+
return inst
71+
}
72+
73+
func (inst EvaluateAttestation) Build() *Instruction {
74+
authority, _, _ := deriveAuthority(ProgramID, inst.RewardManagerState)
75+
attestations, _, _ := deriveAttestations(ProgramID, authority, inst.DisbursementID)
76+
disbursement, _, _ := deriveDisbursement(ProgramID, authority, inst.DisbursementID)
77+
antiAbuseOracle, _, _ := deriveSender(ProgramID, authority, inst.AntiAbuseOracleEthAddress)
78+
79+
inst.AccountMetaSlice = []*solana.AccountMeta{
80+
{
81+
PublicKey: attestations,
82+
IsSigner: false,
83+
IsWritable: true,
84+
},
85+
{
86+
PublicKey: inst.RewardManagerState,
87+
IsSigner: false,
88+
IsWritable: false,
89+
},
90+
{
91+
PublicKey: authority,
92+
IsSigner: false,
93+
IsWritable: false,
94+
},
95+
{
96+
PublicKey: inst.TokenSource,
97+
IsSigner: false,
98+
IsWritable: true,
99+
},
100+
{
101+
PublicKey: inst.DestinationUserBank,
102+
IsSigner: false,
103+
IsWritable: true,
104+
},
105+
{
106+
PublicKey: disbursement,
107+
IsSigner: false,
108+
IsWritable: true,
109+
},
110+
{
111+
PublicKey: antiAbuseOracle,
112+
IsSigner: false,
113+
IsWritable: false,
114+
},
115+
{
116+
PublicKey: inst.Payer,
117+
IsSigner: true,
118+
IsWritable: true,
119+
},
120+
{
121+
PublicKey: solana.SysVarRentPubkey,
122+
IsSigner: false,
123+
IsWritable: false,
124+
},
125+
{
126+
PublicKey: solana.TokenProgramID,
127+
IsSigner: false,
128+
IsWritable: false,
129+
},
130+
{
131+
PublicKey: solana.SystemProgramID,
132+
IsSigner: false,
133+
IsWritable: false,
134+
},
135+
}
136+
137+
return &Instruction{BaseVariant: bin.BaseVariant{
138+
Impl: inst,
139+
TypeID: bin.TypeIDFromUint8(Instruction_EvaluateAttestations),
140+
}}
141+
}
142+
143+
func (inst EvaluateAttestation) MarshalWithEncoder(encoder *bin.Encoder) error {
144+
err := encoder.Encode(inst.Amount)
145+
if err != nil {
146+
return err
147+
}
148+
149+
err = encoder.Encode(inst.DisbursementID)
150+
if err != nil {
151+
return err
152+
}
153+
154+
address, err := hex.DecodeString(strings.TrimPrefix(inst.ReceipientEthAddress, "0x"))
155+
if err != nil {
156+
return err
157+
}
158+
return encoder.WriteBytes(address, false)
159+
}
160+
161+
func (inst *EvaluateAttestation) UnmarshalWithDecoder(decoder *bin.Decoder) error {
162+
return decoder.Decode(&inst)
163+
}
164+
165+
func NewEvaluateAttestationInstruction(
166+
challengeId string,
167+
specifier string,
168+
recipientEthAddress string,
169+
amount uint64,
170+
antiAbuseOracleAddress string,
171+
rewardManagerState solana.PublicKey,
172+
tokenSource solana.PublicKey,
173+
destinationUserBank solana.PublicKey,
174+
payer solana.PublicKey,
175+
) *EvaluateAttestation {
176+
return NewEvaluateAttestationInstructionBuilder().
177+
SetRewardManagerState(rewardManagerState).
178+
SetDisbursementID(challengeId, specifier).
179+
SetRecipientEthAddress(recipientEthAddress).
180+
SetAmount(amount).
181+
SetAntiAbuseOracleEthAddress(antiAbuseOracleAddress).
182+
SetTokenSource(tokenSource).
183+
SetDestinationUserBank(destinationUserBank).
184+
SetPayer(payer)
185+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package reward_manager_test
2+
3+
import (
4+
"encoding/hex"
5+
"testing"
6+
7+
"bridgerton.audius.co/api/solana/programs/reward_manager"
8+
"github.com/gagliardetto/solana-go"
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
func TestEvaluateAttestationsInstruction(t *testing.T) {
13+
// Test data
14+
challengeId := "ft"
15+
specifier := "37364e80"
16+
recipientEthAddress := "0x3f6d9fcf0d4466dd5886e3b1def017adfb7916b4"
17+
amount := uint64(200000000)
18+
antiAbuseOracleEthAddress := "0x00b6462e955dA5841b6D9e1E2529B830F00f31Bf"
19+
20+
// Expected Accounts
21+
// From successful stage transaction (signature 26gT9HVMhzBDzsKcsiKREYmGcXuZhjAJpCVUu9WFNhVMyKje8SdApYc4ev3HrumZB4LEXLUaPnKyriBPLmtzwrWp)
22+
rewardState := solana.MustPublicKeyFromBase58("GaiG9LDYHfZGqeNaoGRzFEnLiwUT7WiC6sA6FDJX9ZPq")
23+
expectedAuthority := solana.MustPublicKeyFromBase58("6mpecd6bJCpH8oDwwjqPzTPU6QacnwW3cR9pAwEwkYJa")
24+
tokenSource := solana.MustPublicKeyFromBase58("HJQj8P47BdA7ugjQEn45LaESYrxhiZDygmukt8iumFZJ")
25+
destinationUserBank := solana.MustPublicKeyFromBase58("Cjv8dvVfWU8wUYAR82T5oZ4nHLB6EyGNvpPBzw3r76Qy")
26+
expectedDisbursement := solana.MustPublicKeyFromBase58("3qQfuDEBWEmxRo5G4J2a4eYUVf9u1LWzLgRPndiwew2w")
27+
expectedOracle := solana.MustPublicKeyFromBase58("FNz5mur7EFh1LyH5HDaKyWVx7vcfGK6gRizEpDqMfgGk")
28+
payer := solana.MustPublicKeyFromBase58("E3CfijtAJwBSHfwFEViAUd3xp7c8TBxwC1eXn1Fgxp8h")
29+
30+
// Expected Data (from same tx)
31+
expectedData, err := hex.DecodeString("0700c2eb0b000000000b00000066743a33373336346538303f6d9fcf0d4466dd5886e3b1def017adfb7916b4")
32+
require.NoError(t, err)
33+
34+
// Use stage program ID
35+
stageProgramId := solana.MustPublicKeyFromBase58("CDpzvz7DfgbF95jSSCHLX3ERkugyfgn9Fw8ypNZ1hfXp")
36+
reward_manager.SetProgramID(stageProgramId)
37+
38+
inst := reward_manager.NewEvaluateAttestationInstruction(
39+
challengeId,
40+
specifier,
41+
recipientEthAddress,
42+
amount,
43+
antiAbuseOracleEthAddress,
44+
rewardState,
45+
tokenSource,
46+
destinationUserBank,
47+
payer,
48+
).Build()
49+
50+
require.Equal(t, stageProgramId, inst.ProgramID())
51+
require.Len(t, inst.Accounts(), 11)
52+
require.Equal(t, rewardState.String(), inst.Accounts()[1].PublicKey.String())
53+
require.Equal(t, expectedAuthority.String(), inst.Accounts()[2].PublicKey.String())
54+
require.Equal(t, tokenSource.String(), inst.Accounts()[3].PublicKey.String())
55+
require.Equal(t, destinationUserBank.String(), inst.Accounts()[4].PublicKey.String())
56+
require.Equal(t, expectedDisbursement.String(), inst.Accounts()[5].PublicKey.String())
57+
require.Equal(t, expectedOracle.String(), inst.Accounts()[6].PublicKey.String())
58+
require.Equal(t, payer.String(), inst.Accounts()[7].PublicKey.String())
59+
60+
data, err := inst.Data()
61+
require.NoError(t, err)
62+
require.Equal(t, expectedData, data)
63+
}
File renamed without changes.

api/solana/programs/reward-manager/SubmitAttestation.go renamed to api/solana/programs/reward_manager/SubmitAttestation.go

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,20 @@
11
package reward_manager
22

33
import (
4-
"encoding/hex"
5-
64
bin "github.com/gagliardetto/binary"
75
"github.com/gagliardetto/solana-go"
86
)
97

10-
const (
11-
SenderSeedPrefix = "S_"
12-
EthAddressByteLength = 20
13-
AttestationsSeedPrefix = "V_"
14-
)
15-
168
type SubmitAttestation struct {
17-
DisbursementID string
9+
// Instruction Data
10+
DisbursementID string
11+
12+
// Used for derivations
1813
SenderEthAddress string `bin:"-" borsh_skip:"true"`
1914
RewardManagerState solana.PublicKey `bin:"-" borsh_skip:"true"`
2015
Payer solana.PublicKey `bin:"-" borsh_skip:"true"`
2116

17+
// Accounts
2218
solana.AccountMetaSlice `bin:"-" borsh_skip:"true"`
2319
}
2420

@@ -47,34 +43,6 @@ func (inst *SubmitAttestation) SetPayer(payer solana.PublicKey) *SubmitAttestati
4743
return inst
4844
}
4945

50-
func deriveAuthority(programId solana.PublicKey, state solana.PublicKey) (solana.PublicKey, uint8, error) {
51-
seeds := make([][]byte, 1)
52-
seeds[0] = state.Bytes()[0:32]
53-
return solana.FindProgramAddress(seeds, programId)
54-
}
55-
56-
func deriveSender(programId solana.PublicKey, authority solana.PublicKey, ethAddress string) (solana.PublicKey, uint8, error) {
57-
58-
senderSeedPrefix := []byte(SenderSeedPrefix)
59-
// Remove 0x and decode hex
60-
decodedEthAddress, err := hex.DecodeString(ethAddress[2:])
61-
if err != nil {
62-
return solana.PublicKey{}, 0, err
63-
}
64-
// Pad the eth address if necessary w/ leading 0
65-
senderSeed := make([]byte, len(senderSeedPrefix)+EthAddressByteLength)
66-
copy(senderSeed, senderSeedPrefix)
67-
copy(senderSeed[len(senderSeed)-len(decodedEthAddress):], decodedEthAddress)
68-
return solana.FindProgramAddress([][]byte{authority.Bytes()[0:32], senderSeed}, programId)
69-
}
70-
71-
func deriveAttestations(programId solana.PublicKey, authority solana.PublicKey, disbursementId string) (solana.PublicKey, uint8, error) {
72-
attestationsSeed := make([]byte, len(AttestationsSeedPrefix)+len(disbursementId))
73-
copy(attestationsSeed, []byte(AttestationsSeedPrefix))
74-
copy(attestationsSeed[len([]byte(AttestationsSeedPrefix)):], disbursementId)
75-
return solana.FindProgramAddress([][]byte{authority.Bytes()[0:32], attestationsSeed}, programId)
76-
}
77-
7846
func (inst SubmitAttestation) Build() *Instruction {
7947
authority, _, _ := deriveAuthority(ProgramID, inst.RewardManagerState)
8048
sender, _, _ := deriveSender(ProgramID, authority, inst.SenderEthAddress)

0 commit comments

Comments
 (0)