-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[NOD-303] Implement get transaction by id for api server (#391)
* [NOD-303] Implement get transaction by id for api server * [NOD-303] Make routeParamTxID a constant * [NOD-303] Change database is not current error. * [NOD-303] Add ID to TransactionInput and TransactionOutput models * [NOD-303] Change transactions_outputs table name to transaction_outputs and transactions_inputs to transaction_inputs * [NOD-303] Add json annotations to transaction response types * [NOD-303] Split server package * [NOD-303] Add GetTransactionByHashHandler * [NOD-303] Add comments to exported functions and variables * [NOD-303] Put response types in a separate file * [NOD-303] Rename functions
- Loading branch information
1 parent
7521545
commit ae25ec2
Showing
36 changed files
with
541 additions
and
122 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package controllers | ||
|
||
import ( | ||
"encoding/hex" | ||
"github.com/daglabs/btcd/apiserver/models" | ||
) | ||
|
||
type transactionResponse struct { | ||
TransactionHash string `json:"transactionHash"` | ||
TransactionID string `json:"transactionId"` | ||
AcceptingBlockHash string `json:"acceptingBlockHash,omitempty"` | ||
AcceptingBlockBlueScore uint64 `json:"acceptingBlockBlueScore,omitempty"` | ||
SubnetworkID string `json:"subnetworkId"` | ||
LockTime uint64 `json:"lockTime"` | ||
Gas uint64 `json:"gas,omitempty"` | ||
PayloadHash string `json:"payloadHash,omitempty"` | ||
Payload string `json:"payload,omitempty"` | ||
Inputs []*transactionInputResponse `json:"inputs"` | ||
Outputs []*transactionOutputResponse `json:"outputs"` | ||
Mass uint64 `json:"mass"` | ||
} | ||
|
||
type transactionOutputResponse struct { | ||
TransactionID string `json:"transactionId,omitempty"` | ||
Value uint64 `json:"value"` | ||
PkScript string `json:"pkScript"` | ||
Address string `json:"address"` | ||
} | ||
|
||
type transactionInputResponse struct { | ||
TransactionID string `json:"transactionId,omitempty"` | ||
PreviousTransactionID string `json:"previousTransactionId"` | ||
PreviousTransactionOutputIndex uint32 `json:"previousTransactionOutputIndex"` | ||
SignatureScript string `json:"signatureScript"` | ||
Sequence uint64 `json:"sequence"` | ||
} | ||
|
||
func convertTxModelToTxResponse(tx *models.Transaction) *transactionResponse { | ||
txRes := &transactionResponse{ | ||
TransactionHash: tx.TransactionHash, | ||
TransactionID: tx.TransactionID, | ||
AcceptingBlockHash: tx.AcceptingBlock.BlockHash, | ||
AcceptingBlockBlueScore: tx.AcceptingBlock.BlueScore, | ||
SubnetworkID: tx.Subnetwork.SubnetworkID, | ||
LockTime: tx.LockTime, | ||
Gas: tx.Gas, | ||
PayloadHash: tx.PayloadHash, | ||
Payload: hex.EncodeToString(tx.Payload), | ||
Inputs: make([]*transactionInputResponse, len(tx.TransactionOutputs)), | ||
Outputs: make([]*transactionOutputResponse, len(tx.TransactionInputs)), | ||
Mass: tx.Mass, | ||
} | ||
for i, txOut := range tx.TransactionOutputs { | ||
txRes.Outputs[i] = &transactionOutputResponse{ | ||
Value: txOut.Value, | ||
PkScript: hex.EncodeToString(txOut.PkScript), | ||
Address: "", // TODO: Fill it when there's an addrindex in the DB. | ||
} | ||
} | ||
for i, txIn := range tx.TransactionInputs { | ||
txRes.Inputs[i] = &transactionInputResponse{ | ||
PreviousTransactionID: txIn.TransactionOutput.Transaction.TransactionID, | ||
PreviousTransactionOutputIndex: txIn.TransactionOutput.Index, | ||
SignatureScript: hex.EncodeToString(txIn.SignatureScript), | ||
Sequence: txIn.Sequence, | ||
} | ||
} | ||
return txRes | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package controllers | ||
|
||
import ( | ||
"fmt" | ||
"github.com/daglabs/btcd/apiserver/database" | ||
"github.com/daglabs/btcd/apiserver/models" | ||
"github.com/daglabs/btcd/apiserver/utils" | ||
"github.com/daglabs/btcd/util/daghash" | ||
"github.com/jinzhu/gorm" | ||
"net/http" | ||
) | ||
|
||
// GetTransactionByIDHandler returns a transaction by a given transaction ID. | ||
func GetTransactionByIDHandler(txID string) (interface{}, *utils.HandlerError) { | ||
if len(txID) != daghash.TxIDSize*2 { | ||
return nil, utils.NewHandlerError(http.StatusUnprocessableEntity, fmt.Sprintf("The given txid is not a hex-encoded %d-byte hash.", daghash.TxIDSize)) | ||
} | ||
tx := &models.Transaction{} | ||
db := database.DB.Where("transaction_id = ?", txID) | ||
addTxPreloadedFields(db).First(&tx) | ||
if tx.ID == 0 { | ||
return nil, utils.NewHandlerError(http.StatusNotFound, "No transaction with the given txid was found.") | ||
} | ||
return convertTxModelToTxResponse(tx), nil | ||
} | ||
|
||
// GetTransactionByHashHandler returns a transaction by a given transaction hash. | ||
func GetTransactionByHashHandler(txHash string) (interface{}, *utils.HandlerError) { | ||
if len(txHash) != daghash.HashSize*2 { | ||
return nil, utils.NewHandlerError(http.StatusUnprocessableEntity, fmt.Sprintf("The given txhash is not a hex-encoded %d-byte hash.", daghash.HashSize)) | ||
} | ||
tx := &models.Transaction{} | ||
db := database.DB.Where("transaction_hash = ?", txHash) | ||
addTxPreloadedFields(db).First(&tx) | ||
if tx.ID == 0 { | ||
return nil, utils.NewHandlerError(http.StatusNotFound, "No transaction with the given txhash was found.") | ||
} | ||
return convertTxModelToTxResponse(tx), nil | ||
} | ||
|
||
func addTxPreloadedFields(db *gorm.DB) *gorm.DB { | ||
return db.Preload("AcceptingBlock"). | ||
Preload("Subnetwork"). | ||
Preload("TransactionOutputs"). | ||
Preload("TransactionInputs.TransactionOutput.Transaction") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package database | ||
|
||
import ( | ||
"fmt" | ||
"github.com/daglabs/btcd/apiserver/config" | ||
"github.com/golang-migrate/migrate/v4/source" | ||
"github.com/jinzhu/gorm" | ||
"os" | ||
|
||
"github.com/golang-migrate/migrate/v4" | ||
) | ||
|
||
// DB is the API server database. | ||
var DB *gorm.DB | ||
|
||
// Connect connects to the database mentioned in | ||
// config variable. | ||
func Connect(cfg *config.Config) error { | ||
connectionString := buildConnectionString(cfg) | ||
isCurrent, err := isCurrent(connectionString) | ||
if err != nil { | ||
return fmt.Errorf("Error checking whether the database is current: %s", err) | ||
} | ||
if !isCurrent { | ||
return fmt.Errorf("Database is not current. Please migrate" + | ||
" the database and start again.") | ||
} | ||
|
||
DB, err = gorm.Open("mysql", connectionString) | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func buildConnectionString(cfg *config.Config) string { | ||
return fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=True", | ||
cfg.DBUser, cfg.DBPassword, cfg.DBAddress, cfg.DBName) | ||
} | ||
|
||
// isCurrent resolves whether the database is on the latest | ||
// version of the schema. | ||
func isCurrent(connectionString string) (bool, error) { | ||
driver, err := source.Open("file://migrations") | ||
if err != nil { | ||
return false, err | ||
} | ||
migrator, err := migrate.NewWithSourceInstance( | ||
"migrations", driver, "mysql://"+connectionString) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
// Get the current version | ||
version, isDirty, err := migrator.Version() | ||
if err == migrate.ErrNilVersion { | ||
return false, nil | ||
} | ||
if err != nil { | ||
return false, err | ||
} | ||
if isDirty { | ||
return false, fmt.Errorf("Database is dirty") | ||
} | ||
|
||
// The database is current if Next returns ErrNotExist | ||
_, err = driver.Next(version) | ||
if pathErr, ok := err.(*os.PathError); ok { | ||
if pathErr.Err == os.ErrNotExist { | ||
return true, nil | ||
} | ||
} | ||
return false, err | ||
} |
1 change: 0 additions & 1 deletion
1
apiserver/db/migrations/000007_create_transactions_outputs_table.down.sql
This file was deleted.
Oops, something went wrong.
1 change: 0 additions & 1 deletion
1
apiserver/db/migrations/000008_create_transactions_inputs_table.down.sql
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
9 changes: 5 additions & 4 deletions
9
...rations/000001_create_blocks_table.up.sql → ...rations/000001_create_blocks_table.up.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions
1
apiserver/migrations/000007_create_transaction_outputs_table.down.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
DROP TABLE `transaction_outputs`; |
2 changes: 1 addition & 1 deletion
2
..._create_transactions_outputs_table.up.sql → ...7_create_transaction_outputs_table.up.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
apiserver/migrations/000008_create_transaction_inputs_table.down.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
DROP TABLE `transaction_inputs`; |
2 changes: 1 addition & 1 deletion
2
...8_create_transactions_inputs_table.up.sql → ...08_create_transaction_inputs_table.up.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.