diff options
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | cmd/faucet/faucet.go | 2 | ||||
-rw-r--r-- | cmd/geth/accountcmd.go | 45 | ||||
-rw-r--r-- | cmd/swarm/main.go | 8 | ||||
-rw-r--r-- | internal/ethapi/api.go | 23 | ||||
-rw-r--r-- | mobile/common.go | 43 | ||||
-rw-r--r-- | mobile/ethereum.go | 22 | ||||
-rw-r--r-- | p2p/discover/udp.go | 2 | ||||
-rw-r--r-- | swarm/api/config.go | 19 | ||||
-rw-r--r-- | swarm/api/config_test.go | 1 | ||||
-rw-r--r-- | swarm/api/http/server.go | 1 | ||||
-rw-r--r-- | swarm/api/manifest.go | 4 | ||||
-rw-r--r-- | swarm/api/manifest_test.go | 33 | ||||
-rw-r--r-- | swarm/swarm.go | 20 |
14 files changed, 186 insertions, 39 deletions
@@ -84,7 +84,7 @@ $ geth --testnet --fast --cache=512 console ``` The `--fast`, `--cache` flags and `console` subcommand have the exact same meaning as above and they -are equially useful on the testnet too. Please see above for their explanations if you've skipped to +are equally useful on the testnet too. Please see above for their explanations if you've skipped to here. Specifying the `--testnet` flag however will reconfigure your Geth instance a bit: diff --git a/cmd/faucet/faucet.go b/cmd/faucet/faucet.go index f672433ee..c06c4365b 100644 --- a/cmd/faucet/faucet.go +++ b/cmd/faucet/faucet.go @@ -102,7 +102,7 @@ func main() { if amount == 1 { amounts[i] = strings.TrimSuffix(amounts[i], "s") } - // Calcualte the period for th enext tier and format it + // Calculate the period for the next tier and format it period := *minutesFlag * int(math.Pow(3, float64(i))) periods[i] = fmt.Sprintf("%d mins", period) if period%60 == 0 { diff --git a/cmd/geth/accountcmd.go b/cmd/geth/accountcmd.go index 1a3c63da9..5c756e66d 100644 --- a/cmd/geth/accountcmd.go +++ b/cmd/geth/accountcmd.go @@ -31,25 +31,40 @@ import ( var ( walletCommand = cli.Command{ - Name: "wallet", - Usage: "Import Ethereum presale wallets", - Action: utils.MigrateFlags(importWallet), - Category: "ACCOUNT COMMANDS", - Flags: []cli.Flag{ - utils.DataDirFlag, - utils.KeyStoreDirFlag, - utils.PasswordFileFlag, - utils.LightKDFFlag, - }, + Name: "wallet", + Usage: "Manage Ethereum presale wallets", + ArgsUsage: "", + Category: "ACCOUNT COMMANDS", Description: ` - geth wallet [options] /path/to/my/presale.wallet + geth wallet import /path/to/my/presale.wallet + +will prompt for your password and imports your ether presale account. +It can be used non-interactively with the --password option taking a +passwordfile as argument containing the wallet password in plaintext.`, + Subcommands: []cli.Command{ + { - will prompt for your password and imports your ether presale account. - It can be used non-interactively with the --password option taking a - passwordfile as argument containing the wallet password in plaintext. + Name: "import", + Usage: "Import Ethereum presale wallet", + ArgsUsage: "<keyFile>", + Action: utils.MigrateFlags(importWallet), + Category: "ACCOUNT COMMANDS", + Flags: []cli.Flag{ + utils.DataDirFlag, + utils.KeyStoreDirFlag, + utils.PasswordFileFlag, + utils.LightKDFFlag, + }, + Description: ` + geth wallet [options] /path/to/my/presale.wallet - `, +will prompt for your password and imports your ether presale account. +It can be used non-interactively with the --password option taking a +passwordfile as argument containing the wallet password in plaintext.`, + }, + }, } + accountCommand = cli.Command{ Name: "account", Usage: "Manage accounts", diff --git a/cmd/swarm/main.go b/cmd/swarm/main.go index 26aa3e50f..71149c310 100644 --- a/cmd/swarm/main.go +++ b/cmd/swarm/main.go @@ -67,6 +67,10 @@ var ( Name: "bzzaccount", Usage: "Swarm account key file", } + SwarmListenAddrFlag = cli.StringFlag{ + Name: "httpaddr", + Usage: "Swarm HTTP API listening interface", + } SwarmPortFlag = cli.StringFlag{ Name: "bzzport", Usage: "Swarm local http api port", @@ -249,6 +253,7 @@ Cleans database of corrupted entries. SwarmConfigPathFlag, SwarmSwapEnabledFlag, SwarmSyncEnabledFlag, + SwarmListenAddrFlag, SwarmPortFlag, SwarmAccountFlag, SwarmNetworkIdFlag, @@ -345,6 +350,9 @@ func registerBzzService(ctx *cli.Context, stack *node.Node) { if len(bzzport) > 0 { bzzconfig.Port = bzzport } + if bzzaddr := ctx.GlobalString(SwarmListenAddrFlag.Name); bzzaddr != "" { + bzzconfig.ListenAddr = bzzaddr + } swapEnabled := ctx.GlobalBool(SwarmSwapEnabledFlag.Name) syncEnabled := ctx.GlobalBoolT(SwarmSyncEnabledFlag.Name) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index f9eed8797..62edc695c 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -24,6 +24,7 @@ import ( "fmt" "math/big" "strings" + "sync" "time" "github.com/ethereum/go-ethereum/accounts" @@ -890,6 +891,12 @@ type PublicTransactionPoolAPI struct { b Backend } +// nonceMutex is a global mutex for locking the nonce while a transaction +// is being submitted. This should be used when a nonce has not been provided by the user, +// and we get a nonce from the pools. The mutex prevents the (an identical nonce) from being +// read again during the time that the first transaction is being signed. +var nonceMutex sync.RWMutex + // NewPublicTransactionPoolAPI creates a new RPC service with methods specific for the transaction pool. func NewPublicTransactionPoolAPI(b Backend) *PublicTransactionPoolAPI { return &PublicTransactionPoolAPI{b} @@ -1170,6 +1177,14 @@ func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (c // SendTransaction creates a transaction for the given argument, sign it and submit it to the // transaction pool. func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args SendTxArgs) (common.Hash, error) { + + if args.Nonce == nil { + // We'll need to set nonce from pool, and thus we need to lock here + nonceMutex.Lock() + defer nonceMutex.Unlock() + + } + // Set some sanity defaults and terminate on failure if err := args.setDefaults(ctx, s.b); err != nil { return common.Hash{}, err @@ -1257,6 +1272,14 @@ type SignTransactionResult struct { // The node needs to have the private key of the account corresponding with // the given from address and it needs to be unlocked. func (s *PublicTransactionPoolAPI) SignTransaction(ctx context.Context, args SendTxArgs) (*SignTransactionResult, error) { + + if args.Nonce == nil { + // We'll need to set nonce from pool, and thus we need to lock here + nonceMutex.Lock() + defer nonceMutex.Unlock() + + } + if err := args.setDefaults(ctx, s.b); err != nil { return nil, err } diff --git a/mobile/common.go b/mobile/common.go index 779f22b4e..3090014c5 100644 --- a/mobile/common.go +++ b/mobile/common.go @@ -89,6 +89,18 @@ func (h *Hash) GetHex() string { // Hashes represents a slice of hashes. type Hashes struct{ hashes []common.Hash } +// NewHashes creates a slice of uninitialized Hashes. +func NewHashes(size int) *Hashes { + return &Hashes{ + hashes: make([]common.Hash, size), + } +} + +// NewHashesEmpty creates an empty slice of Hashes values. +func NewHashesEmpty() *Hashes { + return NewHashes(0) +} + // Size returns the number of hashes in the slice. func (h *Hashes) Size() int { return len(h.hashes) @@ -102,6 +114,20 @@ func (h *Hashes) Get(index int) (hash *Hash, _ error) { return &Hash{h.hashes[index]}, nil } +// Set sets the Hash at the given index in the slice. +func (h *Hashes) Set(index int, hash *Hash) error { + if index < 0 || index >= len(h.hashes) { + return errors.New("index out of bounds") + } + h.hashes[index] = hash.hash + return nil +} + +// Append adds a new Hash element to the end of the slice. +func (h *Hashes) Append(hash *Hash) { + h.hashes = append(h.hashes, hash.hash) +} + // Address represents the 20 byte address of an Ethereum account. type Address struct { address common.Address @@ -164,6 +190,18 @@ func (a *Address) GetHex() string { // Addresses represents a slice of addresses. type Addresses struct{ addresses []common.Address } +// NewAddresses creates a slice of uninitialized addresses. +func NewAddresses(size int) *Addresses { + return &Addresses{ + addresses: make([]common.Address, size), + } +} + +// NewAddressesEmpty creates an empty slice of Addresses values. +func NewAddressesEmpty() *Addresses { + return NewAddresses(0) +} + // Size returns the number of addresses in the slice. func (a *Addresses) Size() int { return len(a.addresses) @@ -185,3 +223,8 @@ func (a *Addresses) Set(index int, address *Address) error { a.addresses[index] = address.address return nil } + +// Append adds a new address element to the end of the slice. +func (a *Addresses) Append(address *Address) { + a.addresses = append(a.addresses, address.address) +} diff --git a/mobile/ethereum.go b/mobile/ethereum.go index 94f707a87..30a94dc89 100644 --- a/mobile/ethereum.go +++ b/mobile/ethereum.go @@ -87,6 +87,18 @@ func (p *SyncProgress) GetKnownStates() int64 { return int64(p.progress.KnownS // Topics is a set of topic lists to filter events with. type Topics struct{ topics [][]common.Hash } +// NewTopics creates a slice of uninitialized Topics. +func NewTopics(size int) *Topics { + return &Topics{ + topics: make([][]common.Hash, size), + } +} + +// NewTopicsEmpty creates an empty slice of Topics values. +func NewTopicsEmpty() *Topics { + return NewTopics(0) +} + // Size returns the number of topic lists inside the set func (t *Topics) Size() int { return len(t.topics) @@ -109,6 +121,11 @@ func (t *Topics) Set(index int, topics *Hashes) error { return nil } +// Append adds a new topic list to the end of the slice. +func (t *Topics) Append(topics *Hashes) { + t.topics = append(t.topics, topics.hashes) +} + // FilterQuery contains options for contact log filtering. type FilterQuery struct { query ethereum.FilterQuery @@ -123,3 +140,8 @@ func (fq *FilterQuery) GetFromBlock() *BigInt { return &BigInt{fq.query.FromB func (fq *FilterQuery) GetToBlock() *BigInt { return &BigInt{fq.query.ToBlock} } func (fq *FilterQuery) GetAddresses() *Addresses { return &Addresses{fq.query.Addresses} } func (fq *FilterQuery) GetTopics() *Topics { return &Topics{fq.query.Topics} } + +func (fq *FilterQuery) SetFromBlock(fromBlock *BigInt) { fq.query.FromBlock = fromBlock.bigint } +func (fq *FilterQuery) SetToBlock(toBlock *BigInt) { fq.query.ToBlock = toBlock.bigint } +func (fq *FilterQuery) SetAddresses(addresses *Addresses) { fq.query.Addresses = addresses.addresses } +func (fq *FilterQuery) SetTopics(topics *Topics) { fq.query.Topics = topics.topics } diff --git a/p2p/discover/udp.go b/p2p/discover/udp.go index 93545e7d5..f9eb99ee3 100644 --- a/p2p/discover/udp.go +++ b/p2p/discover/udp.go @@ -224,7 +224,7 @@ func ListenUDP(priv *ecdsa.PrivateKey, laddr string, natm nat.Interface, nodeDBP if err != nil { return nil, err } - log.Debug("UDP listener up", "self", tab.self) + log.Info("UDP listener up", "self", tab.self) return tab, nil } diff --git a/swarm/api/config.go b/swarm/api/config.go index 23a855500..647c153ed 100644 --- a/swarm/api/config.go +++ b/swarm/api/config.go @@ -32,7 +32,8 @@ import ( ) const ( - port = "8500" + DefaultHTTPListenAddr = "127.0.0.1" + DefaultHTTPPort = "8500" ) var ( @@ -48,12 +49,13 @@ type Config struct { *network.HiveParams Swap *swap.SwapParams *network.SyncParams - Path string - Port string - PublicKey string - BzzKey string - EnsRoot common.Address - NetworkId uint64 + Path string + ListenAddr string + Port string + PublicKey string + BzzKey string + EnsRoot common.Address + NetworkId uint64 } // config is agnostic to where private key is coming from @@ -76,7 +78,8 @@ func NewConfig(path string, contract common.Address, prvKey *ecdsa.PrivateKey, n HiveParams: network.NewHiveParams(dirpath), ChunkerParams: storage.NewChunkerParams(), StoreParams: storage.NewStoreParams(dirpath), - Port: port, + ListenAddr: DefaultHTTPListenAddr, + Port: DefaultHTTPPort, Path: dirpath, Swap: swap.DefaultSwapParams(contract, prvKey), PublicKey: pubkeyhex, diff --git a/swarm/api/config_test.go b/swarm/api/config_test.go index 2f40098a3..6b5cea915 100644 --- a/swarm/api/config_test.go +++ b/swarm/api/config_test.go @@ -80,6 +80,7 @@ var ( false ], "Path": "TMPDIR", + "ListenAddr": "127.0.0.1", "Port": "8500", "PublicKey": "0x045f5cfd26692e48d0017d380349bcf50982488bc11b5145f3ddf88b24924299048450542d43527fbe29a5cb32f38d62755393ac002e6bfdd71b8d7ba725ecd7a3", "BzzKey": "0xe861964402c0b78e2d44098329b8545726f215afa737d803714a4338552fcb81", diff --git a/swarm/api/http/server.go b/swarm/api/http/server.go index 849b9e10f..5f64f971b 100644 --- a/swarm/api/http/server.go +++ b/swarm/api/http/server.go @@ -69,7 +69,6 @@ func StartHttpServer(api *api.Api, config *ServerConfig) { hdlr := c.Handler(NewServer(api)) go http.ListenAndServe(config.Addr, hdlr) - log.Info(fmt.Sprintf("Swarm HTTP proxy started on localhost:%s", config.Addr)) } func NewServer(api *api.Api) *Server { diff --git a/swarm/api/manifest.go b/swarm/api/manifest.go index dbaaf4bff..e251620a7 100644 --- a/swarm/api/manifest.go +++ b/swarm/api/manifest.go @@ -237,12 +237,12 @@ func (self *manifestTrie) addEntry(entry *manifestTrieEntry, quitC chan bool) { } b := byte(entry.Path[0]) - if (self.entries[b] == nil) || (self.entries[b].Path == entry.Path) { + oldentry := self.entries[b] + if (oldentry == nil) || (oldentry.Path == entry.Path && oldentry.ContentType != ManifestType) { self.entries[b] = entry return } - oldentry := self.entries[b] cpl := 0 for (len(entry.Path) > cpl) && (len(oldentry.Path) > cpl) && (entry.Path[cpl] == oldentry.Path[cpl]) { cpl++ diff --git a/swarm/api/manifest_test.go b/swarm/api/manifest_test.go index 20b8117c6..0208848a3 100644 --- a/swarm/api/manifest_test.go +++ b/swarm/api/manifest_test.go @@ -18,6 +18,8 @@ package api import ( // "encoding/json" + "bytes" + "encoding/json" "fmt" "io" "strings" @@ -78,3 +80,34 @@ func TestGetEntry(t *testing.T) { func TestDeleteEntry(t *testing.T) { } + +// TestAddFileWithManifestPath tests that adding an entry at a path which +// already exists as a manifest just adds the entry to the manifest rather +// than replacing the manifest with the entry +func TestAddFileWithManifestPath(t *testing.T) { + // create a manifest containing "ab" and "ac" + manifest, _ := json.Marshal(&Manifest{ + Entries: []ManifestEntry{ + {Path: "ab", Hash: "ab"}, + {Path: "ac", Hash: "ac"}, + }, + }) + reader := &storage.LazyTestSectionReader{ + SectionReader: io.NewSectionReader(bytes.NewReader(manifest), 0, int64(len(manifest))), + } + trie, err := readManifest(reader, nil, nil, nil) + if err != nil { + t.Fatal(err) + } + checkEntry(t, "ab", "ab", trie) + checkEntry(t, "ac", "ac", trie) + + // now add path "a" and check we can still get "ab" and "ac" + entry := &manifestTrieEntry{} + entry.Path = "a" + entry.Hash = "a" + trie.addEntry(entry, nil) + checkEntry(t, "ab", "ab", trie) + checkEntry(t, "ac", "ac", trie) + checkEntry(t, "a", "a", trie) +} diff --git a/swarm/swarm.go b/swarm/swarm.go index 442e68d51..4f93a30b7 100644 --- a/swarm/swarm.go +++ b/swarm/swarm.go @@ -21,6 +21,7 @@ import ( "context" "crypto/ecdsa" "fmt" + "net" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -166,13 +167,13 @@ Start is called when the stack is started * TODO: start subservices like sword, swear, swarmdns */ // implements the node.Service interface -func (self *Swarm) Start(net *p2p.Server) error { +func (self *Swarm) Start(srv *p2p.Server) error { connectPeer := func(url string) error { node, err := discover.ParseNode(url) if err != nil { return fmt.Errorf("invalid node URL: %v", err) } - net.AddPeer(node) + srv.AddPeer(node) return nil } // set chequebook @@ -189,8 +190,8 @@ func (self *Swarm) Start(net *p2p.Server) error { log.Warn(fmt.Sprintf("Starting Swarm service")) self.hive.Start( - discover.PubkeyID(&net.PrivateKey.PublicKey), - func() string { return net.ListenAddr }, + discover.PubkeyID(&srv.PrivateKey.PublicKey), + func() string { return srv.ListenAddr }, connectPeer, ) log.Info(fmt.Sprintf("Swarm network started on bzz address: %v", self.hive.Addr())) @@ -200,17 +201,16 @@ func (self *Swarm) Start(net *p2p.Server) error { // start swarm http proxy server if self.config.Port != "" { - addr := ":" + self.config.Port + addr := net.JoinHostPort(self.config.ListenAddr, self.config.Port) go httpapi.StartHttpServer(self.api, &httpapi.ServerConfig{ Addr: addr, CorsString: self.corsString, }) - } - - log.Debug(fmt.Sprintf("Swarm http proxy started on port: %v", self.config.Port)) + log.Info(fmt.Sprintf("Swarm http proxy started on %v", addr)) - if self.corsString != "" { - log.Debug(fmt.Sprintf("Swarm http proxy started with corsdomain: %v", self.corsString)) + if self.corsString != "" { + log.Debug(fmt.Sprintf("Swarm http proxy started with corsdomain: %v", self.corsString)) + } } return nil |