-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implemented rpc server method GetRawTransaction #135
Changes from 8 commits
41e27d7
79f41f9
a837151
c280890
30d0a4a
6540cf8
ba3393e
36b69e4
df11e05
42590dc
38528c5
9b91af1
04a25fe
5bff6c4
974e986
087ea47
4b4822a
94ac1d3
5b9f828
da3f83f
a9d07e8
a8328ff
18b6b35
b576289
61b8e96
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,8 +4,11 @@ import ( | |
"fmt" | ||
"io/ioutil" | ||
"os" | ||
"sync" | ||
"time" | ||
|
||
"github.com/CityOfZion/neo-go/pkg/core/transaction" | ||
"github.com/CityOfZion/neo-go/pkg/util" | ||
"github.com/go-yaml/yaml" | ||
"github.com/pkg/errors" | ||
) | ||
|
@@ -27,6 +30,10 @@ var ( | |
// BuildTime the time and date the current version of the node built, | ||
// set at build time. | ||
BuildTime string | ||
|
||
// ConfigDefault is the Config which is defined in the Load method. | ||
configDefault *Config | ||
mu sync.Mutex | ||
) | ||
|
||
type ( | ||
|
@@ -104,17 +111,49 @@ func Load(path string, netMode NetMode) (Config, error) { | |
return Config{}, errors.Wrap(err, "Unable to read config") | ||
} | ||
|
||
config := Config{ | ||
config := &Config{ | ||
ProtocolConfiguration: ProtocolConfiguration{ | ||
SystemFee: SystemFee{}, | ||
}, | ||
ApplicationConfiguration: ApplicationConfiguration{}, | ||
} | ||
|
||
err = yaml.Unmarshal(configData, &config) | ||
setConfig(config) | ||
|
||
err = yaml.Unmarshal(configData, &configDefault) | ||
if err != nil { | ||
return Config{}, errors.Wrap(err, "Problem unmarshaling config json data") | ||
} | ||
|
||
return config, nil | ||
return *configDefault, nil | ||
} | ||
|
||
func setConfig(cfg *Config) { | ||
mu.Lock() | ||
configDefault = cfg | ||
mu.Unlock() | ||
} | ||
|
||
// GetConfig returns a single instance of configDefault. | ||
func GetConfig() *Config { | ||
if configDefault == nil { | ||
panic("configDefault is not available. Please load a configuration file.") | ||
} | ||
return configDefault | ||
} | ||
|
||
// TryGetValue returns the system fee base on transaction type. | ||
func (s SystemFee) TryGetValue(txType transaction.TXType) util.Fixed8 { | ||
switch txType { | ||
case transaction.EnrollmentType: | ||
return util.NewFixed8(s.EnrollmentTransaction) | ||
case transaction.IssueType: | ||
return util.NewFixed8(s.IssueTransaction) | ||
case transaction.PublishType: | ||
return util.NewFixed8(s.PublishTransaction) | ||
case transaction.RegisterType: | ||
return util.NewFixed8(s.RegisterTransaction) | ||
default: | ||
return util.NewFixed8(0) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we must fix // NewFixed8 return a new Fixed8 type multiplied by decimals.
func NewFixed8(val int64) Fixed8 {
return Fixed8(decimals * val)
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. or mb to: // NewFixed8 return a new Fixed8 type multiplied by decimals.
func NewFixed8(val float64) Fixed8 {
return Fixed8(int64(decimals * val))
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. see there |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ import ( | |
"bytes" | ||
"encoding/binary" | ||
"fmt" | ||
"sync" | ||
"sync/atomic" | ||
"time" | ||
|
||
|
@@ -25,6 +26,10 @@ var ( | |
genAmount = []int{8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} | ||
decrementInterval = 2000000 | ||
persistInterval = 1 * time.Second | ||
|
||
// BlockchainDefault is the Blockchain which is defined in the NewBlockchain method. | ||
blockchainDefault *Blockchain | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't use global variables |
||
mu sync.Mutex | ||
) | ||
|
||
// Blockchain represents the blockchain. | ||
|
@@ -69,16 +74,30 @@ func NewBlockchain(s storage.Store, cfg config.ProtocolConfiguration) (*Blockcha | |
blockCache: NewCache(), | ||
verifyBlocks: false, | ||
} | ||
go bc.run() | ||
|
||
if err := bc.init(); err != nil { | ||
setBlockChain(bc) | ||
|
||
go blockchainDefault.run() | ||
if err := blockchainDefault.init(); err != nil { | ||
return nil, err | ||
} | ||
|
||
return bc, nil | ||
return blockchainDefault, nil | ||
} | ||
|
||
// GetBlockchain returns the blockchainDefault. | ||
func GetBlockchain() *Blockchain { | ||
return blockchainDefault | ||
} | ||
|
||
// setBlockChain sets the blockchainDefault. | ||
func setBlockChain(bc *Blockchain) { | ||
mu.Lock() | ||
blockchainDefault = bc | ||
mu.Unlock() | ||
} | ||
|
||
// GetBlockchainLevelDB returns blockchain based on configuration | ||
// NewBlockchainLevelDB returns LevelDB blockchain based on configuration | ||
func NewBlockchainLevelDB(cfg config.Config) (*Blockchain, error) { | ||
store, err := storage.NewLevelDBStore( | ||
cfg.ApplicationConfiguration.DataDirectoryPath, | ||
|
@@ -148,7 +167,7 @@ func (bc *Blockchain) init() error { | |
headers := make([]*Header, 0) | ||
|
||
for hash != targetHash { | ||
header, err := bc.getHeader(hash) | ||
header, err := bc.GetHeader(hash) | ||
if err != nil { | ||
return fmt.Errorf("could not get header %s: %s", hash, err) | ||
} | ||
|
@@ -483,7 +502,7 @@ func (bc *Blockchain) GetBlock(hash util.Uint256) (*Block, error) { | |
return block, nil | ||
} | ||
|
||
func (bc *Blockchain) getHeader(hash util.Uint256) (*Header, error) { | ||
func (bc *Blockchain) GetHeader(hash util.Uint256) (*Header, error) { | ||
b, err := bc.Get(storage.AppendPrefix(storage.DataBlock, hash.BytesReverse())) | ||
if err != nil { | ||
return nil, err | ||
|
@@ -504,7 +523,7 @@ func (bc *Blockchain) HasTransaction(hash util.Uint256) bool { | |
// HasBlock return true if the blockchain contains the given | ||
// block hash. | ||
func (bc *Blockchain) HasBlock(hash util.Uint256) bool { | ||
if header, err := bc.getHeader(hash); err == nil { | ||
if header, err := bc.GetHeader(hash); err == nil { | ||
return header.Index <= bc.BlockHeight() | ||
} | ||
return false | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -77,15 +77,15 @@ func TestGetHeader(t *testing.T) { | |
assert.Nil(t, err) | ||
|
||
hash := block.Hash() | ||
header, err := bc.getHeader(hash) | ||
header, err := bc.GetHeader(hash) | ||
if err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. require.NoError(t, err) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
t.Fatal(err) | ||
} | ||
assert.Equal(t, block.Header(), header) | ||
|
||
block = newBlock(2) | ||
hash = block.Hash() | ||
_, err = bc.getHeader(block.Hash()) | ||
_, err = bc.GetHeader(block.Hash()) | ||
assert.NotNil(t, err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. replace with |
||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package core | ||
|
||
import ( | ||
"github.com/CityOfZion/neo-go/config" | ||
"github.com/CityOfZion/neo-go/pkg/core/transaction" | ||
"github.com/CityOfZion/neo-go/pkg/util" | ||
) | ||
|
||
// References returns a map with input prevHash as key (util.Uint256) | ||
// and transaction output as value from a transaction t. | ||
// @TODO: unfortunately we couldn't attach this method to the Transaction struct in the | ||
// transaction package because of a import cycle problem. Perhaps we should think to re-design | ||
// the code base to avoid this situation. | ||
func References(t *transaction.Transaction) map[util.Uint256]*transaction.Output { | ||
references := make(map[util.Uint256]*transaction.Output) | ||
|
||
for prevHash, inputs := range t.GroupInputsByPrevHash() { | ||
bc := GetBlockchain() | ||
if tx, _, err := bc.GetTransaction(prevHash); err != nil { | ||
tx = nil | ||
} else if tx != nil { | ||
for _, in := range inputs { | ||
references[in.PrevHash] = tx.Outputs[in.PrevIndex] | ||
} | ||
} else { | ||
references = nil | ||
} | ||
} | ||
return references | ||
} | ||
|
||
// FeePerByte returns network fee divided by the size of the transaction | ||
func FeePerByte(t *transaction.Transaction) util.Fixed8 { | ||
return NetworkFee(t).Div(int64(t.Size())) | ||
} | ||
|
||
// NetworkFee returns network fee | ||
func NetworkFee(t *transaction.Transaction) util.Fixed8 { | ||
inputAmount := util.NewFixed8(0) | ||
for _, txOutput := range References(t) { | ||
if txOutput.AssetID == utilityTokenTX().Hash() { | ||
inputAmount.Add(txOutput.Amount) | ||
} | ||
} | ||
|
||
outputAmount := util.NewFixed8(0) | ||
for _, txOutput := range t.Outputs { | ||
if txOutput.AssetID == utilityTokenTX().Hash() { | ||
outputAmount.Add(txOutput.Amount) | ||
} | ||
} | ||
|
||
return inputAmount.Sub(outputAmount).Sub(SystemFee(t)) | ||
} | ||
|
||
// SystemFee returns system fee | ||
func SystemFee(t *transaction.Transaction) util.Fixed8 { | ||
return config.GetConfig().ProtocolConfiguration.SystemFee.TryGetValue(t.Type) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package core | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/CityOfZion/neo-go/config" | ||
"github.com/CityOfZion/neo-go/pkg/core/transaction" | ||
"github.com/CityOfZion/neo-go/pkg/util" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestSize(t *testing.T) { | ||
txID := "f999c36145a41306c846ea80290416143e8e856559818065be3f4e143c60e43a" | ||
tx := getTestTransaction(txID, t) | ||
|
||
assert.Equal(t, 283, tx.Size()) | ||
assert.Equal(t, 22, util.GetVarSize(tx.Attributes)) | ||
assert.Equal(t, 35, util.GetVarSize(tx.Inputs)) | ||
assert.Equal(t, 121, util.GetVarSize(tx.Outputs)) | ||
assert.Equal(t, 103, util.GetVarSize(tx.Scripts)) | ||
} | ||
|
||
func getTestBlockchain(t *testing.T) *Blockchain { | ||
net := config.ModeUnitTestNet | ||
configPath := "../../config" | ||
cfg, err := config.Load(configPath, net) | ||
if err != nil { | ||
t.Fatal("could not create levelDB chain", err) | ||
} | ||
|
||
// adjust datadirectory to point to the correct folder | ||
cfg.ApplicationConfiguration.DataDirectoryPath = "../rpc/chains/unit_testnet" | ||
chain, err := NewBlockchainLevelDB(cfg) | ||
if err != nil { | ||
t.Fatal("could not create levelDB chain", err) | ||
} | ||
|
||
return chain | ||
} | ||
|
||
func getTestTransaction(txID string, t *testing.T) *transaction.Transaction { | ||
chain := getTestBlockchain(t) | ||
|
||
txHash, err := util.Uint256DecodeString(txID) | ||
if err != nil { | ||
t.Fatalf("could not decode string %s to Uint256: err =%s", txID, err) | ||
} | ||
|
||
tx, _, err := chain.GetTransaction(txHash) | ||
if err != nil { | ||
t.Fatalf("Could not get transaction with hash=%s: err=%s", txHash, err) | ||
} | ||
return tx | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,3 +47,57 @@ const ( | |
Remark14 AttrUsage = 0xfe | ||
Remark15 AttrUsage = 0xff | ||
) | ||
|
||
// String implements the stringer interface. | ||
func (attr AttrUsage) String() string { | ||
attrLookup := map[AttrUsage]string{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. mb we can move that to global? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
ContractHash: "ContractHash", | ||
ECDH02: "ECDH02", | ||
ECDH03: "ECDH03", | ||
Script: "Script", | ||
Vote: "Vote", | ||
CertURL: "CertURL", | ||
DescriptionURL: "DescriptionURL", | ||
Description: "Description", | ||
|
||
Hash1: "Hash1", | ||
Hash2: "Hash2", | ||
Hash3: "Hash3", | ||
Hash4: "Hash4", | ||
Hash5: "Hash5", | ||
Hash6: "Hash6", | ||
Hash7: "Hash7", | ||
Hash8: "Hash8", | ||
Hash9: "Hash9", | ||
Hash10: "Hash10", | ||
Hash11: "Hash11", | ||
Hash12: "Hash12", | ||
Hash13: "Hash13", | ||
Hash14: "Hash14", | ||
Hash15: "Hash15", | ||
|
||
Remark: "Remark", | ||
Remark1: "Remark1", | ||
Remark2: "Remark2", | ||
Remark3: "Remark3", | ||
Remark4: "Remark4", | ||
Remark5: "Remark5", | ||
Remark6: "Remark6", | ||
Remark7: "Remark7", | ||
Remark8: "Remark8", | ||
Remark9: "Remark9", | ||
Remark10: "Remark10", | ||
Remark11: "Remark11", | ||
Remark12: "Remark12", | ||
Remark13: "Remark13", | ||
Remark14: "Remark14", | ||
Remark15: "Remark15", | ||
} | ||
|
||
v, ok := attrLookup[attr] | ||
if !ok { | ||
return "Unkown Attribute" | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if v, ok := attrLookup[attr]; ok {
return v
}
return "Unkown Attribute" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
|
||
return v | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't use global variables