Skip to content

Commit

Permalink
Merge pull request #133 from coinbase/patrick/inject-pubkeys-during-c…
Browse files Browse the repository at this point in the history
…onstruction

[Constructor] Inject Public Keys During Transaction Construction
  • Loading branch information
patrick-ogrady committed Sep 4, 2020
2 parents d549c50 + 05a8576 commit 701531d
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 36 deletions.
25 changes: 23 additions & 2 deletions constructor/coordinator/coordinator.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,10 @@ func (c *Coordinator) findJob(
// createTransaction constructs and signs a transaction with the provided intent.
func (c *Coordinator) createTransaction(
ctx context.Context,
dbTx storage.DatabaseTransaction,
broadcast *job.Broadcast,
) (*types.TransactionIdentifier, string, error) {
metadataRequest, err := c.helper.Preprocess(
metadataRequest, requiredPublicKeys, err := c.helper.Preprocess(
ctx,
broadcast.Network,
broadcast.Intent,
Expand All @@ -202,10 +203,25 @@ func (c *Coordinator) createTransaction(
return nil, "", fmt.Errorf("%w: unable to preprocess", err)
}

publicKeys := make([]*types.PublicKey, len(requiredPublicKeys))
for i, accountIdentifier := range requiredPublicKeys {
keyPair, err := c.helper.GetKey(ctx, dbTx, accountIdentifier.Address)
if err != nil {
return nil, "", fmt.Errorf(
"%w: unable to find key for address %s",
err,
accountIdentifier.Address,
)
}

publicKeys[i] = keyPair.PublicKey
}

requiredMetadata, err := c.helper.Metadata(
ctx,
broadcast.Network,
metadataRequest,
publicKeys,
)
if err != nil {
return nil, "", fmt.Errorf("%w: unable to construct metadata", err)
Expand All @@ -216,6 +232,7 @@ func (c *Coordinator) createTransaction(
broadcast.Network,
broadcast.Intent,
requiredMetadata,
publicKeys,
)
if err != nil {
return nil, "", fmt.Errorf("%w: unable to construct payloads", err)
Expand Down Expand Up @@ -483,7 +500,11 @@ func (c *Coordinator) Process(
var transactionCreated *types.TransactionIdentifier
if broadcast != nil {
// Construct Transaction
transactionIdentifier, networkTransaction, err := c.createTransaction(ctx, broadcast)
transactionIdentifier, networkTransaction, err := c.createTransaction(
ctx,
dbTx,
broadcast,
)
if err != nil {
return fmt.Errorf("%w: unable to create transaction", err)
}
Expand Down
63 changes: 61 additions & 2 deletions constructor/coordinator/coordinator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

"github.com/coinbase/rosetta-sdk-go/asserter"
"github.com/coinbase/rosetta-sdk-go/constructor/job"
"github.com/coinbase/rosetta-sdk-go/keys"
mocks "github.com/coinbase/rosetta-sdk-go/mocks/constructor/coordinator"
"github.com/coinbase/rosetta-sdk-go/parser"
"github.com/coinbase/rosetta-sdk-go/storage"
Expand Down Expand Up @@ -546,7 +547,7 @@ func TestProcess(t *testing.T) {
map[string]interface{}{
"test": "works",
},
).Return(metadataOptions, nil).Once()
).Return(metadataOptions, nil, nil).Once()
fetchedMetadata := map[string]interface{}{
"tx_meta": "help",
}
Expand All @@ -555,6 +556,7 @@ func TestProcess(t *testing.T) {
ctx,
network,
metadataOptions,
[]*types.PublicKey{},
).Return(fetchedMetadata, nil).Once()

unsignedTx := "unsigned transaction"
Expand All @@ -571,6 +573,7 @@ func TestProcess(t *testing.T) {
network,
ops,
fetchedMetadata,
[]*types.PublicKey{},
).Return(unsignedTx, signingPayloads, nil).Once()
helper.On(
"Parse",
Expand Down Expand Up @@ -950,7 +953,43 @@ func TestProcess_Failed(t *testing.T) {
map[string]interface{}{
"test": "works",
},
).Return(metadataOptions, nil).Once()
).Return(metadataOptions, []*types.AccountIdentifier{
{
Address: "hello",
},
{
Address: "hello2",
},
}, nil).Once()
helper.On(
"GetKey",
ctx,
dbTx,
"hello",
).Return(
&keys.KeyPair{
PublicKey: &types.PublicKey{
Bytes: []byte("hello"),
CurveType: types.Secp256k1,
},
},
nil,
).Once()
helper.On(
"GetKey",
ctx,
dbTx,
"hello2",
).Return(
&keys.KeyPair{
PublicKey: &types.PublicKey{
Bytes: []byte("hello2"),
CurveType: types.Edwards25519,
},
},
nil,
).Once()

fetchedMetadata := map[string]interface{}{
"tx_meta": "help",
}
Expand All @@ -959,6 +998,16 @@ func TestProcess_Failed(t *testing.T) {
ctx,
network,
metadataOptions,
[]*types.PublicKey{
{
Bytes: []byte("hello"),
CurveType: types.Secp256k1,
},
{
Bytes: []byte("hello2"),
CurveType: types.Edwards25519,
},
},
).Return(fetchedMetadata, nil).Once()

unsignedTx := "unsigned transaction"
Expand All @@ -975,6 +1024,16 @@ func TestProcess_Failed(t *testing.T) {
network,
ops,
fetchedMetadata,
[]*types.PublicKey{
{
Bytes: []byte("hello"),
CurveType: types.Secp256k1,
},
{
Bytes: []byte("hello2"),
CurveType: types.Edwards25519,
},
},
).Return(unsignedTx, signingPayloads, nil).Once()
helper.On(
"Parse",
Expand Down
12 changes: 11 additions & 1 deletion constructor/coordinator/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,14 @@ type Helper interface {
*keys.KeyPair,
) error

// GetKey is called to get the *types.KeyPair
// associated with an address.
GetKey(
context.Context,
storage.DatabaseTransaction,
string, // address
) (*keys.KeyPair, error)

// AllAddresses returns a slice of all known addresses.
AllAddresses(
context.Context,
Expand Down Expand Up @@ -119,14 +127,15 @@ type Helper interface {
*types.NetworkIdentifier,
[]*types.Operation,
map[string]interface{},
) (map[string]interface{}, error)
) (map[string]interface{}, []*types.AccountIdentifier, error)

// Metadata calls the /construction/metadata endpoint
// using the online node.
Metadata(
context.Context,
*types.NetworkIdentifier,
map[string]interface{},
[]*types.PublicKey,
) (map[string]interface{}, error)

// Payloads calls the /construction/payloads endpoint
Expand All @@ -136,6 +145,7 @@ type Helper interface {
*types.NetworkIdentifier,
[]*types.Operation,
map[string]interface{},
[]*types.PublicKey,
) (string, []*types.SigningPayload, error)

// Parse calls the /construction/parse endpoint
Expand Down
12 changes: 8 additions & 4 deletions fetcher/construction.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,13 @@ func (f *Fetcher) ConstructionMetadata(
ctx context.Context,
network *types.NetworkIdentifier,
options map[string]interface{},
publicKeys []*types.PublicKey,
) (map[string]interface{}, *Error) {
metadata, clientErr, err := f.rosettaClient.ConstructionAPI.ConstructionMetadata(ctx,
&types.ConstructionMetadataRequest{
NetworkIdentifier: network,
Options: options,
PublicKeys: publicKeys,
},
)
if err != nil {
Expand Down Expand Up @@ -209,12 +211,14 @@ func (f *Fetcher) ConstructionPayloads(
network *types.NetworkIdentifier,
operations []*types.Operation,
metadata map[string]interface{},
publicKeys []*types.PublicKey,
) (string, []*types.SigningPayload, *Error) {
response, clientErr, err := f.rosettaClient.ConstructionAPI.ConstructionPayloads(ctx,
&types.ConstructionPayloadsRequest{
NetworkIdentifier: network,
Operations: operations,
Metadata: metadata,
PublicKeys: publicKeys,
},
)

Expand Down Expand Up @@ -248,7 +252,7 @@ func (f *Fetcher) ConstructionPreprocess(
network *types.NetworkIdentifier,
operations []*types.Operation,
metadata map[string]interface{},
) (map[string]interface{}, *Error) {
) (map[string]interface{}, []*types.AccountIdentifier, *Error) {
response, clientErr, err := f.rosettaClient.ConstructionAPI.ConstructionPreprocess(ctx,
&types.ConstructionPreprocessRequest{
NetworkIdentifier: network,
Expand All @@ -262,17 +266,17 @@ func (f *Fetcher) ConstructionPreprocess(
Err: fmt.Errorf("%w: /construction/preprocess %s", ErrRequestFailed, err.Error()),
ClientErr: clientErr,
}
return nil, fetcherErr
return nil, nil, fetcherErr
}

if err := asserter.ConstructionPreprocessResponse(response); err != nil {
fetcherErr := &Error{
Err: fmt.Errorf("%w: /construction/preprocess %s", ErrAssertionFailed, err.Error()),
}
return nil, fetcherErr
return nil, nil, fetcherErr
}

return response.Options, nil
return response.Options, response.RequiredPublicKeys, nil
}

// ConstructionSubmit returns the validated response
Expand Down
Loading

0 comments on commit 701531d

Please sign in to comment.